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