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

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:47 2005 by Doxygen 1.4.4