/[svn]/libgig/trunk/src/Serialization.h
ViewVC logotype

Diff of /libgig/trunk/src/Serialization.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3182 by schoenebeck, Sun May 14 20:40:02 2017 UTC revision 3183 by schoenebeck, Mon May 15 18:44:32 2017 UTC
# Line 118  namespace Serialization { Line 118  namespace Serialization {
118    
119      typedef std::string String;      typedef std::string String;
120    
121        /** @brief Raw data stream of serialized C++ objects.
122         *
123         * This data type is used for the data stream as a result of serializing
124         * your C++ objects with Archive::serialize(), and for native raw data
125         * representation of individual serialized C/C++ objects, members and variables.
126         *
127         * @see Archive::rawData(), Object::rawData()
128         */
129      typedef std::vector<uint8_t> RawData;      typedef std::vector<uint8_t> RawData;
130    
131        /** @brief Abstract identifier for serialized C++ objects.
132         *
133         * This data type is used for identifying serialized C++ objects and members
134         * of your C++ objects. It is important to know that such an ID might not
135         * necessarily be unique. For example the ID of one C++ object might often
136         * be identical to the ID of the first member of that particular C++ object.
137         * That's why there is additionally the concept of an UID in this framework.
138         *
139         * @see UID
140         */
141      typedef void* ID;      typedef void* ID;
142    
143        /** @brief Version number data type.
144         *
145         * This data type is used for maintaining version number information of
146         * your C++ class implementations.
147         *
148         * @see Archive::setVersion() and Archive::setMinVersion()
149         */
150      typedef uint32_t Version;      typedef uint32_t Version;
151    
152        /** @brief To which time zone a certain timing information relates to.
153         *
154         * The constants in this enum type are used to define to which precise time
155         * zone a time stamp relates to.
156         */
157      enum time_base_t {      enum time_base_t {
158          LOCAL_TIME,          LOCAL_TIME, ///< The time stamp relates to the machine's local time zone. Request a time stamp in local time if you want to present that time stamp to the end user.
159          UTC_TIME          UTC_TIME ///< The time stamp relates to "Greenwhich Mean Time" zone, also known as "Coordinated Universal Time". Request time stamp with UTC if you want to compare that time stamp with other time stamps.
160      };      };
161    
162        /** @brief Check whether data is a C/C++ @c enum type.
163         *
164         * Returns true if the supplied C++ variable or object is of a C/C++ @c enum
165         * type.
166         *
167         * @param data - the variable or object whose data type shall be checked
168         */
169      template<typename T>      template<typename T>
170      bool IsEnum(const T& data) {      bool IsEnum(const T& data) {
171          #if !HAS_BUILTIN_TYPE_TRAITS          #if !HAS_BUILTIN_TYPE_TRAITS
# Line 138  namespace Serialization { Line 175  namespace Serialization {
175          #endif          #endif
176      }      }
177    
178        /** @brief Check whether data is a C++ @c union type.
179         *
180         * Returns true if the supplied C++ variable or object is of a C/C++ @c union
181         * type. Note that the result of this function is only reliable if the C++
182         * compiler you are using has support for built-in type traits. If your C++
183         * compiler does not have built-in type traits support, then this function
184         * will simply return @c false on all your calls.
185         *
186         * @param data - the variable or object whose data type shall be checked
187         */
188      template<typename T>      template<typename T>
189      bool IsUnion(const T& data) {      bool IsUnion(const T& data) {
190          #if !HAS_BUILTIN_TYPE_TRAITS          #if !HAS_BUILTIN_TYPE_TRAITS
# Line 147  namespace Serialization { Line 194  namespace Serialization {
194          #endif          #endif
195      }      }
196    
197        /** @brief Check whether data is a C/C++ @c struct or C++ @c class type.
198         *
199         * Returns true if the supplied C++ variable or object is of C/C++ @c struct
200         * or C++ @c class type. Note that if you are using a C++ compiler which
201         * does have built-in type traits support, then this function will also
202         * return @c true on C/C++ @c union types.
203         *
204         * @param data - the variable or object whose data type shall be checked
205         */
206      template<typename T>      template<typename T>
207      bool IsClass(const T& data) {      bool IsClass(const T& data) {
208          #if !HAS_BUILTIN_TYPE_TRAITS          #if !HAS_BUILTIN_TYPE_TRAITS
# Line 169  namespace Serialization { Line 225  namespace Serialization {
225      /** @brief Unique identifier for one specific C++ object, member or fundamental variable.      /** @brief Unique identifier for one specific C++ object, member or fundamental variable.
226       *       *
227       * Reflects a unique identifier for one specific serialized C++ class       * Reflects a unique identifier for one specific serialized C++ class
228       * instance, struct instance, member, primitive pointer, or fundamental       * instance, C/C++ struct instance, member, primitive pointer, or
229       * variables.       * fundamental variables.
230         *
231         * A unique identifier is composed of an id (an identifier which is not
232         * necessarily unique) and a size. Since the underlying ID is derived from
233         * the original C++ object's memory location, such an ID is not sufficient
234         * to distinguish a particular C++ object from the first member of that C++
235         * object, since both typically share the same memory address. So
236         * additionally the memory size of the respective object or member is
237         * bundled with UID objects to make them unique and distinguishable.
238       */       */
239      class UID {      class UID {
240      public:      public:
241          ID id;          ID id; ///< Abstract non-unique ID of the object or member in question.
242          size_t size;          size_t size; ///< Memory size of the object or member in question.
243    
244          bool isValid() const;          bool isValid() const;
245          operator bool() const { return isValid(); }          operator bool() const { return isValid(); } ///< Same as calling isValid().
246          //bool operator()() const { return isValid(); }          //bool operator()() const { return isValid(); }
247          bool operator==(const UID& other) const { return id == other.id && size == other.size; }          bool operator==(const UID& other) const { return id == other.id && size == other.size; }
248          bool operator!=(const UID& other) const { return id != other.id || size != other.size; }          bool operator!=(const UID& other) const { return id != other.id || size != other.size; }
249          bool operator<(const UID& other) const { return id < other.id || (id == other.id && size < other.size); }          bool operator<(const UID& other) const { return id < other.id || (id == other.id && size < other.size); }
250          bool operator>(const UID& other) const { return id > other.id || (id == other.id && size > other.size); }          bool operator>(const UID& other) const { return id > other.id || (id == other.id && size > other.size); }
251    
252            /** @brief Create an unique indentifier for a native C++ object/member/variable.
253             *
254             * Creates and returns an unique identifier for the passed native C++
255             * object, object member or variable. For the same C++ object/member/variable
256             * this function will always return the same UID. For all other ones,
257             * this function is guaranteed to return a different UID.
258             */
259          template<typename T>          template<typename T>
260          static UID from(const T& obj) {          static UID from(const T& obj) {
261              return Resolver<T>::resolve(obj);              return Resolver<T>::resolve(obj);
# Line 212  namespace Serialization { Line 283  namespace Serialization {
283    
284      /**      /**
285       * Reflects an invalid UID and behaves similar to NULL as invalid value for       * Reflects an invalid UID and behaves similar to NULL as invalid value for
286       * pointer types.       * pointer types. All UID objects are first initialized with this value,
287         * and it essentially an all zero object.
288       */       */
289      extern const UID NO_UID;      extern const UID NO_UID;
290    
291        /** @brief Chain of UIDs.
292         *
293         * This data type is used for native C++ pointers. The first member of the
294         * UID chain is the unique identifier of the C++ pointer itself, then the
295         * following UIDs are the respective objects or variables the pointer is
296         * pointing to. The size (the amount of elements) of the UIDChain depends
297         * solely on the degree of the pointer type. For example the following C/C++
298         * pointer:
299         * @code
300         * int* pNumber;
301         * @endcode
302         * is an integer pointer of first degree. Such a pointer would have a
303         * UIDChain with 2 members: the first element would be the UID of the
304         * pointer itself, the second element of the chain would be the integer data
305         * that pointer is pointing to. In the following example:
306         * @code
307         * bool*** pppSomeFlag;
308         * @endcode
309         * That boolean pointer would be of third degree, and thus its UIDChain
310         * would have a size of 4 (elements).
311         *
312         * Accordingly a non pointer type like:
313         * @code
314         * float f;
315         * @endcode
316         * would yield in a UIDChain of size 1.
317         *
318         * Since however this serialization framework currently only supports
319         * pointers of first degree yet, all UIDChains are currently either of
320         * size 1 or 2, which might change in future though.
321         */
322      typedef std::vector<UID> UIDChain;      typedef std::vector<UID> UIDChain;
323    
324      // prototyping of private internal friend functions      // prototyping of private internal friend functions
# Line 231  namespace Serialization { Line 334  namespace Serialization {
334    
335      /** @brief Abstract reflection of a native C++ data type.      /** @brief Abstract reflection of a native C++ data type.
336       *       *
337       * Provides detailed information about a C++ data type, whether it is a       * Provides detailed information about a serialized C++ data type, whether
338       * fundamental C/C++ data type (like int, float, char, etc.) or custom       * it is a fundamental C/C++ data type (like @c int, @c float, @c char,
339       * defined data type like a C++ class, struct, enum, as well as other       * etc.) or custom defined data types like a C++ @c class, C/C++ @c struct,
340       * features of the data type like its native memory size and more.       * @c enum, as well as other features of the respective data type like its
341         * native memory size and more.
342         *
343         * All informations provided by this class are retrieved from the
344         * respective individual C++ objects, their members and other data when
345         * they are serialized, and all those information are stored with the
346         * serialized archive and its resulting data stream. Due to the availability
347         * of these extensive data type information within serialized archives, this
348         * framework is capable to use them in order to adapt its deserialization
349         * process upon subsequent changes to your individual C++ classes.
350       */       */
351      class DataType {      class DataType {
352      public:      public:
353          DataType();          DataType();
354          size_t size() const { return m_size; }          size_t size() const { return m_size; } ///< Returns native memory size of the respective C++ object or variable.
355          bool isValid() const;          bool isValid() const;
356          bool isPointer() const;          bool isPointer() const;
357          bool isClass() const;          bool isClass() const;
# Line 249  namespace Serialization { Line 361  namespace Serialization {
361          bool isBool() const;          bool isBool() const;
362          bool isEnum() const;          bool isEnum() const;
363          bool isSigned() const;          bool isSigned() const;
364          operator bool() const { return isValid(); }          operator bool() const { return isValid(); } ///< Same as calling isValid().
365          //bool operator()() const { return isValid(); }          //bool operator()() const { return isValid(); }
366          bool operator==(const DataType& other) const;          bool operator==(const DataType& other) const;
367          bool operator!=(const DataType& other) const;          bool operator!=(const DataType& other) const;
368          bool operator<(const DataType& other) const;          bool operator<(const DataType& other) const;
369          bool operator>(const DataType& other) const;          bool operator>(const DataType& other) const;
370          String asLongDescr() const;          String asLongDescr() const;
371          String baseTypeName() const { return m_baseTypeName; }          String baseTypeName() const;
372          String customTypeName(bool demangle = false) const;          String customTypeName(bool demangle = false) const;
373    
374            /** @brief Construct a DataType object for the given native C++ data.
375             *
376             * Use this function to create corresponding DataType objects for
377             * native C/C++ objects, members and variables.
378             *
379             * @param data - native C/C++ object/member/variable a DataType object
380             *               shall be created for
381             * @returns corresponding DataType object for the supplied native C/C++
382             *          object/member/variable
383             */
384          template<typename T>          template<typename T>
385          static DataType dataTypeOf(const T& data) {          static DataType dataTypeOf(const T& data) {
386              return Resolver<T>::resolve(data);              return Resolver<T>::resolve(data);
# Line 341  namespace Serialization { Line 463  namespace Serialization {
463       * serialized C++ object, like its C++ data type, offset of this member       * serialized C++ object, like its C++ data type, offset of this member
464       * within its containing data structure/class, its C++ member variable name       * within its containing data structure/class, its C++ member variable name
465       * and more.       * and more.
466         *
467         * Consider you defined the following user defined C/C++ @c struct type in
468         * your application:
469         * @code
470         * struct Foo {
471         *     int  a;
472         *     bool b;
473         *     double someValue;
474         * };
475         * @endcode
476         * Then @c a, @c b and @c someValue are "members" of @c struct @c Foo for
477         * instance. So that @c struct would have 3 members in the latter example.
478         *
479         * @see Object::members()
480       */       */
481      class Member {      class Member {
482      public:      public:
483          Member();          Member();
484          UID uid() const { return m_uid; }          UID uid() const;
485          String name() const { return m_name; }          String name() const;
486          size_t offset() const { return m_offset; }          size_t offset() const;
487          const DataType& type() const { return m_type; }          const DataType& type() const;
488          bool isValid() const;          bool isValid() const;
489          operator bool() const { return isValid(); }          operator bool() const { return isValid(); } ///< Same as calling isValid().
490          //bool operator()() const { return isValid(); }          //bool operator()() const { return isValid(); }
491          bool operator==(const Member& other) const;          bool operator==(const Member& other) const;
492          bool operator!=(const Member& other) const;          bool operator!=(const Member& other) const;
# Line 374  namespace Serialization { Line 510  namespace Serialization {
510       *       *
511       * Provides detailed information about a specific serialized C++ object,       * Provides detailed information about a specific serialized C++ object,
512       * like its C++ member variables, its C++ class/struct name, its native       * like its C++ member variables, its C++ class/struct name, its native
513       * memory size and more.       * memory size and more. When your native C++ objects are serialized, all
514         * native data is translated reflected by such an Object reflection. So each
515         * instance of your serialized C++ class objects become available as an
516         * Object, but also each member variable of your C++ objects, and all other
517         * native C/C++ data. So essentially every native data is turned into its
518         * own Object and accessible by this API.
519         *
520         * Even though this framework allows you to adjust abstract Object instances
521         * to a certain extent, most of the methods of this Object class are
522         * read-only though and the actual modifyable methods are made available
523         * not as part of this Object class, but as part of the Archive class
524         * instead. This was designed like this for performance and safety reasons.
525         *
526         * @see Archive::setIntValue() as an example for modifying Object instances.
527       */       */
528      class Object {      class Object {
529      public:      public:
530          Object();          Object();
531          Object(UIDChain uidChain, DataType type);          Object(UIDChain uidChain, DataType type);
532    
533          UID uid(int index = 0) const {          UID uid(int index = 0) const;
534              return (index < m_uid.size()) ? m_uid[index] : NO_UID;          const UIDChain& uidChain() const;
535          }          const DataType& type() const;
536            const RawData& rawData() const;
537          const UIDChain& uidChain() const { return m_uid; }          Version version() const;
538          const DataType& type() const { return m_type; }          Version minVersion() const;
         const RawData& rawData() const { return m_data; }  
         Version version() const { return m_version; }  
         Version minVersion() const { return m_minVersion; }  
539          bool isVersionCompatibleTo(const Object& other) const;          bool isVersionCompatibleTo(const Object& other) const;
540          std::vector<Member>& members() { return m_members; }          std::vector<Member>& members();
541          const std::vector<Member>& members() const { return m_members; }          const std::vector<Member>& members() const;
542          Member memberNamed(String name) const;          Member memberNamed(String name) const;
543          Member memberByUID(const UID& uid) const;          Member memberByUID(const UID& uid) const;
544          std::vector<Member> membersOfType(const DataType& type) const;          std::vector<Member> membersOfType(const DataType& type) const;
545          int sequenceIndexOf(const Member& member) const;          int sequenceIndexOf(const Member& member) const;
546          bool isValid() const;          bool isValid() const;
547          operator bool() const { return isValid(); }          operator bool() const { return isValid(); } ///< Same as calling isValid().
548          //bool operator()() const { return isValid(); }          //bool operator()() const { return isValid(); }
549          bool operator==(const Object& other) const;          bool operator==(const Object& other) const;
550          bool operator!=(const Object& other) const;          bool operator!=(const Object& other) const;
# Line 553  namespace Serialization { Line 699  namespace Serialization {
699          Archive(const uint8_t* data, size_t size);          Archive(const uint8_t* data, size_t size);
700          virtual ~Archive();          virtual ~Archive();
701    
702            /** @brief Initiate serialization.
703             *
704             * Initiates serialization of all native C++ objects, which means
705             * capturing and storing the current data of all your C++ objects as
706             * content of this Archive.
707             *
708             * This framework has a concept of a "root" object which you must pass
709             * to this method. The root object is the starting point for
710             * serialization of your C++ objects. The framework will then
711             * recursively serialize all members of that C++ object an continue to
712             * serialize all other C++ objects that it might contain or point to.
713             *
714             * After this method returned, you might traverse all serialized objects
715             * by walking them starting from the rootObject(). You might then modify
716             * that abstract reflection of your C++ objects and finally you might
717             * call rawData() to get an encoded raw data stream which you might use
718             * for sending it "over wire" to somewhere where it is going to be
719             * deserialized later on.
720             *
721             * Note that whenever you call this method, the previous content of this
722             * Archive will first be cleared.
723             *
724             * @param obj - native C++ root object where serialization shall start
725             * @see Archive::operator<<()
726             */
727          template<typename T>          template<typename T>
728          void serialize(const T* obj) {          void serialize(const T* obj) {
729              m_operation = OPERATION_SERIALIZE;              m_operation = OPERATION_SERIALIZE;
# Line 564  namespace Serialization { Line 735  namespace Serialization {
735              m_operation = OPERATION_NONE;              m_operation = OPERATION_NONE;
736          }          }
737    
738            /** @brief Initiate deserialization.
739             *
740             * Initiates deserialization of all native C++ objects, which means all
741             * your C++ objects will be restored with the values contained in this
742             * Archive. So that also means calling deserialize() only makes sense if
743             * this a non-empty Archive, which i.e. is the case if you either called
744             * serialize() with this Archive object before or if you passed a
745             * previously serialized raw data stream to the constructor of this
746             * Archive object.
747             *
748             * This framework has a concept of a "root" object which you must pass
749             * to this method. The root object is the starting point for
750             * deserialization of your C++ objects. The framework will then
751             * recursively deserialize all members of that C++ object an continue to
752             * deserialize all other C++ objects that it might contain or point to,
753             * according to the values stored in this Archive.
754             *
755             * @param obj - native C++ root object where deserialization shall start
756             * @see Archive::operator>>()
757             *
758             * @throws Exception if the data stored in this Archive cannot be
759             *         restored to the C++ objects passed to this method, i.e.
760             *         because of version or type incompatibilities.
761             */
762          template<typename T>          template<typename T>
763          void deserialize(T* obj) {          void deserialize(T* obj) {
764              Archive a;              Archive a;
# Line 574  namespace Serialization { Line 769  namespace Serialization {
769              m_operation = OPERATION_NONE;              m_operation = OPERATION_NONE;
770          }          }
771    
772            /** @brief Initiate serialization of your C++ objects.
773             *
774             * Same as calling @c serialize(), this is just meant if you prefer
775             * to use operator based code instead, which you might find to be more
776             * intuitive.
777             *
778             * Example:
779             * @code
780             * Archive a;
781             * a << myRootObject;
782             * @endcode
783             *
784             * @see Archive::serialize() for more details.
785             */
786          template<typename T>          template<typename T>
787          void operator<<(const T& obj) {          void operator<<(const T& obj) {
788              serialize(&obj);              serialize(&obj);
789          }          }
790    
791            /** @brief Initiate deserialization of your C++ objects.
792             *
793             * Same as calling @c deserialize(), this is just meant if you prefer
794             * to use operator based code instead, which you might find to be more
795             * intuitive.
796             *
797             * Example:
798             * @code
799             * Archive a(rawDataStream);
800             * a >> myRootObject;
801             * @endcode
802             *
803             * @throws Exception if the data stored in this Archive cannot be
804             *         restored to the C++ objects passed to this method, i.e.
805             *         because of version or type incompatibilities.
806             *
807             * @see Archive::deserialize() for more details.
808             */
809          template<typename T>          template<typename T>
810          void operator>>(T& obj) {          void operator>>(T& obj) {
811              deserialize(&obj);              deserialize(&obj);
# Line 587  namespace Serialization { Line 814  namespace Serialization {
814          const RawData& rawData();          const RawData& rawData();
815          virtual String rawDataFormat() const;          virtual String rawDataFormat() const;
816    
817            /** @brief Serialize a native C/C++ member variable.
818             *
819             * This method is usually called by the serialize() method
820             * implementation of your C/C++ structs and classes, for each of the
821             * member variables that shall be serialized and deserialized
822             * automatically with this framework. It is recommend that you are not
823             * using this method name directly, but rather define a short hand C
824             * macro in your .cpp file like:
825             * @code
826             * #define SRLZ(member) \
827             *   archive->serializeMember(*this, member, #member);
828             *
829             * void Foo::serialize(Serialization::Archive* archive) {
830             *     SRLZ(a);
831             *     SRLZ(b);
832             *     SRLZ(c);
833             * }
834             * @endcode
835             * As you can see, using such a macro makes your code more readable and
836             * less error prone.
837             *
838             * It is completely up to you to decide which ones of your member
839             * variables shall automatically be serialized and deserialized with
840             * this framework. Only those member variables which are registered by
841             * calling this method will be serialized and deserialized. It does not
842             * really matter in which order you register your individiual member
843             * variables by calling this method, but the sequence is actually stored
844             * as meta information with the resulting archive and the resulting raw
845             * data stream. That meta information might then be used by this
846             * framework to automatically correct and adapt deserializing that
847             * archive later on for a future (or older) and potentially heavily
848             * modified version of your software. So it is recommended, even though
849             * also not required, that you may retain the sequence of your
850             * serializeMember() calls for your individual C++ classes' members over
851             * all your software versions, to retain backward compatibility of older
852             * archives as much as possible.
853             *
854             * @param nativeObject - native C++ object to be registered for
855             *                       serialization / deserialization
856             * @param nativeMember - native C++ member variable of @a nativeObject
857             *                       to be registered for serialization /
858             *                       deserialization
859             * @param memberName - name of @a nativeMember to be stored with this
860             *                     archive
861             */
862          template<typename T_classType, typename T_memberType>          template<typename T_classType, typename T_memberType>
863          void serializeMember(const T_classType& nativeObject, const T_memberType& nativeMember, const char* memberName) {          void serializeMember(const T_classType& nativeObject, const T_memberType& nativeMember, const char* memberName) {
864              const size_t offset =              const size_t offset =
# Line 615  namespace Serialization { Line 887  namespace Serialization {
887              }              }
888          }          }
889    
890          /** @brief Set version number for your C++ class.          /** @brief Set current version number for your C++ class.
891           *           *
892           * By calling this method you can store a version number for your           * By calling this method you can define a version number for your
893           * current C++ class (that is a version for its current data structure           * current C++ class (that is a version for its current data structure
894           * layout and method implementations) with serialized archive.           * layout and method implementations) that is going to be stored along
895             * with the serialized archive. Only call this method if you really want
896             * to constrain compatibility of your C++ class.
897           *           *
898           * Along with calling @c setMinVersion() this provides a way for you           * Along with calling @c setMinVersion() this provides a way for you
899           * to constrain backward compatiblity regarding serialization and           * to constrain backward compatibility regarding serialization and
900           * deserialization of your class which the Archive class will obey to.           * deserialization of your C++ class which the Archive class will obey
901           * If required, then typically you might do so in your @c serialize()           * to. If required, then typically you might do so in your
902           * method implementation like:           * @c serialize() method implementation like:
903           * @code           * @code
904           * #define SRLZ(member) \           * #define SRLZ(member) \
905           *   archive->serializeMember(*this, member, #member);           *   archive->serializeMember(*this, member, #member);
# Line 634  namespace Serialization { Line 908  namespace Serialization {
908           *     // when serializing: the current version of this class that is           *     // when serializing: the current version of this class that is
909           *     // going to be stored with the serialized archive           *     // going to be stored with the serialized archive
910           *     archive->setVersion(*this, 6);           *     archive->setVersion(*this, 6);
911           *     // when deserializing: the minimum allowed version of this class           *     // when deserializing: the minimum version this C++ class is
912           *     // being serialized in the past           *     // compatible with
913           *     archive->setMinVersion(*this, 3);           *     archive->setMinVersion(*this, 3);
914           *     // actual data mebers to serialize / deserialize           *     // actual data mebers to serialize / deserialize
915           *     SRLZ(a);           *     SRLZ(a);
# Line 643  namespace Serialization { Line 917  namespace Serialization {
917           *     SRLZ(c);           *     SRLZ(c);
918           * }           * }
919           * @endcode           * @endcode
920           * In this example above, the C++ clas "Foo" would be serialized along           * In this example above, the C++ class "Foo" would be serialized along
921           * with the version number @c 6 in the resulting archive (and its raw           * with the version number @c 6 and minimum version @c 3 as additional
922           * data stream respectively).           * meta information in the resulting archive (and its raw data stream
923             * respectively).
924           *           *
925           * When deserializing archives with the example C++ class code above,           * When deserializing archives with the example C++ class code above,
926           * the Archive object would check whether your originally serialized           * the Archive object would check whether your originally serialized
# Line 654  namespace Serialization { Line 929  namespace Serialization {
929           * @c Serialization::Exception, claiming that the classes are version           * @c Serialization::Exception, claiming that the classes are version
930           * incompatible.           * incompatible.
931           *           *
932             * But also consider the other way around: you might have serialized
933             * your latest version of your C++ class, and might deserialize that
934             * archive with an older version of your C++ class. In that case it will
935             * likewise be checked whether the version of that old C++ class is at
936             * least as high as the minimum version set with the already seralized
937             * bleeding edge C++ class.
938             *
939           * Since this Serialization / deserialization framework is designed to           * Since this Serialization / deserialization framework is designed to
940           * be robust on changes to your C++ classes and aims trying to           * be robust on changes to your C++ classes and aims trying to
941           * deserialize all your C++ objects correctly even if your C++ classes           * deserialize all your C++ objects correctly even if your C++ classes
942           * have seen substantial software changes in the meantime; you might           * have seen substantial software changes in the meantime; you might
943           * sometimes see it as necessary to constrain backward compatiblity           * sometimes see it as necessary to constrain backward compatibility
944           * this way.           * this way. Because obviously there are certain things this framework
945             * can cope with, like for example that you renamed a data member while
946             * keeping the layout consistent, or that you have added new members to
947             * your C++ class or simply changed the order of your members in your
948             * C++ class. But what this framework cannot detect is for example if
949             * you changed the semantics of the values stored with your members, or
950             * even substantially changed the algorithms in your class methods such
951             * that they would not handle the data of your C++ members in the same
952             * and correct way anymore.
953           *           *
954           * @param nativeObject - your C++ object you want to set a version for           * @param nativeObject - your C++ object you want to set a version for
955           * @param v - the version number to set for your C++ class (by default,           * @param v - the version number to set for your C++ class (by default,
# Line 682  namespace Serialization { Line 972  namespace Serialization {
972           *           *
973           * Call this method to define a minimum version that your current C++           * Call this method to define a minimum version that your current C++
974           * class implementation would be compatible with when it comes to           * class implementation would be compatible with when it comes to
975           * deserialization of an archive containing an object with an older           * deserialization of an archive containing an object of your C++ class.
976           * version of your C++ class.           * Like the version information, the minimum version will also be stored
977             * for objects of your C++ class with the resulting archive (and its
978             * resulting raw data stream respectively).
979             *
980             * When you start to constrain version compatibility of your C++ class
981             * you usually start by using 1 as version and 1 as minimum version.
982             * So it is eligible to set the same number to both version and minimum
983             * version. However you must @b not set a minimum version higher than
984             * version. Doing so would not raise an exception, but the resulting
985             * behavior would be undefined.
986             *
987             * It is not relevant whether you first set version and then minimum
988             * version or vice versa. It is also not relevant when exactly you set
989             * those two numbers, even though usually you would set both in your
990             * serialize() method implementation.
991           *           *
992           * @see @c setVersion() for more details about this overall topic.           * @see @c setVersion() for more details about this overall topic.
993             *
994             * @param nativeObject - your C++ object you want to set a version for
995             * @param v - the minimum version you want to define for your C++ class
996             *            (by default, that is if you do not explicitly call this
997             *            method, then a minium version of @c 0 is assumed for your
998             *            C++ class instead).
999           */           */
1000          template<typename T_classType>          template<typename T_classType>
1001          void setMinVersion(const T_classType& nativeObject, Version v) {          void setMinVersion(const T_classType& nativeObject, Version v) {

Legend:
Removed from v.3182  
changed lines
  Added in v.3183

  ViewVC Help
Powered by ViewVC