TreeStream.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klee/Internal/ADT/TreeStream.h"
00011
00012 #include <cassert>
00013 #include <iostream>
00014 #include <iomanip>
00015 #include <fstream>
00016 #include <iterator>
00017 #include <map>
00018
00019 #include <string.h>
00020
00021 using namespace klee;
00022
00024
00025 TreeStreamWriter::TreeStreamWriter(const std::string &_path)
00026 : lastID(0),
00027 bufferCount(0),
00028 path(_path),
00029 output(new std::ofstream(path.c_str(),
00030 std::ios::out | std::ios::binary)),
00031 ids(1) {
00032 if (!output->good()) {
00033 delete output;
00034 output = 0;
00035 }
00036 }
00037
00038 TreeStreamWriter::~TreeStreamWriter() {
00039 flush();
00040 if (output)
00041 delete output;
00042 }
00043
00044 bool TreeStreamWriter::good() {
00045 return !!output;
00046 }
00047
00048 TreeOStream TreeStreamWriter::open() {
00049 return open(TreeOStream(*this, 0));
00050 }
00051
00052 TreeOStream TreeStreamWriter::open(const TreeOStream &os) {
00053 assert(output && os.writer==this);
00054 flushBuffer();
00055 unsigned id = ids++;
00056 output->write(reinterpret_cast<const char*>(&os.id), 4);
00057 unsigned tag = id | (1<<31);
00058 output->write(reinterpret_cast<const char*>(&tag), 4);
00059 return TreeOStream(*this, id);
00060 }
00061
00062 void TreeStreamWriter::write(TreeOStream &os, const char *s, unsigned size) {
00063 #if 1
00064 if (bufferCount &&
00065 (os.id!=lastID || size+bufferCount>bufferSize))
00066 flushBuffer();
00067 if (bufferCount) {
00068 memcpy(&buffer[bufferCount], s, size);
00069 bufferCount += size;
00070 } else if (size<bufferSize) {
00071 lastID = os.id;
00072 memcpy(buffer, s, size);
00073 bufferCount = size;
00074 } else {
00075 output->write(reinterpret_cast<const char*>(&os.id), 4);
00076 output->write(reinterpret_cast<const char*>(&size), 4);
00077 output->write(buffer, size);
00078 }
00079 #else
00080 output->write(reinterpret_cast<const char*>(&os.id), 4);
00081 output->write(reinterpret_cast<const char*>(&size), 4);
00082 output->write(s, size);
00083 #endif
00084 }
00085
00086 void TreeStreamWriter::flushBuffer() {
00087 if (bufferCount) {
00088 output->write(reinterpret_cast<const char*>(&lastID), 4);
00089 output->write(reinterpret_cast<const char*>(&bufferCount), 4);
00090 output->write(buffer, bufferCount);
00091 bufferCount = 0;
00092 }
00093 }
00094
00095 void TreeStreamWriter::flush() {
00096 flushBuffer();
00097 output->flush();
00098 }
00099
00100 void TreeStreamWriter::readStream(TreeStreamID streamID,
00101 std::vector<unsigned char> &out) {
00102 assert(streamID>0 && streamID<ids);
00103 flush();
00104
00105 std::ifstream is(path.c_str(),
00106 std::ios::in | std::ios::binary);
00107 assert(is.good());
00108 #if 0
00109 std::cout << "finding chain for: " << streamID << "\n";
00110 #endif
00111
00112 std::map<unsigned,unsigned> parents;
00113 std::vector<unsigned> roots;
00114 for (;;) {
00115 assert(is.good());
00116 unsigned id;
00117 unsigned tag;
00118 is.read(reinterpret_cast<char*>(&id), 4);
00119 is.read(reinterpret_cast<char*>(&tag), 4);
00120 if (tag&(1<<31)) {
00121 unsigned child = tag ^ (1<<31);
00122
00123 if (child==streamID) {
00124 roots.push_back(child);
00125 while (id) {
00126 roots.push_back(id);
00127 std::map<unsigned, unsigned>::iterator it = parents.find(id);
00128 assert(it!=parents.end());
00129 id = it->second;
00130 }
00131 break;
00132 } else {
00133 parents.insert(std::make_pair(child,id));
00134 }
00135 } else {
00136 unsigned size = tag;
00137 while (size--) is.get();
00138 }
00139 }
00140 #if 0
00141 std::cout << "roots: ";
00142 std::copy(roots.begin(), roots.end(), std::ostream_iterator<unsigned>(std::cout, " "));
00143 std::cout << "\n";
00144 #endif
00145 is.seekg(0, std::ios::beg);
00146 for (;;) {
00147 unsigned id;
00148 unsigned tag;
00149 is.read(reinterpret_cast<char*>(&id), 4);
00150 is.read(reinterpret_cast<char*>(&tag), 4);
00151 if (!is.good()) break;
00152 if (tag&(1<<31)) {
00153 unsigned child = tag ^ (1<<31);
00154 if (id==roots.back() && roots.size()>1 && child==roots[roots.size()-2])
00155 roots.pop_back();
00156 } else {
00157 unsigned size = tag;
00158 if (id==roots.back()) {
00159 while (size--) out.push_back(is.get());
00160 } else {
00161 while (size--) is.get();
00162 }
00163 }
00164 }
00165 }
00166
00168
00169 TreeOStream::TreeOStream()
00170 : writer(0),
00171 id(0) {
00172 }
00173
00174 TreeOStream::TreeOStream(TreeStreamWriter &_writer, unsigned _id)
00175 : writer(&_writer),
00176 id(_id) {
00177 }
00178
00179 TreeOStream::~TreeOStream() {
00180 }
00181
00182 unsigned TreeOStream::getID() const {
00183 assert(writer);
00184 return id;
00185 }
00186
00187 void TreeOStream::write(const char *buffer, unsigned size) {
00188 assert(writer);
00189 writer->write(*this, buffer, size);
00190 }
00191
00192 TreeOStream &TreeOStream::operator<<(const std::string &s) {
00193 assert(writer);
00194 write(s.c_str(), s.size());
00195 return *this;
00196 }
00197
00198 void TreeOStream::flush() {
00199 assert(writer);
00200 writer->flush();
00201 }