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