TreeStream.cpp

Go to the documentation of this file.
00001 //===-- TreeStream.cpp ----------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
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) { // (os.id==lastID && size+bufferCount<=bufferSize)
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)) { // fork
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)) { // fork
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 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8