Homepage Demos Overview Downloads Tutorials Reference
Credits

LoadSave.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_LoadSave_h
00003 #define INCLUDED_LoadSave_h
00004 
00005 #include <string>
00006 
00007 //! Intended as an interface to allow easy and uniform file operations
00008 /*!
00009   
00010   Generally, for usage, all you need to know is to call
00011   <tt>SaveFile("/path/to/file.ext")</tt> or
00012   <tt>SaveBuffer(membuffer)</tt> in order to have the class serialize
00013   itself, and the LoadFile() / LoadBuffer() in order to reload the
00014   data.
00015   
00016   So, when SaveFile() is called, it checks that it
00017   can open the specified file, and then calls SaveFileStream()
00018   with the open file.  This will then check getBinSize(), create a
00019   buffer of that size, and call SaveBuffer() to do the actual work of
00020   serialization into that buffer.  If SaveBuffer is successful (make
00021   sure your getBinSize() doesn't underestimate!) SaveFileStream()
00022   copies the buffer out to the file, and then finally, SaveFile() will
00023   close the file.
00024   
00025   This has the nice side effect that if you want to send the data over
00026   the network instead of a file, you can call SaveBuffer() directly
00027   and reuse the code.  However, if you have a lot of data to save, you
00028   can override the SaveFileStream() function as well, and save into
00029   the file directly.  So far I've only bothered to do that with
00030   only a few classes.
00031   
00032   The recommended style for using LoadSave in classes with inheritance
00033   is to have each subclass first call the superclass's implementation,
00034   and then save their own local data.  This compartmentalizes the data
00035   access and makes it easy to maintain - the code that serializes is
00036   right in with the code that defines the structure.  If you change
00037   one, it's easy to see where to change the other.  And protection
00038   between levels of inheritance is retained.  (This is why I say it's
00039   highly flexible/maintainable, but poor readability since the
00040   serialization is all broken up.)
00041   
00042   I also recommend putting a little string header at the beginning of
00043   each class's info.  This will allow polymorphism when loading files
00044   (you can look at the string and create the appropriate type) but
00045   also is handy for checking field alignment... it's a lot easier to
00046   tell how much you're offset within a string than to do the same with
00047   a stream of binary values.  Further, you can use the string as
00048   version information if you want to be backward compatible in future
00049   versions of your code.
00050   
00051   LoadSave provides a series of encode and decode functions for all
00052   the primitive types.  This will handle copying the value into the
00053   buffer or file, and can provide platform independence through byte
00054   swapping if needed (there's a compiler flag you can set for
00055   platforms that have the opposite byte order).  Most of these are
00056   pretty straightfoward - an int is just 4 bytes and so on.
00057   
00058   However, there's one caveat that I want to make sure to point out if
00059   you have to write parsing code in say, Java.  Strings are encoded by
00060   first storing an int to hold the string's length, then the string
00061   itself, and then a null character.  This adds 5 bytes to the length
00062   of any string, but makes loading the files much easier/faster - you
00063   can call string library functions directly on the buffer if it's
00064   already in memory since the string is null terminated, or can
00065   allocate memory to hold the string during loading from a file if
00066   needed because you'll know the size of the string before you get to
00067   it.
00068   
00069   Of course, the string stuff is transparent if you just use
00070   LoadSave's encode/decode functions to parse it.  But if that's not
00071   available (for instance if your receiver is in Java, there's a
00072   readLoadSaveString() in VisionListener.java if that will help:
00073   http://cvs.tekkotsu.org/cgi-bin/viewcvs.cgi/Tekkotsu/tools/mon/org/tekkotsu/mon/VisionListener.java?rev=1.6&content-type=text/vnd.viewcvs-markup
00074   @code
00075   public boolean _isConnected;
00076 
00077   public String readLoadSaveString(InputStream in) throws java.io.IOException {
00078     int creatorLen=readInt(in);
00079     if(!_isConnected) return ""; 
00080     String creator=new String(readBytes(in,creatorLen));
00081     if(!_isConnected) return "";
00082     if(readChar(in)!='\0')
00083       System.err.println("Misread LoadSave string? "+creator);
00084     return creator;
00085   }
00086 
00087   public int readInt(InputStream in) throws IOException {
00088     int read=0;
00089     int last=0;
00090     byte[] buf=new byte[4];
00091     while (read<4 && last>=0) { last=in.read(buf,read,4-read); read+=last; }
00092     if(last<0)
00093       _isConnected=false;
00094     return (b2i(buf[3])<<24) | (b2i(buf[2])<<16) |
00095            (b2i(buf[1])<< 8) | b2i(buf[0]);
00096   }
00097   public byte[] readBytes(InputStream in, int bytes) throws IOException {
00098     byte[] ret=new byte[bytes];
00099     readBytes(ret, in, bytes);
00100     return ret;
00101   }
00102   public char readChar(InputStream in) throws IOException {
00103     return (char)in.read();
00104   }
00105   @endcode
00106 */
00107 class LoadSave {
00108  public:
00109   //! This is the amount of extra space needed to store a string (int for len of string plus 1 for null term
00110   static const unsigned int stringpad=sizeof(unsigned int)+1;
00111 
00112   //!@name Constructors/Destructors
00113   /*! @brief constructor */
00114   LoadSave() {}
00115   virtual ~LoadSave(); //!< destructor
00116   //@}
00117 
00118   //! These are useful for sending the data across a network as well as to a file.\n
00119   //! These are the only ones that MUST be overridden, as the file
00120   //! ops can be based on calling these, tho feel free to override
00121   //! the file ops as well if speed or temp. memory is tight.
00122   //!@name Buffer Operations
00123   /*! @brief calculates space needed to save - if you can't precisely add up the size, overestimate and things will still work.
00124    *  @return number of bytes read/written, 0 if error (or empty) */
00125   virtual unsigned int getBinSize() const =0;
00126   //! Load from a saved buffer
00127   /*! @param buf pointer to the memory where you should begin loading
00128    *  @param len length of @a buf available (this isn't all yours, might be more stuff saved after yours)
00129    *  @return the number of bytes actually used */
00130   virtual unsigned int LoadBuffer(const char buf[], unsigned int len)=0;
00131   //! Save to a given buffer
00132   /*! @param buf pointer to the memory where you should begin writing
00133    *  @param len length of @a buf available.  (this isn't all yours, constrain yourself to what you returned in getBinSize() )
00134    *  @return the number of bytes actually used */
00135   virtual unsigned int SaveBuffer(char buf[], unsigned int len) const =0;
00136   //@}
00137 
00138   //!These are called to load and save to files
00139   //!@name File Operations
00140   /*!@brief initiate opening of the specified file and loading/saving of all appropriate information.
00141    * @param filename the file to load/save @return number of bytes read/written, 0 if error (or empty)*/
00142   virtual unsigned int LoadFile(const char* filename);
00143   virtual unsigned int SaveFile(const char* filename) const;
00144 
00145   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00146   /*! @param f a pointer to the file to load
00147    *  @warning could potentially be very inefficient if root-level objects
00148    *  override LoadFile but leaf-level ones use this implementation, but
00149    *  leaf-level ones won't even get this call unless you override the ones
00150    *  above them - hence, this is all or nothing
00151    *  @return number of bytes read, 0 if error (or empty) */
00152   virtual unsigned int LoadFileStream(FILE* f);
00153   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00154   /*! @param f a pointer to the file to save
00155    *  @warning could potentially be very inefficient if root-level objects
00156    *  override SaveFile but leaf-level ones use this implementation, but
00157    *  leaf-level ones won't even get this call unless you override the ones
00158    *  above them - hence, this is all or nothing
00159    *  @return number of bytes written, 0 if error (or empty) */
00160   virtual unsigned int SaveFileStream(FILE* f) const;
00161   //@}
00162 
00163   //! Handy for checking results from functions which manipulate the buffer
00164   /*! @param res number of bytes used
00165    *  @param buf pointer to address of current place in buffer, will be incremented by @a res bytes
00166    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00167    *  @param msg Error to display if res is less than or equal to zero
00168    *  @return true if everything worked, false otherwise */
00169   static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg);
00170 
00171   //! Handy for checking results from functions which manipulate the buffer
00172   /*! This really should be rewritten to use variable number of arguments which can be passed
00173    *  directly on to printf...
00174    *  @param res number of bytes used
00175    *  @param buf pointer to address of current place in buffer, will be incremented by @a res bytes
00176    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00177    *  @param msg Error to display if res is less than or equal to zero
00178    *  @param arg1 An additional argument to be displayed (using %d in the @a msg); intended for things such as line number of error in file being read
00179    *  @return true if everything worked, false otherwise */
00180   static bool ChkAdvance(int res, const char** buf, unsigned int* len, const char* msg, int arg1);
00181 
00182   //! These are for putting creator codes at the beginning of your data to check for sanity, just optional
00183   //!@name Creator Utilities
00184 
00185   /*!@brief Returns size of the creator code
00186    * @param creator a string to use for the creator
00187    * @return the size to leave for the creator code */
00188   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00189   //! Compares the creator code in the buffer to the one given
00190   /*!@param creator what the creator should be
00191    * @param buf the buffer to check
00192    * @param len the size remaining in the buffer
00193    * @param isLoading set this to true if you want to output a warning if it doesn't match
00194    * @return the number of bytes used by the creator, or 0 if it didn't match */
00195   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const;
00196   //! Compares the creator code in the file to the one given, will attempt to reset the file position if fails (so you can check for one of several types)
00197   /*!@param creator what the creator should be
00198    * @param f the file pointer to check
00199    * @param isLoading set this to true if you want to output a warning if it doesn't match
00200    * @return the number of bytes consumed by the creator code, or 0 if it didn't match */
00201   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const;
00202   //! Saves a creator code to a buffer
00203   /*!@param creator the string to use for the creator code
00204    * @param buf the buffer to save the code into
00205    * @param len the space available in the buffer
00206    * @return the number of bytes consumed */
00207   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const;
00208   //! Saves a creator code directly to a file
00209   /*!@param creator the string to use for the creator code
00210    * @param f the file to save the code into
00211    * @return the number of bytes consumed */
00212   virtual unsigned int saveCreator(const char* creator, FILE* f) const;
00213   //@}
00214 
00215   /* //if you want to have a default behavior template like this (look up template specialization) (i thought i needed this, nevermind)
00216     template<class T> inline static unsigned int encode(const T x, char buf[], unsigned int cap) { cout << "*** WARNING attempted to encode non-primitive and non-LoadSave" << endl; return 0; }
00217     template<class T> inline static unsigned int decode(T& x, const char buf[], unsigned int cap) { cout << "*** WARNING attempted to decode non-primitive and non-LoadSave" << endl; return 0; }
00218     template<class T> inline static unsigned int encode(const T x, FILE* f) { cout << "*** WARNING attempted to encode non-primitive and non-LoadSave" << endl; return 0; }
00219     template<class T> inline static unsigned int decode(T& x, FILE* f) { cout << "*** WARNING attempted to decode non-primitive and non-LoadSave" << endl; return 0; }
00220   */
00221 
00222   //!encode/decode cross-platform compatable (byte order consistancy)
00223   //!@name Encode/Decode Utils
00224   /*!@brief encode or decode with byte order consistancy*/
00225   inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap)  { return x.SaveBuffer(buf,cap); }
00226   inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap)  { return x.LoadBuffer(buf,cap); }
00227   inline static unsigned int encode(const LoadSave& x, FILE* f)                  { return x.SaveFileStream(f); }
00228   inline static unsigned int decode(LoadSave& x, FILE* f)                        { return x.LoadFileStream(f); }
00229   
00230   //I don't know what compiler flag to use - this one is fake.
00231   //Ideally, we should be able to detect host orientation
00232   //and then pick a standard byte order.
00233 #ifdef LOADSAVE_SWAPBYTES
00234   
00235   inline static unsigned int encode(const double x, char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; byteswap(*(double*)buf,x); return sizeof(x); }
00236   inline static unsigned int decode(double& x, const char buf[], unsigned int cap)         { if(cap<sizeof(x)) return 0; byteswap(x,*(const double*)buf); return sizeof(x);}
00237   inline static unsigned int encode(const double x, FILE* f)                          { double t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00238   inline static unsigned int decode(double& x, FILE* f)                               { double t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00239   
00240   inline static unsigned int encode(const float x, char buf[], unsigned int cap)           { if(cap<sizeof(x)) return 0; byteswap(*(float*)buf,x); return sizeof(x); }
00241   inline static unsigned int decode(float& x, const char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; byteswap(x,*(const float*)buf); return sizeof(x);}
00242   inline static unsigned int encode(const float x, FILE* f)                           { float t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00243   inline static unsigned int decode(float& x, FILE* f)                                { float t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00244   
00245   inline static unsigned int encode(const long x, char buf[], unsigned int cap)            { if(cap<sizeof(x)) return 0; byteswap(*(long*)buf,x); return sizeof(x); }
00246   inline static unsigned int decode(long& x, const char buf[], unsigned int cap)           { if(cap<sizeof(x)) return 0; byteswap(x,*(const long*)buf); return sizeof(x);}
00247   inline static unsigned int encode(const long x, FILE* f)                            { long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00248   inline static unsigned int decode(long& x, FILE* f)                                 { long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00249   inline static unsigned int encode(const unsigned long x, char buf[], unsigned int cap)   { if(cap<sizeof(x)) return 0; byteswap(*(unsigned long*)buf,x); return sizeof(x); }
00250   inline static unsigned int decode(unsigned long& x, const char buf[], unsigned int cap)  { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned long*)buf); return sizeof(x);}
00251   inline static unsigned int encode(const unsigned long x, FILE* f)                   { unsigned long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00252   inline static unsigned int decode(unsigned long& x, FILE* f)                        { unsigned long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00253   inline static unsigned int encode(const int x, char buf[], unsigned int cap)             { if(cap<sizeof(x)) return 0; byteswap(*(int*)buf,x); return sizeof(x); }
00254   inline static unsigned int decode(int& x, const char buf[], unsigned int cap)            { if(cap<sizeof(x)) return 0; byteswap(x,*(const int*)buf); return sizeof(x);}
00255   inline static unsigned int encode(const int x, FILE* f)                             { int t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00256   inline static unsigned int decode(int& x, FILE* f)                                  { int t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00257   inline static unsigned int encode(const unsigned int x, char buf[], unsigned int cap)    { if(cap<sizeof(x)) return 0; byteswap(*(unsigned int*)buf,x); return sizeof(x); }
00258   inline static unsigned int decode(unsigned int& x, const char buf[], unsigned int cap)   { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned int*)buf); return sizeof(x);}
00259   inline static unsigned int encode(const unsigned int x, FILE* f)                    { unsigned int t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00260   inline static unsigned int decode(unsigned int& x, FILE* f)                         { unsigned int t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00261   
00262   inline static unsigned int encode(const short x, char buf[], unsigned int cap)           { if(cap<sizeof(x)) return 0; byteswap(*(short*)buf,x); return sizeof(x); }
00263   inline static unsigned int decode(short& x, const char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; byteswap(x,*(const short*)buf); return sizeof(x);}
00264   inline static unsigned int encode(const short x, FILE* f)                           { short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00265   inline static unsigned int decode(short& x, FILE* f)                                { short t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00266   inline static unsigned int encode(const unsigned short x, char buf[], unsigned int cap)  { if(cap<sizeof(x)) return 0; byteswap(*(unsigned short*)buf,x); return sizeof(x); }
00267   inline static unsigned int decode(unsigned short& x, const char buf[], unsigned int cap) { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned short*)buf); return sizeof(x);}
00268   inline static unsigned int encode(const unsigned short x, FILE* f)                  { unsigned short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00269   inline static unsigned int decode(unsigned short& x, FILE* f)                       { unsigned short t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00270 
00271 #else
00272   
00273   inline static unsigned int encode(const double x, char buf[], unsigned int cap)         { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00274   inline static unsigned int decode(double& x, const char buf[], unsigned int cap)        { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00275   inline static unsigned int encode(const double x, FILE* f)                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00276   inline static unsigned int decode(double& x, FILE* f)                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00277   
00278   inline static unsigned int encode(const float x, char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00279   inline static unsigned int decode(float& x, const char buf[], unsigned int cap)         { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00280   inline static unsigned int encode(const float x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00281   inline static unsigned int decode(float& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00282 
00283   inline static unsigned int encode(const long x, char buf[], unsigned int cap)           { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00284   inline static unsigned int decode(long& x, const char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00285   inline static unsigned int encode(const long x, FILE* f)                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00286   inline static unsigned int decode(long& x, FILE* f)                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00287   inline static unsigned int encode(const unsigned long x, char buf[], unsigned int cap)  { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00288   inline static unsigned int decode(unsigned long& x, const char buf[], unsigned int cap) { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00289   inline static unsigned int encode(const unsigned long x, FILE* f)                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00290   inline static unsigned int decode(unsigned long& x, FILE* f)                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00291   inline static unsigned int encode(const int x, char buf[], unsigned int cap)            { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00292   inline static unsigned int decode(int& x, const char buf[], unsigned int cap)           { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00293   inline static unsigned int encode(const int x, FILE* f)                            { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00294   inline static unsigned int decode(int& x, FILE* f)                                 { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00295   inline static unsigned int encode(const unsigned int x, char buf[], unsigned int cap)   { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00296   inline static unsigned int decode(unsigned int& x, const char buf[], unsigned int cap)  { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00297   inline static unsigned int encode(const unsigned int x, FILE* f)                   { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00298   inline static unsigned int decode(unsigned int& x, FILE* f)                        { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00299   
00300   inline static unsigned int encode(const short x, char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00301   inline static unsigned int decode(short& x, const char buf[], unsigned int cap)         { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00302   inline static unsigned int encode(const short x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00303   inline static unsigned int decode(short& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00304   inline static unsigned int encode(const unsigned short x, char buf[], unsigned int cap) { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00305   inline static unsigned int decode(unsigned short& x, const char buf[], unsigned int cap){ if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00306   inline static unsigned int encode(const unsigned short x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00307   inline static unsigned int decode(unsigned short& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00308 
00309 #endif //end of big/little endian differences
00310   
00311   inline static unsigned int encode(const std::string& x, char buf[], unsigned int cap)  { if(cap<sizeof(unsigned int)+x.size()+1) return 0; memcpy(buf+encode(x.size(),buf,cap),x.c_str(),x.size()+1); return x.size()+stringpad; }
00312   inline static unsigned int decode(std::string& x, const char buf[], unsigned int cap)  { if(cap<sizeof(unsigned int)) return 0; unsigned int sz=0; decode(sz,buf,cap); if(cap<sizeof(unsigned int)+sz+1) return 0; x.assign(buf+sizeof(unsigned int),sz); return x.size()+stringpad; }
00313   inline static unsigned int encode(const std::string& x, FILE* f)                  { encode(x.size(),f); return sizeof(unsigned int)+fwrite(x.c_str(),1,sizeof(x)+1,f); }
00314   inline static unsigned int decode(std::string& x, FILE* f)                        { unsigned int sz=0; decode(sz,f); char *tmp=new char[sz+1]; if(fread(tmp,1,sz+1,f)!=sz+1) { delete [] tmp; return 0; } x.assign(tmp,sz); delete [] tmp; return sz+stringpad; }
00315   
00316   inline static unsigned int encode(const char* x, char buf[], unsigned int cap)      { unsigned int sz=strlen(x); if(cap<sizeof(unsigned int)+sz+1) return 0; memcpy(buf+encode(sz,buf,cap),x,sz+1); return sz+stringpad; }
00317   inline static unsigned int decode(char*& x, const char buf[], unsigned int cap)     { if(cap<sizeof(unsigned int)) return 0; unsigned int sz=0; decode(sz,buf,cap); if(cap<sizeof(unsigned int)+sz+1) return 0; x=new char[sz+1]; strncpy(x,buf+sizeof(unsigned int),sz+1); return sz+stringpad; }
00318   inline static unsigned int encode(const char* x, FILE* f)                      { unsigned int sz=strlen(x); encode(sz,f); return sizeof(unsigned int)+fwrite(x,1,sz+1,f); }
00319   inline static unsigned int decode(char*& x, FILE* f)                           { unsigned int sz=0; decode(sz,f); x=new char[sz+1]; if(fread(x,1,sz+1,f)!=sz+1) { delete [] x; x=NULL; return 0; } return sz+stringpad; }
00320   
00321   inline static unsigned int encode(const char x, char buf[], unsigned int cap)          { if(cap<sizeof(x)) return 0; buf[0]=x; return sizeof(x); }
00322   inline static unsigned int decode(char& x, const char buf[], unsigned int cap)         { if(cap<sizeof(x)) return 0; x=buf[0]; return sizeof(x);}
00323   inline static unsigned int encode(const char x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00324   inline static unsigned int decode(char& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00325   inline static unsigned int encode(const unsigned char x, char buf[], unsigned int cap) { if(cap<sizeof(x)) return 0; buf[0]=(char)x; return sizeof(x); }
00326   inline static unsigned int decode(unsigned char& x, const char buf[], unsigned int cap){ if(cap<sizeof(x)) return 0; x=(unsigned char)buf[0]; return sizeof(x);}
00327   inline static unsigned int encode(const unsigned char x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00328   inline static unsigned int decode(unsigned char& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00329   
00330   inline static unsigned int encode(const bool x, char buf[], unsigned int cap)          { if(cap<sizeof(char)) return 0; buf[0]=(char)(x?1:0); return sizeof(char); }
00331   inline static unsigned int decode(bool& x, const char buf[], unsigned int cap)         { if(cap<sizeof(char)) return 0; x=(buf[0]!=(char)0); return sizeof(char);}
00332   inline static unsigned int encode(const bool x, FILE* f)                          { char t=(char)(x?1:0); return sizeof(char)*fwrite(&t,sizeof(char),1,f); }
00333   inline static unsigned int decode(bool& x, FILE* f)                               { char t='\0'; fread(&t,sizeof(char),1,f); x=(t!=(char)0); return sizeof(char); }
00334   //@}  
00335 protected:
00336   //!templated function to swap byte ordering, should allow compiler to unroll the loop; warning don't use this if src==dst!!!
00337   template<class T> inline static void byteswap(T& dstc, const T& srcc) {
00338     char* dst=(char*)&dstc;
00339     const char* src=(const char*)&srcc;
00340     for(unsigned int i=0; i<sizeof(T); i++)
00341       dst[sizeof(T)-1-i]=src[i];
00342   }
00343 };
00344 
00345 
00346 /*! @file
00347  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00348  * @todo detect appropriate byte ordering for other platforms
00349  * @author ejt (Creator)
00350  *
00351  * $Author: ejt $
00352  * $Name: tekkotsu-2_2_1 $
00353  * $Revision: 1.11 $
00354  * $State: Exp $
00355  * $Date: 2004/04/08 16:28:06 $
00356  */
00357 
00358 #endif

Tekkotsu v2.2.1
Generated Tue Nov 23 16:36:38 2004 by Doxygen 1.3.9.1