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 "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 /*! @def LOADSAVE_SWAPBYTES
00017  *  @brief Set to 0 on platforms which don't actually need to swap bytes, 1 otherwise.  If not set externally, will attempt to auto-detect.
00018  *  Swapping is performed to standardize on little-endian byte order.  Mainly because this is what we used on the Aibo, which
00019  *  was the most processor-starved platform.  If running embedded on other platforms, you may want to reverse the logic
00020  *  for determining whether byte swapping will be performed! */
00021 #ifndef LOADSAVE_SWAPBYTES
00022 
00023 #ifdef BYTE_ORDER
00024 #  if BYTE_ORDER == BIG_ENDIAN
00025 #    define LOADSAVE_SWAPBYTES 1
00026 #  elif BYTE_ORDER == LITTLE_ENDIAN
00027 #    define LOADSAVE_SWAPBYTES 0
00028 #  else
00029 #    warning unknown byte ordering for current platform, assuming no swap
00030 #    define LOADSAVE_SWAPBYTES 0
00031 #  endif
00032 #else
00033 //aperios distribution doesn't actually define BYTE_ORDER :(
00034 //just as well, since we're using that byte order anyway
00035 #  ifdef PLATFORM_APERIOS
00036 //!On PLATFORM_APERIOS, we avoid swapping bytes, since it's likely to be the most CPU constrained platform
00037 #    define LOADSAVE_SWAPBYTES 0
00038 #  else
00039 #    warning unknown byte ordering for current platform, assuming no swap
00040 #    define LOADSAVE_SWAPBYTES 0
00041 #  endif
00042 #endif
00043 
00044 #endif
00045 
00046 //! Intended as an interface to allow easy and portable serialization operations
00047 /*! Generally, for triggering serialization of a LoadSave subclass, all you need to know is to call saveFile() /
00048     saveBuffer() in order to have the class serialize itself, and loadFile() /
00049     loadBuffer() in order to reload the data.
00050     
00051     When saveFile() is called, it checks that it can open the specified file, and then calls
00052     saveFileStream() with the open file.  This will then check getBinSize(), create a buffer of that
00053     size, and call saveBuffer() to do the actual work of serialization into that buffer.  If
00054     saveBuffer is successful, saveFileStream() copies the buffer out to the file, and then finally,
00055     saveFile() will close the file.
00056     
00057     This means when writing a class which requires serialization, you need only define 3 functions:
00058     loadBuffer(), saveBuffer(), and getBinSize().  If you are saving directly into a file and need
00059     the highest possible performance, overriding loadFileStream and saveFileStream and
00060     reimplementing the serialization operations into the file stream can save a buffer copy.
00061     Usually this is not a performance issue, but the interface is there if you need it.
00062     
00063     The recommended style for using LoadSave in classes with multiple levels of inheritance is to
00064     have each subclass first call the superclass's implementation (e.g. of loadBuffer/saveBuffer),
00065     and then save their own data afterward.  This compartmentalizes the data access and makes it
00066     easy to maintain - the code that serializes is right in with the code that defines the
00067     structure.  If you change one, it's easy to see where to change the other.  And protection
00068     between levels of inheritance is retained.  (This is why I say it's highly
00069     flexible/maintainable, but poor readability since the serialization is all broken up.)
00070     
00071     I also recommend putting a little string header at the beginning of each class's info via saveCreator() and checkCreator().  This
00072     will allow polymorphism when loading files (you can look at the string and create the
00073     appropriate type) but also is handy for checking field alignment... it's a lot easier to tell
00074     how much you're offset within a string than to do the same with a stream of binary values.
00075     Further, you can use the string as version information if you want to be backward compatible in
00076     future versions of your code.
00077   
00078     LoadSave provides a series of encode() and decode() functions for all the primitive types.  This
00079     will handle copying the value into the buffer or file, and can provide platform independence
00080     through byte swapping if needed (there's a compiler flag you can set for platforms that have the
00081     opposite byte order, although this should be autodetected from the system headers).
00082     Most of these are pretty straightfoward - an int is just 4 bytes and so on.
00083   
00084     However, there's one caveat that I want to make sure to point out if you have to write parsing
00085     code in say, Java.  Strings are encoded by first storing an int to hold the string's length,
00086     then the string itself, and then a null character.  This adds 5 bytes to the length of any
00087     string, but makes loading the files much easier/faster - you can call string library functions
00088     directly on the buffer if it's already in memory since the string is null terminated, or can
00089     allocate memory to hold the string with one pass from a file because you'll know the
00090     size of the string before you get to it.
00091   
00092     Of course, the string serialization format is transparent if you just stick to using LoadSave's
00093     encode/decode functions to parse it.
00094 */
00095 class LoadSave {
00096  public:
00097   //! This is the amount of extra space needed to store a string (int for len of string plus 1 for @code '\0' @endcode termination)
00098   static const unsigned int stringpad=sizeof(unsigned int)+1;
00099 
00100   //!@name Constructors/Destructors
00101   /*! @brief constructor */
00102   LoadSave() {}
00103   virtual ~LoadSave(); //!< destructor
00104   //@}
00105 
00106   /*! @brief These are useful for sending the data across a network as well as to a file.\n
00107    *  These three functions (getBinSize(), loadBuffer(), saveBuffer() ) are the only ones that MUST be
00108    *  overridden, as the file stream versions can be based on calling these.  However, you can override
00109    *  the file stream versions as well if speed or temp. memory is tight. */
00110   //!@name Buffer Operations
00111   
00112   //! Calculates space needed to save - if you can't precisely add up the size, just make sure to overestimate and things will still work.
00113   /*! getBinSize is used for reserving buffers during serialization, but does not necessarily determine
00114    *  the actual size of what is written -- the return value of saveBuffer() specifies that after the data
00115    *  actually has been written.  If getBinSize overestimates, the extra memory allocation is only
00116    *  temporary, no extra filler bytes are actually stored.
00117    *  @return number of bytes read/written, 0 if error (or empty) */
00118   virtual unsigned int getBinSize() const =0;
00119   //! Load from a saved buffer in memory
00120   /*! @param buf pointer to the memory where you should begin loading
00121    *  @param len length of @a buf available (this isn't necessarily all yours, there might be other things following your data)
00122    *  @return the number of bytes actually used */
00123   virtual unsigned int loadBuffer(const char buf[], unsigned int len)=0;
00124   //! Save to a given buffer in memory
00125   /*! @param buf pointer to the memory where you should begin writing
00126    *  @param len length of @a buf available.  (this isn't necessarily all yours, constrain yourself to what you returned in getBinSize() )
00127    *  @return the number of bytes actually used */
00128   virtual unsigned int saveBuffer(char buf[], unsigned int len) const =0;
00129   //@}
00130 
00131   //!These are called to load and save to files
00132   //!@name File Operations
00133   /*!@brief initiate opening of the specified file and loading/saving of all appropriate information.
00134    * @param filename the file to load/save @return number of bytes read/written, 0 if error (or empty)*/
00135   virtual unsigned int loadFile(const char* filename);
00136   virtual unsigned int saveFile(const char* filename) const;
00137   
00138   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00139   /*! @param f a pointer to the file to load
00140    *  @return number of bytes read, 0 if error (or empty) */
00141   virtual unsigned int loadFileStream(FILE* f);
00142   //!Used recursively on member objects once a file is already open - DON'T CLOSE the file in your overridden functions
00143   /*! @param f a pointer to the file to save
00144    *  @return number of bytes written, 0 if error (or empty) */
00145   virtual unsigned int saveFileStream(FILE* f) const;
00146 
00147   //! deprecated, use loadFile() instead (refactored to standardize capitalization style)
00148   virtual unsigned int LoadFile(const char* filename) ATTR_deprecated;
00149   //! deprecated, use saveFile() instead (refactored to standardize capitalization style)
00150   virtual unsigned int SaveFile(const char* filename) const ATTR_deprecated;
00151   //@}
00152 
00153   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() )  If res is 0, returns false
00154   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00155    *  @param res number of bytes used, or 0 if error
00156    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00157    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00158    *  @return true if everything worked, false otherwise */
00159   static inline bool checkInc(int res, const char*& buf, unsigned int& len) throw();
00160   
00161   //! 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.
00162   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00163    *  @param res number of bytes used, or 0 if error
00164    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00165    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00166    *  @param msg Error to display if res is less than or equal to zero
00167    *  @return true if everything worked, false otherwise */
00168   static inline bool checkInc(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00169   
00170   //! Handy for checking results from functions which manipulate a buffer (see also encodeInc()/decodeInc() ).  If res is 0, returns false
00171   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00172    *  @param res number of bytes used, or 0 if error
00173    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00174    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00175    *  @return true if everything worked, false otherwise */
00176   static inline bool checkInc(int res, char*& buf, unsigned int& len) throw();
00177   
00178   //! 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.
00179   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00180    *  @param res number of bytes used, or 0 if error
00181    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00182    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00183    *  @param msg Error to display if res is less than or equal to zero
00184    *  @return true if everything worked, false otherwise */
00185   static inline bool checkInc(int res, char*& buf, unsigned int& len, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00186   
00187   //! 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.
00188   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00189    *  @param res number of bytes used, or 0 if error
00190    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00191    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00192    *  @param msg Error message to throw in the std::length_error if res is less than or equal to zero */
00193   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)));
00194   
00195   //! 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.
00196   /*! Doesn't have to be used with encode/decode, also handy with snprintf, sscanf type operations using %n
00197    *  @param res number of bytes used, or 0 if error
00198    *  @param buf pointer to current position in buffer, will be incremented by @a res bytes
00199    *  @param len number of bytes remain between current place and end of buffer, will be decremented by @a res bytes
00200    *  @param msg Error message to throw in the std::length_error if res is less than or equal to zero */
00201   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)));
00202   
00203   //! Encodes @a value into the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false
00204   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00205    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00206    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00207    *  @return true if everything worked, false otherwise */
00208   template <class T> static inline bool encodeInc(const T& value, char*& buf, unsigned int& cap) throw();
00209 
00210   //! 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.
00211   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00212    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00213    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00214    *  @param msg Error to display if @a buf did not have enough capacity
00215    *  @return true if everything worked, false otherwise */
00216   template <class T> static inline bool encodeInc(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00217 
00218   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false
00219   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00220    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00221    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00222    *  @return true if everything worked, false otherwise */
00223   template <class T> static inline bool decodeInc(T& value, const char*& buf, unsigned int& cap) throw();
00224   
00225   //! 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.
00226   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00227    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00228    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00229    *  @param msg Error to display if @a buf did not have enough capacity
00230    *  @return true if everything worked, false otherwise */
00231   template <class T> static inline bool decodeInc(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00232   
00233   //! Decodes @a value from the buffer and if successful, increments the the buffer position and decrements the capacity.  If unsuccessful, returns false.
00234   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00235    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00236    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00237    *  @return true if everything worked, false otherwise */
00238   template <class T> static inline bool decodeInc(T& value, char*& buf, unsigned int& cap) throw();
00239   
00240   //! 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.
00241   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00242    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00243    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00244    *  @param msg Error to display if @a buf did not have enough capacity
00245    *  @return true if everything worked, false otherwise */
00246   template <class T> static inline bool decodeInc(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() __attribute__((format(printf,4,5)));
00247   
00248   //! 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.
00249   /*! @param value the value to encode, must be a primitive or a LoadSave subclass (i.e. a value for which encode() is defined)
00250    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00251    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00252    *  @param msg Error to display if @a buf did not have enough capacity */
00253   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)));
00254 
00255   //! 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.
00256   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00257    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00258    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00259    *  @param msg Error to display if @a buf did not have enough capacity */
00260   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)));
00261   
00262   //! 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.
00263   /*! @param value the value to decode into, must be a primitive or a LoadSave subclass (i.e. a value for which decode() is defined)
00264    *  @param buf pointer to current position in buffer, will be incremented by the serialized size of @a value
00265    *  @param cap number of bytes remain between current place and end of buffer, will be decremented by the serialized size of @a value
00266    *  @param msg Error to display if @a buf did not have enough capacity */
00267   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)));
00268   
00269   //! deprecated, use checkInc() instead (provides less error-prone interface (NULL not allowed), mixes better with other new *Inc varients)
00270   static bool chkAdvance(int res, const char** buf, unsigned int* len, const char* msg, ...) ATTR_deprecated __attribute__((format(printf,4,5)));
00271 
00272   /*! @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.
00273    *  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.) */
00274   //! @name Methods to detect the size member fields
00275   /*! @brief returns the serialized size of the argument */
00276   inline static unsigned int getSerializedSize(const LoadSave& x) throw() { return x.getBinSize(); }
00277   inline static unsigned int getSerializedSize(const std::string& x) throw() { return x.size()+stringpad; }
00278   inline static unsigned int getSerializedSize(const char* x) throw() { unsigned int sz=strlen(x); return sz+stringpad; }
00279   inline static unsigned int getSerializedSize(const void*) throw() { return sizeof(unsigned long long); }
00280   inline static unsigned int getSerializedSize(const bool&) throw() { return sizeof(char); }
00281   template <class T> inline static unsigned int getSerializedSize(const T& x) throw() { return sizeof(x); }
00282   //! 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...)
00283   template <class T> inline static unsigned int getSerializedSize() throw() { throw std::invalid_argument("The template argument passed to getSerializedSize() is not supported by LoadSave"); }
00284   //@}
00285   
00286   
00287   /*! @brief These are for putting creator codes (a uniquely identifying string, e.g. the name of the class) at the beginning of your data -- 
00288    *  doing so is a good idea to allow polymorphism, version detection (backward compatability), or just a sanity check */
00289   //!@name Creator Utilities
00290 
00291   /*!@brief Returns size of the creator code
00292    * @param creator a string to use for the creator
00293    * @return the size to leave for the creator code */
00294   virtual unsigned int creatorSize(const char creator[]) const { return strlen(creator)+stringpad; }
00295   //! Compares the creator code in the buffer to the one given
00296   /*!@param creator what the creator should be
00297    * @param buf the buffer to check
00298    * @param len the size remaining in the buffer
00299    * @param isLoading set this to true if you want to output a warning if it doesn't match
00300    * @return the number of bytes used by the creator, or 0 if it didn't match */
00301   virtual unsigned int checkCreator(const char* creator, const char buf[], unsigned int len, bool isLoading=true) const throw();
00302   //! Compares the creator code in the buffer to the one given, increments buf and decrements len if it matches
00303   /*!@param creator what the creator should be
00304    * @param buf the buffer to check
00305    * @param len the size remaining in the buffer
00306    * @param isLoading set this to true if you want to output a warning if it doesn't match
00307    * @return true if it matched, false otherwise */
00308   virtual bool checkCreatorInc(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw();
00309   //! 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
00310   /*!@param creator what the creator should be
00311    * @param buf the buffer to check
00312    * @param len the size remaining in the buffer
00313    * @param isLoading set this to true if you want to output a warning if it doesn't match */
00314   virtual void checkCreatorIncT(const char* creator, const char*& buf, unsigned int& len, bool isLoading=true) const throw(std::runtime_error);
00315   //! 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)
00316   /*!@param creator what the creator should be
00317    * @param f the file pointer to check
00318    * @param isLoading set this to true if you want to output a warning if it doesn't match
00319    * @return the number of bytes consumed by the creator code, or 0 if it didn't match */
00320   virtual unsigned int checkCreator(const char* creator, FILE* f, bool isLoading=true) const throw();
00321   //! Saves a creator code to a buffer
00322   /*!@param creator the string to use for the creator code
00323    * @param buf the buffer to save the code into
00324    * @param len the space available in the buffer
00325    * @return the number of bytes consumed */
00326   virtual unsigned int saveCreator(const char* creator, char buf[], unsigned int len) const throw();
00327   //! Saves a creator code to a buffer, increments buf and decrements len by the amount used
00328   /*!@param creator the string to use for the creator code
00329    * @param buf the buffer to save the code into
00330    * @param len the space available in the buffer
00331    * @return true if successful, false otherwise */
00332   virtual bool saveCreatorInc(const char* creator, char*& buf, unsigned int& len) const throw();
00333   //! Saves a creator code to a buffer, increments buf and decrements len by the amount used
00334   /*!@param creator the string to use for the creator code
00335    * @param buf the buffer to save the code into
00336    * @param len the space available in the buffer */
00337   virtual void saveCreatorIncT(const char* creator, char*& buf, unsigned int& len) const throw(std::runtime_error);
00338   //! Saves a creator code directly to a file
00339   /*!@param creator the string to use for the creator code
00340    * @param f the file to save the code into
00341    * @return the number of bytes consumed */
00342   virtual unsigned int saveCreator(const char* creator, FILE* f) const throw();
00343   //@}
00344 
00345   /* //if you want to have a default behavior template like this (look up template specialization) (i thought i needed this, nevermind)
00346     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; }
00347     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; }
00348     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; }
00349     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; }
00350   */
00351 
00352   //!encode/decode cross-platform compatable (byte order consistancy)
00353   //!@name Encode/Decode Utils
00354   /*!@brief encode or decode with byte order consistancy*/
00355   inline static unsigned int encode(const LoadSave& x, char buf[], unsigned int cap) { return x.saveBuffer(buf,cap); }
00356   inline static unsigned int decode(LoadSave& x, const char buf[], unsigned int cap) { return x.loadBuffer(buf,cap); }
00357   inline static unsigned int encode(const LoadSave& x, FILE* f)                 { return x.saveFileStream(f); }
00358   inline static unsigned int decode(LoadSave& x, FILE* f)                       { return x.loadFileStream(f); }
00359   
00360 #if LOADSAVE_SWAPBYTES
00361   
00362   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); }
00363   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);}
00364   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); }
00365   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);}
00366   
00367   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); }
00368   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);}
00369   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); }
00370   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);}
00371   
00372   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); }
00373   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);}
00374   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); }
00375   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);}
00376   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); }
00377   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);}
00378   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); }
00379   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);}
00380   
00381   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); }
00382   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);}
00383   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); }
00384   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);}
00385   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); }
00386   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);}
00387   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); }
00388   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);}
00389   
00390   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); }
00391   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);}
00392   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); }
00393   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);}
00394   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); }
00395   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);}
00396   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); }
00397   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);}
00398   
00399   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); }
00400   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);}
00401   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); }
00402   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);}
00403   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); }
00404   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);}
00405   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); }
00406   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);}
00407 
00408 #else
00409   
00410   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); }
00411   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); }
00412   inline static unsigned int encode(const double x, FILE* f) throw()                        { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00413   inline static unsigned int decode(double& x, FILE* f) throw()                             { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00414   
00415   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); }
00416   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); }
00417   inline static unsigned int encode(const float x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00418   inline static unsigned int decode(float& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00419 
00420   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); }
00421   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); }
00422   inline static unsigned int encode(const long long x, FILE* f) throw()                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00423   inline static unsigned int decode(long long& x, FILE* f) throw()                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00424   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); }
00425   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); }
00426   inline static unsigned int encode(const unsigned long long x, FILE* f) throw()                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00427   inline static unsigned int decode(unsigned long long& x, FILE* f) throw()                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00428   
00429   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); }
00430   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); }
00431   inline static unsigned int encode(const long x, FILE* f) throw()                          { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00432   inline static unsigned int decode(long& x, FILE* f) throw()                               { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00433   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); }
00434   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); }
00435   inline static unsigned int encode(const unsigned long x, FILE* f) throw()                 { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00436   inline static unsigned int decode(unsigned long& x, FILE* f) throw()                      { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00437   
00438   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); }
00439   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); }
00440   inline static unsigned int encode(const int x, FILE* f) throw()                           { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00441   inline static unsigned int decode(int& x, FILE* f) throw()                                { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00442   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); }
00443   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); }
00444   inline static unsigned int encode(const unsigned int x, FILE* f) throw()                  { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00445   inline static unsigned int decode(unsigned int& x, FILE* f) throw()                       { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00446   
00447   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); }
00448   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); }
00449   inline static unsigned int encode(const short x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00450   inline static unsigned int decode(short& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00451   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); }
00452   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); }
00453   inline static unsigned int encode(const unsigned short x, FILE* f) throw()                { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00454   inline static unsigned int decode(unsigned short& x, FILE* f) throw()                     { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00455 
00456 #endif //end of big/little endian differences
00457   
00458   /* These next two functions will allow you to serialize pointer values, but they are left out for safety -- if you're
00459    * serializing a pointer, you probably meant to serialize the _data at the pointer_ not the pointer itself!
00460    * If you really want to serialize the address in memory (say as an object ID of some sort), it is recommended
00461    * to cast the pointer to unsigned long long (for 64 bit compatability) in your own code, and still not use these. */
00462   
00463   //inline static unsigned int encode(const void* x, char buf[], unsigned int cap) throw() { return encode(static_cast<unsigned long long>(x),buf,cap); }
00464   //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; }
00465   
00466   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; }
00467   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; }
00468   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); }
00469   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; }
00470   
00471   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; }
00472   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; }
00473   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); }
00474   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; }
00475   
00476   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); }
00477   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);}
00478   inline static unsigned int encode(const char x, FILE* f) throw()                         { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00479   inline static unsigned int decode(char& x, FILE* f) throw()                              { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00480   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); }
00481   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);}
00482   inline static unsigned int encode(const unsigned char x, FILE* f) throw()                { return sizeof(x)*fwrite(&x,sizeof(x),1,f); }
00483   inline static unsigned int decode(unsigned char& x, FILE* f) throw()                     { return sizeof(x)*fread(&x,sizeof(x),1,f); }
00484   
00485   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); }
00486   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);}
00487   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); }
00488   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); }
00489   //@}  
00490 protected:
00491   //!templated function to swap byte ordering, should allow compiler to unroll the loop; warning don't use this if src==dst!!!
00492   template<class T> inline static void byteswap(T& dstc, const T& srcc) throw() {
00493     char* dst=(char*)&dstc;
00494     const char* src=(const char*)&srcc;
00495     for(unsigned int i=0; i<sizeof(T); i++)
00496       dst[sizeof(T)-1-i]=src[i];
00497   }
00498 // It appears that aperios does have vasprintf, it's just not exposed in the header files.
00499 // Thus, for Aperios, we provide a prototype above instead of this implementation, but it's here if needed on another platform.
00500 #if defined(NEED_ASPRINTF)
00501   int vasprintf(char** ret, const char* format, va_list al) {
00502     va_list tmpal;
00503     va_copy(tmpal,al);
00504     int nc=vsnprintf(NULL,0,format,tmpal);
00505     *ret = (char*)malloc(nc+1);
00506     if(*ret==NULL) return -1;
00507     return vsnprintf(*ret,nc+1,format,al);
00508   }
00509   int asprintf(char **ret, const char *format, ...) {
00510     va_list ap;
00511     va_start (ap, format);
00512     int nc= vasprintf(ret, format, ap);
00513     va_end(ap);
00514     return nc;
00515   }
00516 #endif
00517 };
00518 
00519 //hide from doxygen
00520 #ifndef __DOXYGEN__
00521 //! template specialization to return serialized size of the specified type
00522 template <> inline unsigned int LoadSave::getSerializedSize<void*>() throw() { return sizeof(unsigned long long); }
00523 template <> inline unsigned int LoadSave::getSerializedSize<bool>() throw() { return sizeof(char); }
00524 template <> inline unsigned int LoadSave::getSerializedSize<char>() throw() { return sizeof(char); }
00525 template <> inline unsigned int LoadSave::getSerializedSize<unsigned char>() throw() { return sizeof(unsigned char); }
00526 template <> inline unsigned int LoadSave::getSerializedSize<short>() throw() { return sizeof(short); }
00527 template <> inline unsigned int LoadSave::getSerializedSize<unsigned short>() throw() { return sizeof(unsigned short); }
00528 template <> inline unsigned int LoadSave::getSerializedSize<int>() throw() { return sizeof(int); }
00529 template <> inline unsigned int LoadSave::getSerializedSize<unsigned int>() throw() { return sizeof(unsigned int); }
00530 template <> inline unsigned int LoadSave::getSerializedSize<long>() throw() { return sizeof(long); }
00531 template <> inline unsigned int LoadSave::getSerializedSize<unsigned long>() throw() { return sizeof(unsigned long); }
00532 template <> inline unsigned int LoadSave::getSerializedSize<long long>() throw() { return sizeof(long long); }
00533 template <> inline unsigned int LoadSave::getSerializedSize<unsigned long long>() throw() { return sizeof(unsigned long long); }
00534 template <> inline unsigned int LoadSave::getSerializedSize<float>() throw() { return sizeof(float); }
00535 template <> inline unsigned int LoadSave::getSerializedSize<double>() throw() { return sizeof(double); }
00536 
00537 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!"); }
00538 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!"); }
00539 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)."); }
00540 #endif
00541 
00542 bool LoadSave::checkInc(int res, const char*& buf, unsigned int& len) throw() {
00543   if(res<0 || (unsigned int)res>len)
00544     return false;
00545   buf+=res;
00546   len-=res;
00547   return true;
00548 }
00549 
00550 bool LoadSave::checkInc(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw() {
00551   if(checkInc(res,buf,len))
00552     return true;
00553   if(msg[0]!='\0') {
00554     if((unsigned int)res>len)
00555       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00556     va_list al;
00557     va_start(al,msg);
00558     vfprintf(stderr,msg,al);
00559     va_end(al);
00560   }
00561   return false;
00562 }
00563 
00564 bool LoadSave::checkInc(int res, char*& buf, unsigned int& len) throw() {
00565   if(res<0 || (unsigned int)res>len)
00566     return false;
00567   buf+=res;
00568   len-=res;
00569   return true;
00570 }
00571 
00572 bool LoadSave::checkInc(int res, char*& buf, unsigned int& len, const char* msg, ...) throw() {
00573   if(checkInc(res,buf,len))
00574     return true;
00575   if(msg[0]!='\0') {
00576     if((unsigned int)res>len)
00577       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00578     va_list al;
00579     va_start(al,msg);
00580     vfprintf(stderr,msg,al);
00581     va_end(al);
00582   }
00583   return false;
00584 }
00585 
00586 void LoadSave::checkIncT(int res, const char*& buf, unsigned int& len, const char* msg, ...) throw(std::length_error) {
00587   if(res>0 && (unsigned int)res<=len) {
00588     buf+=res;
00589     len-=res;
00590   } else {
00591     if((unsigned int)res>len && msg[0]!='\0')
00592       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00593     va_list al;
00594     va_start(al,msg);
00595     char * errmsg;
00596     vasprintf(&errmsg,msg,al);
00597     va_end(al);
00598     if(errmsg==NULL)
00599       throw std::length_error("unspecified");
00600     std::string serrmsg=errmsg;
00601     free(errmsg);
00602     throw std::length_error(serrmsg);
00603   }
00604 }
00605 
00606 void LoadSave::checkIncT(int res, char*& buf, unsigned int& len, const char* msg, ...) throw(std::length_error) {
00607   if(res>0 && (unsigned int)res<=len) {
00608     buf+=res;
00609     len-=res;
00610   } else {
00611     if((unsigned int)res>len && msg[0]!='\0')
00612       fprintf(stderr,"*** WARNING: reported check result length exceeded remaining buffer size; %u (signed %d) vs %u\n",(unsigned int)res,res,len);
00613     va_list al;
00614     va_start(al,msg);
00615     char * errmsg;
00616     vasprintf(&errmsg,msg,al);
00617     va_end(al);
00618     if(errmsg==NULL)
00619       throw std::length_error("unspecified");
00620     std::string serrmsg=errmsg;
00621     free(errmsg);
00622     throw std::length_error(serrmsg);
00623   }
00624 }
00625 
00626 template <class T>
00627 bool LoadSave::encodeInc(const T& value, char*& buf, unsigned int& cap) throw() {
00628   unsigned int res=encode(value,buf,cap);
00629   if(res==0)
00630     return false;
00631 #ifdef LOADSAVE_DEBUG
00632   if(res>cap) {
00633     fprintf(stderr,"*** WARNING: reported encode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00634     return false;
00635   }
00636 #endif
00637   buf+=res;
00638   cap-=res;
00639   return true;
00640 }
00641 template <class T>
00642 bool LoadSave::encodeInc(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00643   if(encodeInc(value,buf,cap))
00644     return true;
00645   if(msg[0]!='\0') {
00646     va_list al;
00647     va_start(al,msg);
00648     vfprintf(stderr,msg,al);
00649     va_end(al);
00650   }
00651   return false;
00652 }
00653 template <class T>
00654 bool LoadSave::decodeInc(T& value, const char*& buf, unsigned int& cap) throw() {
00655   unsigned int res=decode(value,buf,cap);
00656   if(res==0)
00657     return false;
00658 #ifdef LOADSAVE_DEBUG
00659   if(res>cap) {
00660     fprintf(stderr,"*** WARNING: reported decode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00661     return false;
00662   }
00663 #endif
00664   buf+=res;
00665   cap-=res;
00666   return true;
00667 }
00668 template <class T>
00669 bool LoadSave::decodeInc(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00670   if(decodeInc(value,buf,cap))
00671     return true;
00672   if(msg[0]!='\0') {
00673     va_list al;
00674     va_start(al,msg);
00675     vfprintf(stderr,msg,al);
00676     va_end(al);
00677   }
00678   return false;
00679 }
00680 template <class T>
00681 bool LoadSave::decodeInc(T& value, char*& buf, unsigned int& cap) throw() {
00682   unsigned int res=decode(value,buf,cap);
00683   if(res==0)
00684     return false;
00685 #ifdef LOADSAVE_DEBUG
00686   if(res>cap) {
00687     fprintf(stderr,"*** WARNING: reported decode result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00688     return false;
00689   }
00690 #endif
00691   buf+=res;
00692   cap-=res;
00693   return true;
00694 }
00695 template <class T>
00696 bool LoadSave::decodeInc(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw() {
00697   if(decodeInc(value,buf,cap))
00698     return true;
00699   if(msg[0]!='\0') {
00700     va_list al;
00701     va_start(al,msg);
00702     vfprintf(stderr,msg,al);
00703     va_end(al);
00704   }
00705   return false;
00706 }
00707 
00708 template <class T>
00709 void LoadSave::encodeIncT(const T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00710   unsigned int res=encode(value,buf,cap);
00711 #ifdef LOADSAVE_DEBUG
00712   if(res==0 || res>cap) {
00713     if(res>cap)
00714       fprintf(stderr,"*** WARNING: encode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00715 #else
00716   if(res==0) {
00717 #endif
00718     va_list al;
00719     va_start(al,msg);
00720     char * errmsg;
00721     vasprintf(&errmsg,msg,al);
00722     va_end(al);
00723     if(errmsg==NULL)
00724       throw std::length_error("unspecified");
00725     std::string serrmsg=errmsg;
00726     free(errmsg);
00727     throw std::length_error(serrmsg);
00728 // this macro check is just to balance the {}'s for less-than-genius editors
00729 #ifdef LOADSAVE_DEBUG
00730   }
00731 #else
00732   }
00733 #endif
00734   buf+=res;
00735   cap-=res;
00736 }
00737 template <class T>
00738 void LoadSave::decodeIncT(T& value, const char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00739   unsigned int res=decode(value,buf,cap);
00740 #ifdef LOADSAVE_DEBUG
00741   if(res==0 || res>cap) {
00742     if(res>cap)
00743       fprintf(stderr,"*** WARNING: decode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00744 #else
00745   if(res==0) {
00746 #endif
00747     va_list al;
00748     va_start(al,msg);
00749     char * errmsg;
00750     vasprintf(&errmsg,msg,al);
00751     va_end(al);
00752     if(errmsg==NULL)
00753       throw std::length_error("unspecified");
00754     std::string serrmsg=errmsg;
00755     free(errmsg);
00756     throw std::length_error(serrmsg);
00757 // this macro check is just to balance the {}'s for less-than-genius editors
00758 #ifdef LOADSAVE_DEBUG
00759   }
00760 #else
00761   }
00762 #endif
00763   buf+=res;
00764   cap-=res;
00765 }
00766 template <class T>
00767 void LoadSave::decodeIncT(T& value, char*& buf, unsigned int& cap, const char* msg, ...) throw(std::length_error) {
00768   unsigned int res=decode(value,buf,cap);
00769 #ifdef LOADSAVE_DEBUG
00770   if(res==0 || res>cap) {
00771     if(res>cap)
00772       fprintf(stderr,"*** WARNING: decode reported result length exceeded remaining buffer size; %u (signed %d) vs %u\n",res,(int)res,cap);
00773 #else
00774   if(res==0) {
00775 #endif
00776     va_list al;
00777     va_start(al,msg);
00778     char * errmsg;
00779     vasprintf(&errmsg,msg,al);
00780     va_end(al);
00781     if(errmsg==NULL)
00782       throw std::length_error("unspecified");
00783     std::string serrmsg=errmsg;
00784     free(errmsg);
00785     throw std::length_error(serrmsg);
00786 // this macro check is just to balance the {}'s for less-than-genius editors
00787 #ifdef LOADSAVE_DEBUG
00788   }
00789 #else
00790   }
00791 #endif
00792   buf+=res;
00793   cap-=res;
00794 }
00795 
00796 /*! @file
00797  * @brief Describes LoadSave, inherit from this to use a standard interface for loading and saving
00798  * @author ejt (Creator)
00799  * @author Daniel Höh (Revisor)
00800  *
00801  * $Author: ejt $
00802  * $Name: tekkotsu-4_0 $
00803  * $Revision: 1.24 $
00804  * $State: Exp $
00805  * $Date: 2007/11/13 04:16:03 $
00806  */
00807 
00808 #endif

Tekkotsu v4.0
Generated Thu Nov 22 00:54:53 2007 by Doxygen 1.5.4