| Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
LoadSave.hGo 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); } |