00001 #ifndef _COD_HH_ 00002 #define _COD_HH_ 00003 00004 #include <vos/corelibs/vos/vos.hh> 00005 00006 #ifdef HAVE_STDINT_H 00007 # include <stdint.h> 00008 #else 00009 # ifdef HAVE_INTTYPES_H 00010 # include <inttypes.h> 00011 # else 00012 typedef unsigned char uint8_t; 00013 typedef unsigned short int uint16_t; 00014 typedef unsigned long int uint32_t; 00015 # endif 00016 #endif 00017 00018 #if defined(_WIN32) && defined(_MSC_VER) 00019 # ifdef MISC_EXPORTS 00020 # define MISC_API __declspec(dllexport) 00021 # else 00022 # define MISC_API __declspec(dllimport) 00023 # endif 00024 #else 00025 # define MISC_API 00026 #endif 00027 00028 /** COD stands for Compact Object Description. It is a binary file 00029 format for saving and loading Vobjects, and (in the form of the 00030 RemoteCOD subclass) is also used for efficient batch downloads of 00031 the state of many remote vobjects. */ 00032 class MISC_API COD 00033 { 00034 public: 00035 /** An entry in the COD Vobject table */ 00036 struct Entry 00037 { 00038 /** The Vobject itself. */ 00039 Vobject* vobject; 00040 00041 /** The type strings to save. */ 00042 set<string> types; 00043 00044 /** A list of messages which, when replayed, will restore the state 00045 of this Vobject. */ 00046 MessageBlock* mb; 00047 00048 /** For Remote CODs: the position of this object on the 00049 @em remote site. */ 00050 int pos; 00051 00052 /** Should this vobject's child table be written out? */ 00053 bool savechildren; 00054 }; 00055 00056 protected: 00057 struct PCR 00058 { 00059 string context; 00060 string child; 00061 }; 00062 00063 iostream* f; 00064 LocalSite& ls; 00065 00066 map<string, Entry*> vobjectTable; 00067 deque<Entry*> vobjectorder; 00068 00069 unsigned int offset; 00070 unsigned int buffersize; 00071 unsigned char* buffer; 00072 00073 public: 00074 class eof : public runtime_error { 00075 public: 00076 eof() : runtime_error("COD end of file") { }; 00077 }; 00078 00079 00080 protected: 00081 void write(const char* data, unsigned int size); 00082 void write(const unsigned char* data, unsigned int size); 00083 00084 void read(char* data, unsigned int size); 00085 void read(unsigned char* data, unsigned int size); 00086 00087 virtual int writeObjectDesc(Entry* v, bool doWrite = true); 00088 virtual int writeObjectChildren(Vobject* v, bool doWrite = true); 00089 00090 virtual string readStr(); 00091 virtual unsigned short int readShort(); 00092 virtual unsigned long readLong(); 00093 virtual void readObjectDesc(string& name, long& pos, deque<string>& types, MessageBlock& mb); 00094 virtual void readObjectChildren(string& parent, deque<PCR>& children); 00095 virtual bool checkCOD(); 00096 00097 public: 00098 00099 /** Constructor. Does not initialize with an iostream, so you will 00100 have to supply a buffer when you call readCOD or writeCOD. 00101 @param ls The local site any new vobjects will be created on. 00102 */ 00103 COD(LocalSite& ls); 00104 00105 /** Constructor. 00106 @param io the io stream to read from or write to 00107 @param ls The local site any new vobjects will be created on. 00108 */ 00109 COD(iostream& io, LocalSite& ls); 00110 00111 /** Destructor. */ 00112 virtual ~COD(); 00113 00114 /** Write the current COD to the initialized iostream. */ 00115 virtual void writeCOD(bool gzipped = true); 00116 00117 /** Write the current COD to a buffer. The buffer is malloc()'d 00118 by writeCOD and returned via the supplied parameters. 00119 @param buffer the data buffer holding the COD data. You 00120 should free() this when you're done. 00121 @param size the size of the buffer 00122 */ 00123 virtual void writeCOD(unsigned char** buffer, unsigned int* size, bool gzipped = true); 00124 00125 /** Read a COD from the initialized iostream */ 00126 virtual void readCOD(); 00127 00128 /** Read the COD from the supplied data buffer. 00129 @param buffer the source data 00130 @param size the length of the data 00131 */ 00132 virtual void readCOD(unsigned char* buffer, unsigned int size); 00133 00134 /** Computes the output size of the COD 00135 @return the number of bytes needed to store this COD 00136 */ 00137 virtual int computeSize(); 00138 00139 /** Change the iostream to use. */ 00140 virtual void setStream(iostream& io); 00141 00142 /** Add a Vobject to this COD. 00143 @param v the Vobject 00144 @param portable passed to Vobject::saveState -- should this 00145 COD save site- or configuration-specific information (possibly 00146 making for a smaller COD) or embed all necessary data? 00147 @param saveChildren should the child list be saved in this COD? 00148 @return the position of this entry in the COD's vobject table 00149 @note This will use Vobject::saveState to get additional details 00150 */ 00151 virtual int addVobject(Vobject* v, bool portable, bool saveChildren); 00152 00153 /** Add a Vobject to this COD. This uses the supplied values, 00154 overriding the information stored in the Vobject itself. It does not 00155 call Vobject::saveState() 00156 @param v the Vobject 00157 @param types the type strings to be saved 00158 @param mb a message block of messages used to restore the 00159 state of this Vobject 00160 @param saveChildren should the child list be saved in this COD? 00161 @return the position of this entry in the COD's vobject table 00162 */ 00163 virtual int addVobject(Vobject* v, const set<string>& types, MessageBlock* mb, bool saveChildren); 00164 00165 /** Add a Vobject to this COD. This uses the supplied values, 00166 overriding the information stored in the Vobject itself. It does not 00167 call Vobject::saveState() 00168 @param v the Vobject 00169 @param types the type strings to be saved 00170 @param mb a message block of messages used to restore the 00171 state of this Vobject 00172 @param saveChildren should the child list be saved in this COD? 00173 @return the position of this entry in the COD's vobject table 00174 */ 00175 virtual int addVobject(Vobject* v, const deque<string>& types, MessageBlock* mb, bool saveChildren); 00176 00177 /** Number of Vobjects in the COD Vobject table. 00178 @return the table size 00179 */ 00180 virtual int numVobjects(); 00181 00182 /** Get the Vobject from the COD Vobject table by site name. 00183 @param name the site name 00184 @return the entry, or NULL if invalid 00185 */ 00186 virtual Entry* getVobject(const string& name); 00187 00188 /** Get the Vobject by position in the COD Vobject table. 00189 @param pos the position 00190 @return the entry, or NULL if invalid 00191 */ 00192 virtual Entry* getVobject(int pos); 00193 00194 /** Remove a Vobject from the COD Vobject table. 00195 @param name the site name 00196 */ 00197 virtual void removeVobject(const string& name); 00198 00199 /** Remove a Vobject from the COD Vobject table. 00200 @param pos the position in the COD Vobject table 00201 */ 00202 virtual void removeVobject(int pos); 00203 00204 /** Clear the COD Vobject table. */ 00205 virtual void clear(); 00206 00207 /** Get the default local site. 00208 @return the local site NOTE you should assign this to a vRef<> 00209 or call release when you're done! */ 00210 virtual LocalSite& getLocalSite(); 00211 00212 /** A utility function which writes some variables to the supplied 00213 buffer, following the format string. The values are written 00214 in network byte order (big-endian). The format string 00215 supports the following data types: 00216 00217 'c': a char, or single byte 00218 00219 's': a short, or 16 bit integer 00220 00221 'l': a long, or 32 bit integer 00222 00223 'S': a string. This must actually be passed in as two values, 00224 first the length (a 16 bit unsigned integer) and then a char* 00225 to the actual character data. The string is packed using a 00226 leading 16 bit length followed by the string data. 00227 00228 'f': a 32-bit IEEE floating point number 00229 00230 @param buf the buffer to write to 00231 @param maxsize the maximum size of the buffer, to avoid overflows 00232 @param fmt the format string 00233 @param ... the values to be written to the buffer 00234 @return the number of bytes written to the buffer, which will 00235 always be <= maxsize 00236 @note Here's an example of using pack: 00237 @code 00238 char c = 'Q'; 00239 short int s = 42; 00240 long int l = 999999; 00241 char* S = "Foo Bar Baz"; 00242 float f = 3.21; 00243 char buffer[256]; 00244 00245 int length = pack(buffer, sizeof(buffer), "cslSf", c, s, l, strlen(S), S, f); 00246 @endcode 00247 */ 00248 static int pack(uint8_t *buf, int maxsize, char *fmt, ...); 00249 00250 /** A utility function that reads some values from a packed data 00251 buffer. It is symmetric to the unpack() function. The only 00252 major difference being that pointers to variables are 00253 passed in to which the unpacked values will be assigned. 00254 @param buf the buffer to read from 00255 @param the maximum size of the buffer, to avoid overruns 00256 @param fmt the format string 00257 @param ... pointers to variables to store the unpacked contents 00258 @return the number of bytes read 00259 @note Here's an example of using unpack: 00260 @code 00261 char* buffer = getSomeData(); 00262 int buffersize = getSomeDataLength(); 00263 00264 char c; 00265 short int s, strsize; 00266 long int l; 00267 char* S; 00268 float f; 00269 00270 int length = unpack(buffer, buffersize, "cslSf", &c, &s, &l, &strsize, &S, &f); 00271 @endcode 00272 */ 00273 static int unpack(const uint8_t *buf, int maxsize, char *fmt, ...); 00274 00275 static void gzipUncompress(unsigned char** dest, unsigned int* destlen, const unsigned char* source, unsigned int srclen); 00276 static void gzipCompress(unsigned char** dest, unsigned int* destlen, const unsigned char* source, unsigned int srclen); 00277 }; 00278 00279 /** The contents of a remote COD represent live objects on a remote 00280 site, rather than a save state which is to be loaded locally. In 00281 particular, this means that the objects are created and messages 00282 delivered as updates to RemoteVobjects. 00283 */ 00284 class RemoteCOD : public COD 00285 { 00286 protected: 00287 RemoteSite& rs; 00288 00289 public: 00290 /** Constructor. Does not initialize with an iostream, so you will 00291 have to supply a buffer when you call readCOD or writeCOD. 00292 @param ls Our local site 00293 @param rs The remote site the objects are associated with 00294 */ 00295 RemoteCOD(LocalSite& ls, RemoteSite& rs); 00296 00297 /** Constructor. 00298 @param io the io stream to read from or write to 00299 @param ls Our local site 00300 @param rs The remote site the objects are associated with 00301 */ 00302 RemoteCOD(iostream& io, LocalSite& ls, RemoteSite& rs); 00303 00304 /** Destructor */ 00305 virtual ~RemoteCOD(); 00306 00307 /** @return the remote site this objects are associated with */ 00308 virtual RemoteSite& getRemoteSite(); 00309 00310 /** Read the remote COD from the supplied iostream */ 00311 virtual void readCOD(); 00312 00313 /** Read the remote COD from the supplied buffer 00314 @param buffer a data buffer with the COD contents 00315 @param size the size of the buffer 00316 */ 00317 virtual void readCOD(unsigned char* buffer, unsigned int size) 00318 { COD::readCOD(buffer, size); } 00319 }; 00320 00321 #endif