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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:44 2016 by Doxygen 1.6.3