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 /*! Be mindful of version differences - better safe than sorry - put a
00009  *  version number as the first field, just in case */
00010 class LoadSave {
00011  public:
00012   //! This is the amount of extra space needed to store a string (int for len of string plus 1 for null term
00013   static const unsigned int stringpad=sizeof(unsigned int)+1;
00014 
00015   //!@name Constructors/Destructors
00016   /*! @brief constructor */
00017   LoadSave() {}
00018   LoadSave(const char* filename) { LoadFile(filename); }
00019   virtual ~LoadSave(); //!< destructor
00020   //@}
00021 
00022   //! These are useful for sending the data across a network as well as to a file.\n
00023   //! These are the only ones that MUST be overridden, as the file
00024   //! ops can be based on calling these, tho feel free to override
00025   //! the file ops as well if speed or temp. memory is tight.
00026   //!@name Buffer Operations
00027   /*! @brief calculates space needed to save - if you can't precisely add up the size, overestimate and things will still work.
00028    *  @return number of bytes read/written, 0 if error (or empty) */
00029   virtual unsigned int getBinSize() const =0;
00030   //! Load from a saved buffer
00031   /*! @param buf pointer to the memory where you should begin loading
00032    *  @param len length of @a buf available (this isn't all yours, might be more stuff saved after yours)
00033    *  @return the number of bytes actually used */
00034   virtual unsigned int LoadBuffer(const char buf[], unsigned int len)=0;
00035   //! Save to a given buffer
00036   /*! @param buf pointer to the memory where you should begin writing
00037    *  @param len length of @a buf available.  (this isn't all yours, constrain yourself to what you returned in getBinSize() )
00038    *  @return the number of bytes actually used */
00039   virtual unsigned int SaveBuffer(char buf[], unsigned int len) const =0;
00040   //@}
00041 
00042   //!These are called to load and save to files
00043   //!@name File Operations
00044   /*!@brief initiate opening of the specified file and loading/saving of all appropriate information.
00045    * @param filename the file to load/save @return number of bytes read/written, 0 if error (or empty)*/
00046   virtual unsigned int LoadFile(const char* filename);
00047   virtual unsigned int SaveFile(const char* filename) const;
00048 
00049   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00050   /*! @param f a pointer to the file to load
00051    *  @warning could potentially be very inefficient if root-level objects
00052    *  override LoadFile but leaf-level ones use this implementation, but
00053    *  leaf-level ones won't even get this call unless you override the ones
00054    *  above them - hence, this is all or nothing
00055    *  @return number of bytes read, 0 if error (or empty) */
00056   virtual unsigned int LoadFile(FILE* f);
00057   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00058   /*! @param f a pointer to the file to save
00059    *  @warning could potentially be very inefficient if root-level objects
00060    *  override SaveFile but leaf-level ones use this implementation, but
00061    *  leaf-level ones won't even get this call unless you override the ones
00062    *  above them - hence, this is all or nothing
00063    *  @return number of bytes written, 0 if error (or empty) */
00064   virtual unsigned int SaveFile(FILE* f) const;
00065   //@}
00066 
00067   //! These are for putting creator codes at the beginning of your data to check for sanity, just optional
00068   //!@name Creator Utilities
00069   /*!@brief Returns size of the creator code
00070    * @param creator a string to use for the creator
00071    * @return the size to leave for the creator code */
00072   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00073   //! Compares the creator code in the buffer to the one given
00074   /*!@param creator what the creator should be
00075    * @param buf the buffer to check
00076    * @param len the size remaining in the buffer
00077    * @param isLoading set this to true if you want to output a warning if it doesn't match
00078    * @return the number of bytes used by the creator, or 0 if it didn't match */
00079   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const;
00080   //! 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)
00081   /*!@param creator what the creator should be
00082    * @param f the file pointer to check
00083    * @param isLoading set this to true if you want to output a warning if it doesn't match
00084    * @return the number of bytes consumed by the creator code, or 0 if it didn't match */
00085   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const;
00086   //! Saves a creator code to a buffer
00087   /*!@param creator the string to use for the creator code
00088    * @param buf the buffer to save the code into
00089    * @param len the space available in the buffer
00090    * @return the number of bytes consumed */
00091   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const;
00092   //! Saves a creator code directly to a file
00093   /*!@param creator the string to use for the creator code
00094    * @param f the file to save the code into
00095    * @return the number of bytes consumed */
00096   virtual unsigned int saveCreator(const char* creator, FILE* f) const;
00097   //@}
00098 
00099   /* //if you want to have a default behavior template like this (look up template specialization) (i thought i needed this, nevermind)
00100     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; }
00101     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; }
00102     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; }
00103     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; }
00104   */
00105 
00106   //!encode/decode cross-platform compatable (byte order consistancy)
00107   //!@name Encode/Decode Utils
00108   /*!@brief encode or decode with byte order consistancy*/
00109   inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap)  { return x.SaveBuffer(buf,cap); }
00110   inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap)  { return x.LoadBuffer(buf,cap); }
00111   inline static unsigned int encode(const LoadSave& x, FILE* f)                  { return x.SaveFile(f); }
00112   inline static unsigned int decode(LoadSave& x, FILE* f)                        { return x.LoadFile(f); }
00113   
00114   //I don't know what compiler flag to use - this one is fake.
00115   //Ideally, we should be able to detect host orientation
00116   //and then pick a standard byte order.
00117 #ifdef LOADSAVE_SWAPBYTES
00118   
00119   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); }
00120   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);}
00121   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); }
00122   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);}
00123   
00124   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); }
00125   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);}
00126   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); }
00127   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);}
00128   
00129   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); }
00130   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);}
00131   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); }
00132   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);}
00133   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); }
00134   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);}
00135   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); }
00136   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);}
00137   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); }
00138   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);}
00139   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); }
00140   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);}
00141   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); }
00142   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);}
00143   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); }
00144   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);}
00145   
00146   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); }
00147   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);}
00148   inline static unsigned int encode(const short x, FILE* f)                           { short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00149   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);}
00150   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); }
00151   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);}
00152   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); }
00153   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);}
00154 
00155 #else
00156   
00157   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); }
00158   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); }
00159   inline static unsigned int encode(const double x, FILE* f)                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00160   inline static unsigned int decode(double& x, FILE* f)                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00161   
00162   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); }
00163   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); }
00164   inline static unsigned int encode(const float x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00165   inline static unsigned int decode(float& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00166 
00167   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); }
00168   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); }
00169   inline static unsigned int encode(const long x, FILE* f)                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00170   inline static unsigned int decode(long& x, FILE* f)                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00171   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); }
00172   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); }
00173   inline static unsigned int encode(const unsigned long x, FILE* f)                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00174   inline static unsigned int decode(unsigned long& x, FILE* f)                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00175   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); }
00176   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); }
00177   inline static unsigned int encode(const int x, FILE* f)                            { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00178   inline static unsigned int decode(int& x, FILE* f)                                 { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00179   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); }
00180   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); }
00181   inline static unsigned int encode(const unsigned int x, FILE* f)                   { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00182   inline static unsigned int decode(unsigned int& x, FILE* f)                        { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00183   
00184   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); }
00185   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); }
00186   inline static unsigned int encode(const short x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00187   inline static unsigned int decode(short& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00188   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); }
00189   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); }
00190   inline static unsigned int encode(const unsigned short x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00191   inline static unsigned int decode(unsigned short& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00192 
00193 #endif //end of big/little endian differences
00194   
00195   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; }
00196   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; }
00197   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); }
00198   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; }
00199   
00200   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; }
00201   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; }
00202   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); }
00203   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; }
00204   
00205   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); }
00206   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);}
00207   inline static unsigned int encode(const char x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00208   inline static unsigned int decode(char& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00209   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); }
00210   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);}
00211   inline static unsigned int encode(const unsigned char x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00212   inline static unsigned int decode(unsigned char& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00213   
00214   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); }
00215   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);}
00216   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); }
00217   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); }
00218   //@}  
00219 protected:
00220   //!templated function to swap byte ordering, should allow compiler to unroll the loop; warning don't use this if src==dst!!!
00221   template<class T> inline static void byteswap(T& dstc, const T& srcc) {
00222     char* dst=(char*)&dstc;
00223     const char* src=(const char*)&srcc;
00224     for(unsigned int i=0; i<sizeof(T); i++)
00225       dst[sizeof(T)-1-i]=src[i];
00226   }
00227 };
00228 
00229 
00230 /*! @file
00231  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00232  * @todo detect appropriate byte ordering for other platforms
00233  * @author ejt (Creator)
00234  *
00235  * $Author: ejt $
00236  * $Name: tekkotsu-2_0 $
00237  * $Revision: 1.6 $
00238  * $State: Exp $
00239  * $Date: 2004/01/18 10:16:58 $
00240  */
00241 
00242 #endif

Tekkotsu v2.0
Generated Wed Jan 21 03:20:29 2004 by Doxygen 1.3.4