Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

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 #ifdef LITTLEENDIAN
00116   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); }
00117   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); }
00118   inline static unsigned int encode(const double x, FILE* f)                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00119   inline static unsigned int decode(double& x, FILE* f)                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00120   
00121   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); }
00122   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); }
00123   inline static unsigned int encode(const float x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00124   inline static unsigned int decode(float& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00125 
00126   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); }
00127   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); }
00128   inline static unsigned int encode(const long x, FILE* f)                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00129   inline static unsigned int decode(long& x, FILE* f)                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00130   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); }
00131   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); }
00132   inline static unsigned int encode(const unsigned long x, FILE* f)                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00133   inline static unsigned int decode(unsigned long& x, FILE* f)                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00134   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); }
00135   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); }
00136   inline static unsigned int encode(const int x, FILE* f)                            { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00137   inline static unsigned int decode(int& x, FILE* f)                                 { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00138   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); }
00139   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); }
00140   inline static unsigned int encode(const unsigned int x, FILE* f)                   { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00141   inline static unsigned int decode(unsigned int& x, FILE* f)                        { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00142   
00143   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); }
00144   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); }
00145   inline static unsigned int encode(const short x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00146   inline static unsigned int decode(short& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00147   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); }
00148   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); }
00149   inline static unsigned int encode(const unsigned short x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00150   inline static unsigned int decode(unsigned short& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00151   
00152 #else //BIGENDIAN
00153   
00154   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); }
00155   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);}
00156   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); }
00157   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);}
00158   
00159   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); }
00160   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);}
00161   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); }
00162   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);}
00163   
00164   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); }
00165   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);}
00166   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); }
00167   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);}
00168   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); }
00169   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);}
00170   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); }
00171   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);}
00172   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); }
00173   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);}
00174   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); }
00175   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);}
00176   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); }
00177   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);}
00178   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); }
00179   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);}
00180   
00181   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); }
00182   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);}
00183   inline static unsigned int encode(const short x, FILE* f)                           { short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00184   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);}
00185   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); }
00186   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);}
00187   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); }
00188   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);}
00189 #endif //BIG/LITTLE ENDIAN
00190   
00191   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; }
00192   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; }
00193   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); }
00194   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; }
00195   
00196   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; }
00197   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; }
00198   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); }
00199   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; }
00200   
00201   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); }
00202   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);}
00203   inline static unsigned int encode(const char x, FILE* f)                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00204   inline static unsigned int decode(char& x, FILE* f)                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00205   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); }
00206   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);}
00207   inline static unsigned int encode(const unsigned char x, FILE* f)                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00208   inline static unsigned int decode(unsigned char& x, FILE* f)                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00209   
00210   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); }
00211   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);}
00212   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); }
00213   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); }
00214   //@}  
00215 protected:
00216   //!templated function to swap byte ordering, should allow compiler to unroll the loop @warning don't use this if src==dst!!!
00217   template<class T> inline static void byteswap(T& dstc, const T& srcc) {
00218     char* dst=(char*)&dstc;
00219     const char* src=(const char*)&srcc;
00220     for(unsigned int i=0; i<sizeof(T); i++)
00221       dst[sizeof(T)-1-i]=src[i];
00222   }
00223 };
00224 
00225 
00226 /*! @file
00227  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00228  * @todo detect appropriate byte ordering for other platforms
00229  * @author ejt (Creator)
00230  *
00231  * $Author: ejt $
00232  * $Name: tekkotsu-1_4_1 $
00233  * $Revision: 1.3 $
00234  * $State: Exp $
00235  * $Date: 2003/01/10 07:45:21 $
00236  */
00237 
00238 #endif

Tekkotsu v1.4
Generated Sat Jul 19 00:06:31 2003 by Doxygen 1.3.2