Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

LoadSave.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_LoadSave_h
00003 #define INCLUDED_LoadSave_h
00004 
00005 #include <string>
00006 #include <sys/param.h>
00007 #include <stdexcept>
00008 #include <stdarg.h>
00009 #include "Shared/attributes.h"
00010 
00011 #ifdef PLATFORM_APERIOS
00012 //! prototype declared only on PLATFORM_APERIOS; system provides an implementation, but apparently no API declaration
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 //aperios distribution doesn't actually define BYTE_ORDER :(
00029 //just as well, since we're using that byte order anyway
00030 #  ifdef PLATFORM_APERIOS
00031 //!On PLATFORM_APERIOS, we avoid swapping bytes, since it's likely to be the most CPU constrained platform
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 //! Intended as an interface to allow easy and portable serialization operations
00042 /*! Generally, for triggering serialization of a LoadSave subclass, all you need to know is to call saveFile() /
00043     saveBuffer() in order to have the class serialize itself, and loadFile() /
00044     loadBuffer() in order to reload the data.
00045     
00046     When saveFile() is called, it checks that it can open the specified file, and then calls
00047     saveFileStream() with the open file.  This will then check getBinSize(), create a buffer of that
00048     size, and call saveBuffer() to do the actual work of serialization into that buffer.  If
00049     saveBuffer is successful, saveFileStream() copies the buffer out to the file, and then finally,
00050     saveFile() will close the file.
00051     
00052     This means when writing a class which requires serialization, you need only define 3 functions:
00053     loadBuffer(), saveBuffer(), and getBinSize().  If you are saving directly into a file and need
00054     the highest possible performance, overriding loadFileStream and saveFileStream and
00055     reimplementing the serialization operations into the file stream can save a buffer copy.
00056     Usually this is not a performance issue, but the interface is there if you need it.
00057     
00058     The recommended style for using LoadSave in classes with multiple levels of inheritance is to
00059     have each subclass first call the superclass's implementation (e.g. of loadBuffer/saveBuffer),
00060     and then save their own data afterward.  This compartmentalizes the data access and makes it
00061     easy to maintain - the code that serializes is right in with the code that defines the
00062     structure.  If you change one, it's easy to see where to change the other.  And protection
00063     between levels of inheritance is retained.  (This is why I say it's highly
00064     flexible/maintainable, but poor readability since the serialization is all broken up.)
00065     
00066     I also recommend putting a little string header at the beginning of each class's info via saveCreator() and checkCreator().  This
00067     will allow polymorphism when loading files (you can look at the string and create the
00068     appropriate type) but also is handy for checking field alignment... it's a lot easier to tell
00069     how much you're offset within a string than to do the same with a stream of binary values.
00070     Further, you can use the string as version information if you want to be backward compatible in
00071     future versions of your code.
00072   
00073     LoadSave provides a series of encode() and decode() functions for all the primitive types.  This
00074     will handle copying the value into the buffer or file, and can provide platform independence
00075     through byte swapping if needed (there's a compiler flag you can set for platforms that have the
00076     opposite byte order, although this should be autodetected from the system headers).
00077     Most of these are pretty straightfoward - an int is just 4 bytes and so on.
00078   
00079     However, there's one caveat that I want to make sure to point out if you have to write parsing
00080     code in say, Java.  Strings are encoded by first storing an int to hold the string's length,
00081     then the string itself, and then a null character.  This adds 5 bytes to the length of any
00082     string, but makes loading the files much easier/faster - you can call string library functions
00083     directly on the buffer if it's already in memory since the string is null terminated, or can
00084     allocate memory to hold the string with one pass from a file because you'll know the
00085     size of the string before you get to it.
00086   
00087     Of course, the string serialization format is transparent if you just stick to using LoadSave's
00088     encode/decode functions to parse it.
00089 */
00090 class LoadSave {
00091  public:
00092   //! This is the amount of extra space needed to store a string (int for len of string plus 1 for @code '\0' @endcode termination)
00093   static const unsigned int stringpad=sizeof(unsigned int)+1;
00094 
00095   //!@name Constructors/Destructors
00096   /*! @brief constructor */
00097   LoadSave() {}
00098   virtual ~LoadSave(); //!< destructor
00099   //@}
00100 
00101   /*! @brief These are useful for sending the data across a network as well as to a file.\n
00102    *  These three functions (getBinSize(), loadBuffer(), saveBuffer() ) are the only ones that MUST be
00103    *  overridden, as the file stream versions can be based on calling these.  However, you can override
00104    *  the file stream versions as well if speed or temp. memory is tight. */
00105   //!@name Buffer Operations
00106   
00107   //! Calculates space needed to save - if you can't precisely add up the size, just make sure to overestimate and things will still work.
00108   /*! getBinSize is used for reserving buffers during serialization, but does not necessarily determine
00109    *  the actual size of what is written -- the return value of saveBuffer() specifies that after the data
00110    *  actually has been written.  If getBinSize overestimates, the extra memory allocation is only
00111    *  temporary, no extra filler bytes are actually stored.
00112    *  @return number of bytes read/written, 0 if error (or empty) */
00113   virtual unsigned int getBinSize() const =0;
00114   //! Load from a saved buffer in memory
00115   /*! @param buf pointer to the memory where you should begin loading
00116    *  @param len length of @a buf available (this isn't necessarily all yours, there might be other things following your data)
00117    *  @return the number of bytes actually used */
00118   virtual unsigned int loadBuffer(const char buf[], unsigned int len)=0;
00119   //! Save to a given buffer in memory
00120   /*! @param buf pointer to the memory where you should begin writing
00121    *  @param len length of @a buf available.  (this isn't necessarily all yours, constrain yourself to what you returned in getBinSize() )
00122    *  @return the number of bytes actually used */
00123   virtual unsigned int saveBuffer(char buf[], unsigned int len) const =0;
00124   //@}
00125 
00126   //!These are called to load and save to files
00127   //!@name File Operations
00128   /*!@brief initiate opening of the specified file and loading/saving of all appropriate information.
00129    * @param filename the file to load/save @return number of bytes read/written, 0 if error (or empty)*/
00130   virtual unsigned int loadFile(const char* filename);
00131   virtual unsigned int saveFile(const char* filename) const;
00132   
00133   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00134   /*! @param f a pointer to the file to load
00135    *  @return number of bytes read, 0 if error (or empty) */
00136   virtual unsigned int loadFileStream(FILE* f);
00137   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00138   /*! @param f a pointer to the file to save
00139    *  @return number of bytes written, 0 if error (or empty) */
00140   virtual unsigned int saveFileStream(FILE* f) const;
00141 
00142   //! deprecated, use loadFile() instead (refactored to standardize capitalization style)
00143   virtual unsigned int LoadFile(const char* filename) ATTR_deprecated;
00144   //! deprecated, use saveFile() instead (refactored to standardize capitalization style)
00145   virtual unsigned int SaveFile(const char* filename) const ATTR_deprecated;
00146   //@}
00147 
00148   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() )  If res is 0, returns false
00149   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00150    *  @param res number of bytes used, or 0 if error
00151    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00152    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00153    *  @return true if everything worked, false otherwise */
00154   static inline bool checkInc(int res, const char*& buf, unsigned int& len) throw();
00155   
00156   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() )  If res is 0, displays the specified message on stderr and returns false.
00157   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00158    *  @param res number of bytes used, or 0 if error
00159    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00160    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00161    *  @param msg Error to display if res is less than or equal to zero
00162    *  @return true if everything worked, false otherwise */
00163   static inline bool checkInc(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00164   
00165   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() ).  If res is 0, returns false
00166   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00167    *  @param res number of bytes used, or 0 if error
00168    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00169    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00170    *  @return true if everything worked, false otherwise */
00171   static inline bool checkInc(int res, char*& buf, unsigned int& len) throw();
00172   
00173   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() ).  If res is 0, displays the specified message on stderr and returns false.
00174   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00175    *  @param res number of bytes used, or 0 if error
00176    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00177    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00178    *  @param msg Error to display if res is less than or equal to zero
00179    *  @return true if everything worked, false otherwise */
00180   static inline bool checkInc(int res, char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00181   
00182   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() )  If res is 0, throws a std::length_error with the specified message.
00183   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00184    *  @param res number of bytes used, or 0 if error
00185    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00186    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00187    *  @param msg Error message to throw in the std::length_error if res is less than or equal to zero */
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   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() ).  If res is 0, throws a std::length_error with the specified message.
00191   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00192    *  @param res number of bytes used, or 0 if error
00193    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00194    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00195    *  @param msg Error message to throw in the std::length_error if res is less than or equal to zero */
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   //! Encodes @a value into the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false
00199   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00200    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00201    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00202    *  @return true if everything worked, false otherwise */
00203   template <class T> static inline bool encodeInc(const T& value, char*& buf, unsigned int& cap) throw();
00204 
00205   //! Encodes @a value into the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, displays the specified message on stderr and returns false.
00206   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00207    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00208    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00209    *  @param msg Error to display if @a buf did not have enough capacity
00210    *  @return true if everything worked, false otherwise */
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   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false
00214   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00215    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00216    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00217    *  @return true if everything worked, false otherwise */
00218   template <class T> static inline bool decodeInc(T& value, const char*& buf, unsigned int& cap) throw();
00219   
00220   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, displays the specified message on stderr and returns false.
00221   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00222    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00223    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00224    *  @param msg Error to display if @a buf did not have enough capacity
00225    *  @return true if everything worked, false otherwise */
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   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false.
00229   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00230    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00231    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00232    *  @return true if everything worked, false otherwise */
00233   template <class T> static inline bool decodeInc(T& value, char*& buf, unsigned int& cap) throw();
00234   
00235   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, displays the specified message on stderr and returns false.
00236   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00237    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00238    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00239    *  @param msg Error to display if @a buf did not have enough capacity
00240    *  @return true if everything worked, false otherwise */
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   //! Encodes @a value into the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, throws a std::length_error with the specified message.
00244   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00245    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00246    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00247    *  @param msg Error to display if @a buf did not have enough capacity */
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   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, throws a std::length_error with the specified message.
00251   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00252    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00253    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00254    *  @param msg Error to display if @a buf did not have enough capacity */
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   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, throws a std::length_error with the specified message.
00258   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00259    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00260    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00261    *  @param msg Error to display if @a buf did not have enough capacity */
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   //! deprecated, use checkInc() instead (provides less error-prone interface (NULL not allowed), mixes better with other new *Inc varients)
00265   static bool chkAdvance(int res, const char** buf, unsigned int* len, const char* msg, ...) ATTR_deprecated __attribute__((format(printf,4,5)));
00266 
00267   /*! @brief These are expected to be called from within your own getBinSize implementation in order to add up the size of all the member fields.
00268    *  Use these instead of sizeof() because this allows proper handling of some oddball conditions (bool isn't 1 byte on some platforms, use strlen on char*, etc.) */
00269   //! @name Methods to detect the size member fields
00270   /*! @brief returns the serialized size of the argument */
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   //! this version lets you get the theoretical size of a type, but beware it will throw invalid_argument if you pass a string type! (can't tell the size of the string without an actual instance...)
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   /*! @brief These are for putting creator codes (a uniquely identifying string, e.g. the name of the class) at the beginning of your data -- 
00283    *  doing so is a good idea to allow polymorphism, version detection (backward compatability), or just a sanity check */
00284   //!@name Creator Utilities
00285 
00286   /*!@brief Returns size of the creator code
00287    * @param creator a string to use for the creator
00288    * @return the size to leave for the creator code */
00289   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00290   //! Compares the creator code in the buffer to the one given
00291   /*!@param creator what the creator should be
00292    * @param buf the buffer to check
00293    * @param len the size remaining in the buffer
00294    * @param isLoading set this to true if you want to output a warning if it doesn't match
00295    * @return the number of bytes used by the creator, or 0 if it didn't match */
00296   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const throw();
00297   //! Compares the creator code in the buffer to the one given, increments buf and decrements len if it matches
00298   /*!@param creator what the creator should be
00299    * @param buf the buffer to check
00300    * @param len the size remaining in the buffer
00301    * @param isLoading set this to true if you want to output a warning if it doesn't match
00302    * @return true if it matched, false otherwise */
00303   virtual bool checkCreatorInc(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw();
00304   //! Compares the creator code in the buffer to the one given, increments buf and decrements len if it matches, throws std::runtime_error if it doesn't match
00305   /*!@param creator what the creator should be
00306    * @param buf the buffer to check
00307    * @param len the size remaining in the buffer
00308    * @param isLoading set this to true if you want to output a warning if it doesn't match */
00309   virtual void checkCreatorIncT(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw(std::runtime_error);
00310   //! Compares the creator code in the file to the one given, will attempt to reset the file position if fails (so you can check for one of several types)
00311   /*!@param creator what the creator should be
00312    * @param f the file pointer to check
00313    * @param isLoading set this to true if you want to output a warning if it doesn't match
00314    * @return the number of bytes consumed by the creator code, or 0 if it didn't match */
00315   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const throw();
00316   //! Saves a creator code to a buffer
00317   /*!@param creator the string to use for the creator code
00318    * @param buf the buffer to save the code into
00319    * @param len the space available in the buffer
00320    * @return the number of bytes consumed */
00321   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const throw();
00322   //! Saves a creator code to a buffer, increments buf and decrements len by the amount used
00323   /*!@param creator the string to use for the creator code
00324    * @param buf the buffer to save the code into
00325    * @param len the space available in the buffer
00326    * @return true if successful, false otherwise */
00327   virtual bool saveCreatorInc(const char* creator, char*& buf, unsigned int& len) const throw();
00328   //! Saves a creator code to a buffer, increments buf and decrements len by the amount used
00329   /*!@param creator the string to use for the creator code
00330    * @param buf the buffer to save the code into
00331    * @param len the space available in the buffer */
00332   virtual void saveCreatorIncT(const char* creator, char*& buf, unsigned int& len) const throw(std::runtime_error);
00333   //! Saves a creator code directly to a file
00334   /*!@param creator the string to use for the creator code
00335    * @param f the file to save the code into
00336    * @return the number of bytes consumed */
00337   virtual unsigned int saveCreator(const char* creator, FILE* f) const throw();
00338   //@}
00339 
00340   /* //if you want to have a default behavior template like this (look up template specialization) (i thought i needed this, nevermind)
00341     template<class T> inline static unsigned int encode(const T x, char buf[], unsigned int cap) { cout << "*** WARNING attempted to encode non-primitive and non-LoadSave" << endl; return 0; }
00342     template<class T> inline static unsigned int decode(T& x, const char buf[], unsigned int cap) { cout << "*** WARNING attempted to decode non-primitive and non-LoadSave" << endl; return 0; }
00343     template<class T> inline static unsigned int encode(const T x, FILE* f) { cout << "*** WARNING attempted to encode non-primitive and non-LoadSave" << endl; return 0; }
00344     template<class T> inline static unsigned int decode(T& x, FILE* f) { cout << "*** WARNING attempted to decode non-primitive and non-LoadSave" << endl; return 0; }
00345   */
00346 
00347   //!encode/decode cross-platform compatable (byte order consistancy)
00348   //!@name Encode/Decode Utils
00349   /*!@brief encode or decode with byte order consistancy*/
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   /* These next two functions will allow you to serialize pointer values, but they are left out for safety -- if you're
00454    * serializing a pointer, you probably meant to serialize the _data at the pointer_ not the pointer itself!
00455    * If you really want to serialize the address in memory (say as an object ID of some sort), it is recommended
00456    * to cast the pointer to unsigned long long (for 64 bit compatability) in your own code, and still not use these. */
00457   
00458   //inline static unsigned int encode(const void* x, char buf[], unsigned int cap) throw() { return encode(static_cast<unsigned long long>(x),buf,cap); }
00459   //inline static unsigned int decode(void*& x, const char buf[], unsigned int cap) throw() { unsigned long long tmp; unsigned int used=decode(tmp,buf,cap); if(used==0) return 0; x=reinterpret_cast<void*>(tmp); return used; }
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   //!templated function to swap byte ordering, should allow compiler to unroll the loop; warning don't use this if src==dst!!!
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 // It appears that aperios does have vasprintf, it's just not exposed in the header files.
00494 // Thus, for Aperios, we provide a prototype above instead of this implementation, but it's here if needed on another platform.
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 //hide from doxygen
00515 #ifndef __DOXYGEN__
00516 //! template specialization to return serialized size of the specified type
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 // this macro check is just to balance the {}'s for less-than-genius editors
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 // this macro check is just to balance the {}'s for less-than-genius editors
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 // this macro check is just to balance the {}'s for less-than-genius editors
00782 #ifdef LOADSAVE_DEBUG
00783   }
00784 #else
00785   }
00786 #endif
00787   buf+=res;
00788   cap-=res;
00789 }
00790 
00791 /*! @file
00792  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00793  * @author ejt (Creator)
00794  * @author Daniel Höh (Revisor)
00795  *
00796  * $Author: ejt $
00797  * $Name: tekkotsu-3_0 $
00798  * $Revision: 1.21 $
00799  * $State: Exp $
00800  * $Date: 2006/10/03 21:11:51 $
00801  */
00802 
00803 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:44 2006 by Doxygen 1.4.7