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   LoadSave(const char* filename) { LoadFile(filename); }
00116   virtual ~LoadSave(); //!< destructor
00117   //@}
00118 
00119   //! These are useful for sending the data across a network as well as to a file.\n
00120   //! These are the only ones that MUST be overridden, as the file
00121   //! ops can be based on calling these, tho feel free to override
00122   //! the file ops as well if speed or temp. memory is tight.
00123   //!@name Buffer Operations
00124   /*! @brief calculates space needed to save - if you can't precisely add up the size, overestimate and things will still work.
00125    *  @return number of bytes read/written, 0 if error (or empty) */
00126   virtual unsigned int getBinSize() const =0;
00127   //! Load from a saved buffer
00128   /*! @param buf pointer to the memory where you should begin loading
00129    *  @param len length of @a buf available (this isn't all yours, might be more stuff saved after yours)
00130    *  @return the number of bytes actually used */
00131   virtual unsigned int LoadBuffer(const char buf[], unsigned int len)=0;
00132   //! Save to a given buffer
00133   /*! @param buf pointer to the memory where you should begin writing
00134    *  @param len length of @a buf available.  (this isn't all yours, constrain yourself to what you returned in getBinSize() )
00135    *  @return the number of bytes actually used */
00136   virtual unsigned int SaveBuffer(char buf[], unsigned int len) const =0;
00137   //@}
00138 
00139   //!These are called to load and save to files
00140   //!@name File Operations
00141   /*!@brief initiate opening of the specified file and loading/saving of all appropriate information.
00142    * @param filename the file to load/save @return number of bytes read/written, 0 if error (or empty)*/
00143   virtual unsigned int LoadFile(const char* filename);
00144   virtual unsigned int SaveFile(const char* filename) const;
00145 
00146   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00147   /*! @param f a pointer to the file to load
00148    *  @warning could potentially be very inefficient if root-level objects
00149    *  override LoadFile but leaf-level ones use this implementation, but
00150    *  leaf-level ones won't even get this call unless you override the ones
00151    *  above them - hence, this is all or nothing
00152    *  @return number of bytes read, 0 if error (or empty) */
00153   virtual unsigned int LoadFileStream(FILE* f);
00154   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00155   /*! @param f a pointer to the file to save
00156    *  @warning could potentially be very inefficient if root-level objects
00157    *  override SaveFile but leaf-level ones use this implementation, but
00158    *  leaf-level ones won't even get this call unless you override the ones
00159    *  above them - hence, this is all or nothing
00160    *  @return number of bytes written, 0 if error (or empty) */
00161   virtual unsigned int SaveFileStream(FILE* f) const;
00162   //@}
00163 
00164   //! These are for putting creator codes at the beginning of your data to check for sanity, just optional
00165   //!@name Creator Utilities
00166   /*!@brief Returns size of the creator code
00167    * @param creator a string to use for the creator
00168    * @return the size to leave for the creator code */
00169   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00170   //! Compares the creator code in the buffer to the one given
00171   /*!@param creator what the creator should be
00172    * @param buf the buffer to check
00173    * @param len the size remaining in the buffer
00174    * @param isLoading set this to true if you want to output a warning if it doesn't match
00175    * @return the number of bytes used by the creator, or 0 if it didn't match */
00176   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const;
00177   //! 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)
00178   /*!@param creator what the creator should be
00179    * @param f the file pointer to check
00180    * @param isLoading set this to true if you want to output a warning if it doesn't match
00181    * @return the number of bytes consumed by the creator code, or 0 if it didn't match */
00182   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const;
00183   //! Saves a creator code to a buffer
00184   /*!@param creator the string to use for the creator code
00185    * @param buf the buffer to save the code into
00186    * @param len the space available in the buffer
00187    * @return the number of bytes consumed */
00188   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const;
00189   //! Saves a creator code directly to a file
00190   /*!@param creator the string to use for the creator code
00191    * @param f the file to save the code into
00192    * @return the number of bytes consumed */
00193   virtual unsigned int saveCreator(const char* creator, FILE* f) const;
00194   //@}
00195 
00196   /* //if you want to have a default behavior template like this (look up template specialization) (i thought i needed this, nevermind)
00197     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; }
00198     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; }
00199     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; }
00200     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; }
00201   */
00202 
00203   //!encode/decode cross-platform compatable (byte order consistancy)
00204   //!@name Encode/Decode Utils
00205   /*!@brief encode or decode with byte order consistancy*/
00206   inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap)  { return x.SaveBuffer(buf,cap); }
00207   inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap)  { return x.LoadBuffer(buf,cap); }
00208   inline static unsigned int encode(const LoadSave& x, FILE* f)                  { return x.SaveFileStream(f); }
00209   inline static unsigned int decode(LoadSave& x, FILE* f)                        { return x.LoadFileStream(f); }
00210   
00211   //I don't know what compiler flag to use - this one is fake.
00212   //Ideally, we should be able to detect host orientation
00213   //and then pick a standard byte order.
00214 #ifdef LOADSAVE_SWAPBYTES
00215   
00216   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); }
00217   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);}
00218   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); }
00219   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);}
00220   
00221   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); }
00222   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);}
00223   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); }
00224   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);}
00225   
00226   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); }
00227   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);}
00228   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); }
00229   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);}
00230   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); }
00231   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);}
00232   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); }
00233   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);}
00234   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); }
00235   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);}
00236   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); }
00237   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);}
00238   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); }
00239   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);}
00240   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); }
00241   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);}
00242   
00243   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); }
00244   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);}
00245   inline static unsigned int encode(const short x, FILE* f)                           { short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00246   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);}
00247   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); }
00248   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);}
00249   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); }
00250   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);}
00251 
00252 #else
00253   
00254   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); }
00255   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); }
00256   inline static unsigned int encode(const double x, FILE* f)                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00257   inline static unsigned int decode(double& x, FILE* f)                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00258   
00259   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); }
00260   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); }
00261   inline static unsigned int encode(const float x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00262   inline static unsigned int decode(float& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00263 
00264   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); }
00265   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); }
00266   inline static unsigned int encode(const long x, FILE* f)                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00267   inline static unsigned int decode(long& x, FILE* f)                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00268   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); }
00269   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); }
00270   inline static unsigned int encode(const unsigned long x, FILE* f)                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00271   inline static unsigned int decode(unsigned long& x, FILE* f)                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00272   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); }
00273   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); }
00274   inline static unsigned int encode(const int x, FILE* f)                            { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00275   inline static unsigned int decode(int& x, FILE* f)                                 { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00276   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); }
00277   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); }
00278   inline static unsigned int encode(const unsigned int x, FILE* f)                   { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00279   inline static unsigned int decode(unsigned int& x, FILE* f)                        { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00280   
00281   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); }
00282   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); }
00283   inline static unsigned int encode(const short x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00284   inline static unsigned int decode(short& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00285   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); }
00286   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); }
00287   inline static unsigned int encode(const unsigned short x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00288   inline static unsigned int decode(unsigned short& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00289 
00290 #endif //end of big/little endian differences
00291   
00292   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; }
00293   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; }
00294   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); }
00295   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; }
00296   
00297   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; }
00298   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; }
00299   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); }
00300   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; }
00301   
00302   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); }
00303   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);}
00304   inline static unsigned int encode(const char x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00305   inline static unsigned int decode(char& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00306   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); }
00307   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);}
00308   inline static unsigned int encode(const unsigned char x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00309   inline static unsigned int decode(unsigned char& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00310   
00311   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); }
00312   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);}
00313   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); }
00314   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); }
00315   //@}  
00316 protected:
00317   //!templated function to swap byte ordering, should allow compiler to unroll the loop; warning don't use this if src==dst!!!
00318   template<class T> inline static void byteswap(T& dstc, const T& srcc) {
00319     char* dst=(char*)&dstc;
00320     const char* src=(const char*)&srcc;
00321     for(unsigned int i=0; i<sizeof(T); i++)
00322       dst[sizeof(T)-1-i]=src[i];
00323   }
00324 };
00325 
00326 
00327 /*! @file
00328  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00329  * @todo detect appropriate byte ordering for other platforms
00330  * @author ejt (Creator)
00331  *
00332  * $Author: ejt $
00333  * $Name: tekkotsu-2_1 $
00334  * $Revision: 1.8 $
00335  * $State: Exp $
00336  * $Date: 2004/02/05 23:33:45 $
00337  */
00338 
00339 #endif

Tekkotsu v2.1
Generated Tue Mar 16 23:19:14 2004 by Doxygen 1.3.5