00001 
00002 #ifndef INCLUDED_LoadSave_h
00003 #define INCLUDED_LoadSave_h
00004 
00005 #include <cstdlib>
00006 #include <cstring>
00007 #include <string>
00008 #include <sys/param.h>
00009 #include <stdexcept>
00010 #include <stdarg.h>
00011 #include <cstdio>
00012 #include <iosfwd>
00013 #include "attributes.h"
00014 
00015 #ifdef PLATFORM_APERIOS
00016 
00017 int vasprintf(char** ret, const char* format, va_list al);
00018 #endif
00019 
00020 
00021 
00022 
00023 
00024 
00025 #ifndef LOADSAVE_SWAPBYTES
00026 
00027 #ifdef BYTE_ORDER
00028 #  if BYTE_ORDER == BIG_ENDIAN
00029 #    define LOADSAVE_SWAPBYTES 1
00030 #  elif BYTE_ORDER == LITTLE_ENDIAN
00031 #    define LOADSAVE_SWAPBYTES 0
00032 #  else
00033 #    warning unknown byte ordering for current platform, assuming no swap
00034 #    define LOADSAVE_SWAPBYTES 0
00035 #  endif
00036 #else
00037 
00038 
00039 #  ifdef PLATFORM_APERIOS
00040 
00041 #    define LOADSAVE_SWAPBYTES 0
00042 #  else
00043 #    warning unknown byte ordering for current platform, assuming no swap
00044 #    define LOADSAVE_SWAPBYTES 0
00045 #  endif
00046 #endif
00047 
00048 #endif
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 class LoadSave {
00100  public:
00101 
00102   static const unsigned int stringpad=sizeof(unsigned int)+1;
00103 
00104 
00105 
00106   LoadSave() {}
00107   virtual ~LoadSave(); 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115   
00116 
00117 
00118 
00119 
00120 
00121 
00122   virtual unsigned int getBinSize() const =0;
00123 
00124 
00125 
00126 
00127   virtual unsigned int loadBuffer(const char buf[], unsigned int len, const char* filename=NULL)=0;
00128 
00129 
00130 
00131 
00132   virtual unsigned int saveBuffer(char buf[], unsigned int len) const =0;
00133 
00134 
00135 
00136 
00137 
00138 
00139   virtual unsigned int loadFile(const char* filename);
00140   virtual unsigned int saveFile(const char* filename) const;
00141   
00142 
00143 
00144 
00145   virtual unsigned int loadFileStream(FILE* f, const char* filename=NULL);
00146 
00147 
00148 
00149   virtual unsigned int saveFileStream(FILE* f) const;
00150   
00151 
00152   virtual unsigned int saveStream(std::ostream& os) const;
00153 
00154 
00155   virtual unsigned int LoadFile(const char* filename) ATTR_deprecated;
00156 
00157   virtual unsigned int SaveFile(const char* filename) const ATTR_deprecated;
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166   static inline bool checkInc(int res, const char*& buf, unsigned int& len) throw();
00167   
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175   static inline bool checkInc(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00176   
00177 
00178 
00179 
00180 
00181 
00182 
00183   static inline bool checkInc(int res, char*& buf, unsigned int& len) throw();
00184   
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192   static inline bool checkInc(int res, char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00193   
00194 
00195 
00196 
00197 
00198 
00199 
00200   static inline void checkIncT(int res, const char*& buf, unsigned int& len, const char* msg="LoadSave::check underflow", ...) throw(std::length_error) __attribute__((format(printf,4,5)));
00201   
00202 
00203 
00204 
00205 
00206 
00207 
00208   static inline void checkIncT(int res, char*& buf, unsigned int& len, const char* msg="LoadSave::check underflow", ...) throw(std::length_error) __attribute__((format(printf,4,5)));
00209   
00210 
00211 
00212 
00213 
00214 
00215   template <class T> static inline bool encodeInc(const T& value, char*& buf, unsigned int& cap) throw();
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223   template <class T> static inline bool encodeInc(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00224 
00225 
00226 
00227 
00228 
00229 
00230   template <class T> static inline bool decodeInc(T& value, const char*& buf, unsigned int& cap) throw();
00231   
00232 
00233 
00234 
00235 
00236 
00237 
00238   template <class T> static inline bool decodeInc(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00239   
00240 
00241 
00242 
00243 
00244 
00245   template <class T> static inline bool decodeInc(T& value, char*& buf, unsigned int& cap) throw();
00246   
00247 
00248 
00249 
00250 
00251 
00252 
00253   template <class T> static inline bool decodeInc(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00254   
00255 
00256 
00257 
00258 
00259 
00260   template <class T> static inline void encodeIncT(const T& value, char*& buf, unsigned int& cap, const char* msg="LoadSave::encode overflow", ...) throw(std::length_error) __attribute__((format(printf,4,5)));
00261 
00262 
00263 
00264 
00265 
00266 
00267   template <class T> static inline void decodeIncT(T& value, const char*& buf, unsigned int& cap, const char* msg="LoadSave::decode underflow", ...) throw(std::length_error) __attribute__((format(printf,4,5)));
00268   
00269 
00270 
00271 
00272 
00273 
00274   template <class T> static inline void decodeIncT(T& value, char*& buf, unsigned int& cap, const char* msg="LoadSave::decode underflow", ...) throw(std::length_error) __attribute__((format(printf,4,5)));
00275   
00276 
00277   static bool chkAdvance(int res, const char** buf, unsigned int* len, const char* msg, ...) ATTR_deprecated __attribute__((format(printf,4,5)));
00278 
00279 
00280 
00281 
00282 
00283   inline static unsigned int getSerializedSize(const LoadSave& x) throw() { return x.getBinSize(); }
00284   inline static unsigned int getSerializedSize(const std::string& x) throw() { return x.size()+stringpad; }
00285   inline static unsigned int getSerializedSize(const char* x) throw() { unsigned int sz=strlen(x); return sz+stringpad; }
00286   inline static unsigned int getSerializedSize(const void*) throw() { return sizeof(unsigned long long); }
00287   inline static unsigned int getSerializedSize(const bool&) throw() { return sizeof(char); }
00288   template <class T> inline static unsigned int getSerializedSize(const T& x) throw() { return sizeof(x); }
00289 
00290   template <class T> inline static unsigned int getSerializedSize() { throw std::invalid_argument("The template argument passed to getSerializedSize() is not supported by LoadSave"); }
00291 
00292   
00293   
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00302 
00303 
00304 
00305 
00306 
00307 
00308   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const throw();
00309 
00310 
00311 
00312 
00313 
00314 
00315   virtual bool checkCreatorInc(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw();
00316 
00317 
00318 
00319 
00320 
00321   virtual void checkCreatorIncT(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw(std::runtime_error);
00322 
00323 
00324 
00325 
00326 
00327   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const throw();
00328 
00329 
00330 
00331 
00332 
00333   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const throw();
00334 
00335 
00336 
00337 
00338 
00339   virtual bool saveCreatorInc(const char* creator, char*& buf, unsigned int& len) const throw();
00340 
00341 
00342 
00343 
00344   virtual void saveCreatorIncT(const char* creator, char*& buf, unsigned int& len) const throw(std::runtime_error);
00345 
00346 
00347 
00348 
00349   virtual unsigned int saveCreator(const char* creator, FILE* f) const throw();
00350 
00351 
00352   
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362   inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap) { return x.saveBuffer(buf,cap); }
00363   inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap) { return x.loadBuffer(buf,cap); }
00364   inline static unsigned int encode(const LoadSave& x, FILE* f)                 { return x.saveFileStream(f); }
00365   inline static unsigned int decode(LoadSave& x, FILE* f)                       { return x.loadFileStream(f); }
00366   
00367 #if LOADSAVE_SWAPBYTES
00368   
00369   inline static unsigned int encode(const double x, char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; byteswap(*(double*)buf,x); return sizeof(x); }
00370   inline static unsigned int decode(double& x, const char buf[], unsigned int cap) throw()        { if(cap<sizeof(x)) return 0; byteswap(x,*(const double*)buf); return sizeof(x);}
00371   inline static unsigned int encode(const double x, FILE* f) throw()                         { double t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00372   inline static unsigned int decode(double& x, FILE* f) throw()                              { double t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00373   
00374   inline static unsigned int encode(const float x, char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; byteswap(*(float*)buf,x); return sizeof(x); }
00375   inline static unsigned int decode(float& x, const char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; byteswap(x,*(const float*)buf); return sizeof(x);}
00376   inline static unsigned int encode(const float x, FILE* f) throw()                          { float t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00377   inline static unsigned int decode(float& x, FILE* f) throw()                               { float t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00378   
00379   inline static unsigned int encode(const long long x, char buf[], unsigned int cap) throw()           { if(cap<sizeof(x)) return 0; byteswap(*(long long*)buf,x); return sizeof(x); }
00380   inline static unsigned int decode(long long& x, const char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; byteswap(x,*(const long long*)buf); return sizeof(x);}
00381   inline static unsigned int encode(const long long x, FILE* f) throw()                           { long long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00382   inline static unsigned int decode(long long& x, FILE* f) throw()                                { long long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00383   inline static unsigned int encode(const unsigned long long x, char buf[], unsigned int cap) throw()  { if(cap<sizeof(x)) return 0; byteswap(*(unsigned long long*)buf,x); return sizeof(x); }
00384   inline static unsigned int decode(unsigned long long& x, const char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned long long*)buf); return sizeof(x);}
00385   inline static unsigned int encode(const unsigned long long x, FILE* f) throw()                  { unsigned long long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00386   inline static unsigned int decode(unsigned long long& x, FILE* f) throw()                       { unsigned long long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00387   
00388   inline static unsigned int encode(const long x, char buf[], unsigned int cap) throw()           { if(cap<sizeof(x)) return 0; byteswap(*(long*)buf,x); return sizeof(x); }
00389   inline static unsigned int decode(long& x, const char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; byteswap(x,*(const long*)buf); return sizeof(x);}
00390   inline static unsigned int encode(const long x, FILE* f) throw()                           { long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00391   inline static unsigned int decode(long& x, FILE* f) throw()                                { long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00392   inline static unsigned int encode(const unsigned long x, char buf[], unsigned int cap) throw()  { if(cap<sizeof(x)) return 0; byteswap(*(unsigned long*)buf,x); return sizeof(x); }
00393   inline static unsigned int decode(unsigned long& x, const char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned long*)buf); return sizeof(x);}
00394   inline static unsigned int encode(const unsigned long x, FILE* f) throw()                  { unsigned long t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00395   inline static unsigned int decode(unsigned long& x, FILE* f) throw()                       { unsigned long t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00396   
00397   inline static unsigned int encode(const int x, char buf[], unsigned int cap) throw()            { if(cap<sizeof(x)) return 0; byteswap(*(int*)buf,x); return sizeof(x); }
00398   inline static unsigned int decode(int& x, const char buf[], unsigned int cap) throw()           { if(cap<sizeof(x)) return 0; byteswap(x,*(const int*)buf); return sizeof(x);}
00399   inline static unsigned int encode(const int x, FILE* f) throw()                            { int t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00400   inline static unsigned int decode(int& x, FILE* f) throw()                                 { int t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00401   inline static unsigned int encode(const unsigned int x, char buf[], unsigned int cap) throw()   { if(cap<sizeof(x)) return 0; byteswap(*(unsigned int*)buf,x); return sizeof(x); }
00402   inline static unsigned int decode(unsigned int& x, const char buf[], unsigned int cap) throw()  { if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned int*)buf); return sizeof(x);}
00403   inline static unsigned int encode(const unsigned int x, FILE* f) throw()                   { unsigned int t=0; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00404   inline static unsigned int decode(unsigned int& x, FILE* f) throw()                        { unsigned int t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00405   
00406   inline static unsigned int encode(const short x, char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; byteswap(*(short*)buf,x); return sizeof(x); }
00407   inline static unsigned int decode(short& x, const char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; byteswap(x,*(const short*)buf); return sizeof(x);}
00408   inline static unsigned int encode(const short x, FILE* f) throw()                          { short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00409   inline static unsigned int decode(short& x, FILE* f) throw()                               { short t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00410   inline static unsigned int encode(const unsigned short x, char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; byteswap(*(unsigned short*)buf,x); return sizeof(x); }
00411   inline static unsigned int decode(unsigned short& x, const char buf[], unsigned int cap) throw(){ if(cap<sizeof(x)) return 0; byteswap(x,*(const unsigned short*)buf); return sizeof(x);}
00412   inline static unsigned int encode(const unsigned short x, FILE* f) throw()                 { unsigned short t; byteswap(t,x); return sizeof(x)*fwrite(&t,sizeof(x),1,f); }
00413   inline static unsigned int decode(unsigned short& x, FILE* f) throw()                      { unsigned short t=0; if(fread(&t,sizeof(x),1,f)==0) return 0; byteswap(x,t); return sizeof(x);}
00414 
00415 #else
00416   
00417   inline static unsigned int encode(const double x, char buf[], unsigned int cap) throw()        { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00418   inline static unsigned int decode(double& x, const char buf[], unsigned int cap) throw()       { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00419   inline static unsigned int encode(const double x, FILE* f) throw()                        { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00420   inline static unsigned int decode(double& x, FILE* f) throw()                             { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00421   
00422   inline static unsigned int encode(const float x, char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00423   inline static unsigned int decode(float& x, const char buf[], unsigned int cap) throw()        { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00424   inline static unsigned int encode(const float x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00425   inline static unsigned int decode(float& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00426 
00427   inline static unsigned int encode(const long long x, char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00428   inline static unsigned int decode(long long& x, const char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00429   inline static unsigned int encode(const long long x, FILE* f) throw()                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00430   inline static unsigned int decode(long long& x, FILE* f) throw()                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00431   inline static unsigned int encode(const unsigned long long x, char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00432   inline static unsigned int decode(unsigned long long& x, const char buf[], unsigned int cap) throw(){ if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00433   inline static unsigned int encode(const unsigned long long x, FILE* f) throw()                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00434   inline static unsigned int decode(unsigned long long& x, FILE* f) throw()                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00435   
00436   inline static unsigned int encode(const long x, char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00437   inline static unsigned int decode(long& x, const char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00438   inline static unsigned int encode(const long x, FILE* f) throw()                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00439   inline static unsigned int decode(long& x, FILE* f) throw()                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00440   inline static unsigned int encode(const unsigned long x, char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00441   inline static unsigned int decode(unsigned long& x, const char buf[], unsigned int cap) throw(){ if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00442   inline static unsigned int encode(const unsigned long x, FILE* f) throw()                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00443   inline static unsigned int decode(unsigned long& x, FILE* f) throw()                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00444   
00445   inline static unsigned int encode(const int x, char buf[], unsigned int cap) throw()           { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00446   inline static unsigned int decode(int& x, const char buf[], unsigned int cap) throw()          { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00447   inline static unsigned int encode(const int x, FILE* f) throw()                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00448   inline static unsigned int decode(int& x, FILE* f) throw()                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00449   inline static unsigned int encode(const unsigned int x, char buf[], unsigned int cap) throw()  { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00450   inline static unsigned int decode(unsigned int& x, const char buf[], unsigned int cap) throw() { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00451   inline static unsigned int encode(const unsigned int x, FILE* f) throw()                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00452   inline static unsigned int decode(unsigned int& x, FILE* f) throw()                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00453   
00454   inline static unsigned int encode(const short x, char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00455   inline static unsigned int decode(short& x, const char buf[], unsigned int cap) throw()        { if(cap<sizeof(x)) return 0; memcpy(&x,buf,sizeof(x)); return sizeof(x); }
00456   inline static unsigned int encode(const short x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00457   inline static unsigned int decode(short& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00458   inline static unsigned int encode(const unsigned short x, char buf[], unsigned int cap) throw(){ if(cap<sizeof(x)) return 0; memcpy(buf,&x,sizeof(x)); return sizeof(x); }
00459   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); }
00460   inline static unsigned int encode(const unsigned short x, FILE* f) throw()                { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00461   inline static unsigned int decode(unsigned short& x, FILE* f) throw()                     { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00462 
00463 #endif //end of big/little endian differences
00464   
00465   
00466 
00467 
00468 
00469   
00470   
00471   
00472   
00473   inline static unsigned int encode(const std::string& x, char buf[], unsigned int cap) throw() { if(cap<sizeof(unsigned int)+x.size()+1) return 0; memcpy(buf+encode(static_cast<unsigned int>(x.size()),buf,cap),x.c_str(),x.size()+1); return x.size()+stringpad; }
00474   inline static unsigned int decode(std::string& x, const char buf[], unsigned int cap) throw() { 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; }
00475   inline static unsigned int encode(const std::string& x, FILE* f) throw()                 { encode(static_cast<unsigned int>(x.size()),f); return sizeof(unsigned int)+fwrite(x.c_str(),1,sizeof(x)+1,f); }
00476   inline static unsigned int decode(std::string& x, FILE* f) throw()                       { 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; }
00477   
00478   inline static unsigned int encode(const char* x, char buf[], unsigned int cap) throw()     { 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; }
00479   inline static unsigned int decode(char*& x, const char buf[], unsigned int cap) throw()    { 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; }
00480   inline static unsigned int encode(const char* x, FILE* f) throw()                     { unsigned int sz=strlen(x); encode(sz,f); return sizeof(unsigned int)+fwrite(x,1,sz+1,f); }
00481   inline static unsigned int decode(char*& x, FILE* f) throw()                          { 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; }
00482   
00483   inline static unsigned int encode(const char x, char buf[], unsigned int cap) throw()         { if(cap<sizeof(x)) return 0; buf[0]=x; return sizeof(x); }
00484   inline static unsigned int decode(char& x, const char buf[], unsigned int cap) throw()        { if(cap<sizeof(x)) return 0; x=buf[0]; return sizeof(x);}
00485   inline static unsigned int encode(const char x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00486   inline static unsigned int decode(char& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00487   inline static unsigned int encode(const unsigned char x, char buf[], unsigned int cap) throw(){ if(cap<sizeof(x)) return 0; buf[0]=(char)x; return sizeof(x); }
00488   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);}
00489   inline static unsigned int encode(const unsigned char x, FILE* f) throw()                { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00490   inline static unsigned int decode(unsigned char& x, FILE* f) throw()                     { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00491   
00492   inline static unsigned int encode(const bool x, char buf[], unsigned int cap) throw()         { if(cap<sizeof(char)) return 0; buf[0]=(char)(x?1:0); return sizeof(char); }
00493   inline static unsigned int decode(bool& x, const char buf[], unsigned int cap) throw()        { if(cap<sizeof(char)) return 0; x=(buf[0]!=(char)0); return sizeof(char);}
00494   inline static unsigned int encode(const bool x, FILE* f) throw()                         { char t=(char)(x?1:0); return sizeof(char)*fwrite(&t,sizeof(char),1,f); }
00495   inline static unsigned int decode(bool& x, FILE* f) throw()                              { char t='\0'; if(fread(&t,sizeof(char),1,f)!=1) return 0; x=(t!=(char)0); return sizeof(char); }
00496 
00497 protected:
00498 
00499   template<class T> inline static void byteswap(T& dstc, const T& srcc) throw() {
00500     char* dst=(char*)&dstc;
00501     const char* src=(const char*)&srcc;
00502     for(unsigned int i=0; i<sizeof(T); i++)
00503       dst[sizeof(T)-1-i]=src[i];
00504   }
00505 
00506 
00507 #if defined(NEED_ASPRINTF)
00508   int vasprintf(char** ret, const char* format, va_list al) {
00509     va_list tmpal;
00510     va_copy(tmpal,al);
00511     int nc=vsnprintf(NULL,0,format,tmpal);
00512     *ret = (char*)malloc(nc+1);
00513     if(*ret==NULL) return -1;
00514     return vsnprintf(*ret,nc+1,format,al);
00515   }
00516   int asprintf(char **ret, const char *format, ...) {
00517     va_list ap;
00518     va_start (ap, format);
00519     int nc= vasprintf(ret, format, ap);
00520     va_end(ap);
00521     return nc;
00522   }
00523 #endif
00524 };
00525 
00526 
00527 #ifndef __DOXYGEN__
00528 
00529 template <> inline unsigned int LoadSave::getSerializedSize<void*>() { return sizeof(unsigned long long); }
00530 template <> inline unsigned int LoadSave::getSerializedSize<bool>() { return sizeof(char); }
00531 template <> inline unsigned int LoadSave::getSerializedSize<char>() { return sizeof(char); }
00532 template <> inline unsigned int LoadSave::getSerializedSize<unsigned char>() { return sizeof(unsigned char); }
00533 template <> inline unsigned int LoadSave::getSerializedSize<short>() { return sizeof(short); }
00534 template <> inline unsigned int LoadSave::getSerializedSize<unsigned short>() { return sizeof(unsigned short); }
00535 template <> inline unsigned int LoadSave::getSerializedSize<int>() { return sizeof(int); }
00536 template <> inline unsigned int LoadSave::getSerializedSize<unsigned int>() { return sizeof(unsigned int); }
00537 template <> inline unsigned int LoadSave::getSerializedSize<long>() { return sizeof(long); }
00538 template <> inline unsigned int LoadSave::getSerializedSize<unsigned long>() { return sizeof(unsigned long); }
00539 template <> inline unsigned int LoadSave::getSerializedSize<long long>() { return sizeof(long long); }
00540 template <> inline unsigned int LoadSave::getSerializedSize<unsigned long long>() { return sizeof(unsigned long long); }
00541 template <> inline unsigned int LoadSave::getSerializedSize<float>() { return sizeof(float); }
00542 template <> inline unsigned int LoadSave::getSerializedSize<double>() { return sizeof(double); }
00543 
00544 template <> inline unsigned int LoadSave::getSerializedSize<char*>() { throw std::invalid_argument("Cannot pass string as template arg to getSerializedSize() -- need instance to know length!"); }
00545 template <> inline unsigned int LoadSave::getSerializedSize<std::string>() { throw std::invalid_argument("Cannot pass string as template arg to getSerializedSize() -- need instance to know length!"); }
00546 template <> inline unsigned int LoadSave::getSerializedSize<LoadSave>() { throw std::invalid_argument("Cannot pass LoadSave subclass as template arg to getSerializedSize() -- need instance to know length!\nIf the subclass in question has a static size, you could add a getSerializedSize() template specialization to do the size calculation (and have getBinSize return that)."); }
00547 #endif
00548 
00549 bool LoadSave::checkInc(int res, const char*& buf, unsigned int& len) throw() {
00550   if(res<0 || (unsigned int)res>len)
00551     return false;
00552   buf+=res;
00553   len-=res;
00554   return true;
00555 }
00556 
00557 bool LoadSave::checkInc(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw() {
00558   if(checkInc(res,buf,len))
00559     return true;
00560   if(msg[0]!='\0') {
00561     if((unsigned int)res>len)
00562       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00563     va_list al;
00564     va_start(al,msg);
00565     vfprintf(stderr,msg,al);
00566     va_end(al);
00567   }
00568   return false;
00569 }
00570 
00571 bool LoadSave::checkInc(int res, char*& buf, unsigned int& len) throw() {
00572   if(res<0 || (unsigned int)res>len)
00573     return false;
00574   buf+=res;
00575   len-=res;
00576   return true;
00577 }
00578 
00579 bool LoadSave::checkInc(int res, char*& buf, unsigned int& len, const char* msg, ...) throw() {
00580   if(checkInc(res,buf,len))
00581     return true;
00582   if(msg[0]!='\0') {
00583     if((unsigned int)res>len)
00584       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00585     va_list al;
00586     va_start(al,msg);
00587     vfprintf(stderr,msg,al);
00588     va_end(al);
00589   }
00590   return false;
00591 }
00592 
00593 void LoadSave::checkIncT(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw(std::length_error) {
00594   if(res>0 && (unsigned int)res<=len) {
00595     buf+=res;
00596     len-=res;
00597   } else {
00598     if((unsigned int)res>len && msg[0]!='\0')
00599       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00600     va_list al;
00601     va_start(al,msg);
00602     char * errmsg;
00603     int nc = vasprintf(&errmsg,msg,al);
00604     va_end(al);
00605     if(errmsg==NULL)
00606       throw std::length_error("unspecified");
00607     std::string serrmsg=errmsg;
00608     free(errmsg);
00609     if(nc<0)
00610       throw std::length_error("error generating error message!");
00611     throw std::length_error(serrmsg);
00612   }
00613 }
00614 
00615 void LoadSave::checkIncT(int res, char*& buf, unsigned int& len, const char* msg, ...) throw(std::length_error) {
00616   if(res>0 && (unsigned int)res<=len) {
00617     buf+=res;
00618     len-=res;
00619   } else {
00620     if((unsigned int)res>len && msg[0]!='\0')
00621       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00622     va_list al;
00623     va_start(al,msg);
00624     char * errmsg;
00625     int nc = vasprintf(&errmsg,msg,al);
00626     va_end(al);
00627     if(errmsg==NULL)
00628       throw std::length_error("unspecified");
00629     std::string serrmsg=errmsg;
00630     free(errmsg);
00631     if(nc<0)
00632       throw std::length_error("error generating error message!");
00633     throw std::length_error(serrmsg);
00634   }
00635 }
00636 
00637 template <class T>
00638 bool LoadSave::encodeInc(const T& value, char*& buf, unsigned int& cap) throw() {
00639   unsigned int res=encode(value,buf,cap);
00640   if(res==0)
00641     return false;
00642 #ifdef LOADSAVE_DEBUG
00643   if(res>cap) {
00644     fprintf(stderr,"*** WARNING: reported encode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00645     return false;
00646   }
00647 #endif
00648   buf+=res;
00649   cap-=res;
00650   return true;
00651 }
00652 template <class T>
00653 bool LoadSave::encodeInc(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00654   if(encodeInc(value,buf,cap))
00655     return true;
00656   if(msg[0]!='\0') {
00657     va_list al;
00658     va_start(al,msg);
00659     vfprintf(stderr,msg,al);
00660     va_end(al);
00661   }
00662   return false;
00663 }
00664 template <class T>
00665 bool LoadSave::decodeInc(T& value, const char*& buf, unsigned int& cap) throw() {
00666   unsigned int res=decode(value,buf,cap);
00667   if(res==0)
00668     return false;
00669 #ifdef LOADSAVE_DEBUG
00670   if(res>cap) {
00671     fprintf(stderr,"*** WARNING: reported decode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00672     return false;
00673   }
00674 #endif
00675   buf+=res;
00676   cap-=res;
00677   return true;
00678 }
00679 template <class T>
00680 bool LoadSave::decodeInc(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00681   if(decodeInc(value,buf,cap))
00682     return true;
00683   if(msg[0]!='\0') {
00684     va_list al;
00685     va_start(al,msg);
00686     vfprintf(stderr,msg,al);
00687     va_end(al);
00688   }
00689   return false;
00690 }
00691 template <class T>
00692 bool LoadSave::decodeInc(T& value, char*& buf, unsigned int& cap) throw() {
00693   unsigned int res=decode(value,buf,cap);
00694   if(res==0)
00695     return false;
00696 #ifdef LOADSAVE_DEBUG
00697   if(res>cap) {
00698     fprintf(stderr,"*** WARNING: reported decode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00699     return false;
00700   }
00701 #endif
00702   buf+=res;
00703   cap-=res;
00704   return true;
00705 }
00706 template <class T>
00707 bool LoadSave::decodeInc(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00708   if(decodeInc(value,buf,cap))
00709     return true;
00710   if(msg[0]!='\0') {
00711     va_list al;
00712     va_start(al,msg);
00713     vfprintf(stderr,msg,al);
00714     va_end(al);
00715   }
00716   return false;
00717 }
00718 
00719 template <class T>
00720 void LoadSave::encodeIncT(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00721   unsigned int res=encode(value,buf,cap);
00722 #ifdef LOADSAVE_DEBUG
00723   if(res==0 || res>cap) {
00724     if(res>cap)
00725       fprintf(stderr,"*** WARNING: encode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00726 #else
00727   if(res==0) {
00728 #endif
00729     va_list al;
00730     va_start(al,msg);
00731     char * errmsg;
00732     vasprintf(&errmsg,msg,al);
00733     va_end(al);
00734     if(errmsg==NULL)
00735       throw std::length_error("unspecified");
00736     std::string serrmsg=errmsg;
00737     free(errmsg);
00738     throw std::length_error(serrmsg);
00739 
00740 #ifdef LOADSAVE_DEBUG
00741   }
00742 #else
00743   }
00744 #endif
00745   buf+=res;
00746   cap-=res;
00747 }
00748 template <class T>
00749 void LoadSave::decodeIncT(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00750   unsigned int res=decode(value,buf,cap);
00751 #ifdef LOADSAVE_DEBUG
00752   if(res==0 || res>cap) {
00753     if(res>cap)
00754       fprintf(stderr,"*** WARNING: decode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00755 #else
00756   if(res==0) {
00757 #endif
00758     va_list al;
00759     va_start(al,msg);
00760     char * errmsg;
00761     vasprintf(&errmsg,msg,al);
00762     va_end(al);
00763     if(errmsg==NULL)
00764       throw std::length_error("unspecified");
00765     std::string serrmsg=errmsg;
00766     free(errmsg);
00767     throw std::length_error(serrmsg);
00768 
00769 #ifdef LOADSAVE_DEBUG
00770   }
00771 #else
00772   }
00773 #endif
00774   buf+=res;
00775   cap-=res;
00776 }
00777 template <class T>
00778 void LoadSave::decodeIncT(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00779   unsigned int res=decode(value,buf,cap);
00780 #ifdef LOADSAVE_DEBUG
00781   if(res==0 || res>cap) {
00782     if(res>cap)
00783       fprintf(stderr,"*** WARNING: decode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00784 #else
00785   if(res==0) {
00786 #endif
00787     va_list al;
00788     va_start(al,msg);
00789     char * errmsg;
00790     vasprintf(&errmsg,msg,al);
00791     va_end(al);
00792     if(errmsg==NULL)
00793       throw std::length_error("unspecified");
00794     std::string serrmsg=errmsg;
00795     free(errmsg);
00796     throw std::length_error(serrmsg);
00797 
00798 #ifdef LOADSAVE_DEBUG
00799   }
00800 #else
00801   }
00802 #endif
00803   buf+=res;
00804   cap-=res;
00805 }
00806 
00807 
00808 
00809 
00810 
00811 
00812 
00813 #endif