/[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 3156 by schoenebeck, Mon May 8 17:18:07 2017 UTC revision 3182 by schoenebeck, Sun May 14 20:40:02 2017 UTC
# Line 36  Line 36 
36  #include <map>  #include <map>
37  #include <time.h>  #include <time.h>
38    
39    #ifndef __has_extension
40    # define __has_extension(x) 0
41    #endif
42    
43    #ifndef HAS_BUILTIN_TYPE_TRAITS
44    # if __cplusplus >= 201103L
45    #  define HAS_BUILTIN_TYPE_TRAITS 1
46    # elif ( __has_extension(is_class) && __has_extension(is_enum) )
47    #  define HAS_BUILTIN_TYPE_TRAITS 1
48    # elif ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) )
49    #  define HAS_BUILTIN_TYPE_TRAITS 1
50    # elif _MSC_VER >= 1400 /* MS Visual C++ 8.0 (Visual Studio 2005) */
51    #  define HAS_BUILTIN_TYPE_TRAITS 1
52    # elif __INTEL_COMPILER >= 1100
53    #  define HAS_BUILTIN_TYPE_TRAITS 1
54    # else
55    #  define HAS_BUILTIN_TYPE_TRAITS 0
56    # endif
57    #endif
58    
59    #if !HAS_BUILTIN_TYPE_TRAITS
60    # include <tr1/type_traits>
61    # define LIBGIG_IS_CLASS(type) std::tr1::__is_union_or_class<type>::value //NOTE: without compiler support we cannot distinguish union from class
62    #else
63    # define LIBGIG_IS_CLASS(type) __is_class(type)
64    #endif
65    
66  /** @brief Serialization / deserialization framework.  /** @brief Serialization / deserialization framework.
67   *   *
68   * See class Archive as starting point for how to implement serialization and   * See class Archive as starting point for how to implement serialization and
# Line 97  namespace Serialization { Line 124  namespace Serialization {
124    
125      typedef uint32_t Version;      typedef uint32_t Version;
126    
     enum operation_t {  
         OPERATION_NONE,  
         OPERATION_SERIALIZE,  
         OPERATION_DESERIALIZE  
     };  
   
127      enum time_base_t {      enum time_base_t {
128          LOCAL_TIME,          LOCAL_TIME,
129          UTC_TIME          UTC_TIME
# Line 110  namespace Serialization { Line 131  namespace Serialization {
131    
132      template<typename T>      template<typename T>
133      bool IsEnum(const T& data) {      bool IsEnum(const T& data) {
134            #if !HAS_BUILTIN_TYPE_TRAITS
135            return std::tr1::is_enum<T>::value;
136            #else
137          return __is_enum(T);          return __is_enum(T);
138            #endif
139      }      }
140    
141      template<typename T>      template<typename T>
142      bool IsUnion(const T& data) {      bool IsUnion(const T& data) {
143            #if !HAS_BUILTIN_TYPE_TRAITS
144            return false; // without compiler support we cannot distinguish union from class
145            #else
146          return __is_union(T);          return __is_union(T);
147            #endif
148      }      }
149    
150      template<typename T>      template<typename T>
151      bool IsClass(const T& data) {      bool IsClass(const T& data) {
152            #if !HAS_BUILTIN_TYPE_TRAITS
153            return std::tr1::__is_union_or_class<T>::value; // without compiler support we cannot distinguish union from class
154            #else
155          return __is_class(T);          return __is_class(T);
156            #endif
157      }      }
158    
159      /*template<typename T>      /*template<typename T>
# Line 162  namespace Serialization { Line 195  namespace Serialization {
195          template<typename T>          template<typename T>
196          struct Resolver {          struct Resolver {
197              static UID resolve(const T& obj) {              static UID resolve(const T& obj) {
198                  return (UID) { (ID) &obj, sizeof(obj) };                  const UID uid = { (ID) &obj, sizeof(obj) };
199                    return uid;
200              }              }
201          };          };
202    
# Line 170  namespace Serialization { Line 204  namespace Serialization {
204          template<typename T>          template<typename T>
205          struct Resolver<T*> {          struct Resolver<T*> {
206              static UID resolve(const T* const & obj) {              static UID resolve(const T* const & obj) {
207                  return (UID) { (ID) obj, sizeof(*obj) };                  const UID uid = { (ID) obj, sizeof(*obj) };
208                    return uid;
209              }              }
210          };          };
211      };      };
# Line 190  namespace Serialization { Line 225  namespace Serialization {
225      static Object _popObjectBlob(const char*& p, const char* end);      static Object _popObjectBlob(const char*& p, const char* end);
226      static void _popPrimitiveValue(const char*& p, const char* end, Object& obj);      static void _popPrimitiveValue(const char*& p, const char* end, Object& obj);
227      static String _primitiveObjectValueToString(const Object& obj);      static String _primitiveObjectValueToString(const Object& obj);
228        //  |
229        template<typename T>
230        static T _primitiveObjectValueToNumber(const Object& obj);
231    
232      /** @brief Abstract reflection of a native C++ data type.      /** @brief Abstract reflection of a native C++ data type.
233       *       *
# Line 219  namespace Serialization { Line 257  namespace Serialization {
257          bool operator>(const DataType& other) const;          bool operator>(const DataType& other) const;
258          String asLongDescr() const;          String asLongDescr() const;
259          String baseTypeName() const { return m_baseTypeName; }          String baseTypeName() const { return m_baseTypeName; }
260          String customTypeName() const { return m_customTypeName; }          String customTypeName(bool demangle = false) const;
261    
262          template<typename T>          template<typename T>
263          static DataType dataTypeOf(const T& data) {          static DataType dataTypeOf(const T& data) {
# Line 350  namespace Serialization { Line 388  namespace Serialization {
388          const UIDChain& uidChain() const { return m_uid; }          const UIDChain& uidChain() const { return m_uid; }
389          const DataType& type() const { return m_type; }          const DataType& type() const { return m_type; }
390          const RawData& rawData() const { return m_data; }          const RawData& rawData() const { return m_data; }
   
391          Version version() const { return m_version; }          Version version() const { return m_version; }
   
         void setVersion(Version v) {  
             m_version = v;  
         }  
   
392          Version minVersion() const { return m_minVersion; }          Version minVersion() const { return m_minVersion; }
   
         void setMinVersion(Version v) {  
             m_minVersion = v;  
         }  
   
393          bool isVersionCompatibleTo(const Object& other) const;          bool isVersionCompatibleTo(const Object& other) const;
   
394          std::vector<Member>& members() { return m_members; }          std::vector<Member>& members() { return m_members; }
395          const std::vector<Member>& members() const { return m_members; }          const std::vector<Member>& members() const { return m_members; }
396          Member memberNamed(String name) const;          Member memberNamed(String name) const;
# Line 381  namespace Serialization { Line 407  namespace Serialization {
407    
408      protected:      protected:
409          void remove(const Member& member);          void remove(const Member& member);
410            void setVersion(Version v);
411            void setMinVersion(Version v);
412    
413      private:      private:
414          DataType m_type;          DataType m_type;
# Line 394  namespace Serialization { Line 422  namespace Serialization {
422          friend Object _popObjectBlob(const char*& p, const char* end);          friend Object _popObjectBlob(const char*& p, const char* end);
423          friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj);          friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj);
424          friend String _primitiveObjectValueToString(const Object& obj);          friend String _primitiveObjectValueToString(const Object& obj);
425    
426            template<typename T>
427            friend T _primitiveObjectValueToNumber(const Object& obj);
428    
429          friend class Archive;          friend class Archive;
430      };      };
431    
# Line 509  namespace Serialization { Line 541  namespace Serialization {
541       * Note that there is only one method that you need to implement. So the       * Note that there is only one method that you need to implement. So the
542       * respective serialize() method implementation of your classes/structs are       * respective serialize() method implementation of your classes/structs are
543       * both called for serialization, as well as for deserialization!       * both called for serialization, as well as for deserialization!
544         *
545         * In case you need to enforce backward incompatiblity for one of your C++
546         * classes, you can do so by setting a version and minimum version for your
547         * class (see @c setVersion() and @c setMinVersion() for details).
548       */       */
549      class Archive {      class Archive {
550      public:      public:
# Line 554  namespace Serialization { Line 590  namespace Serialization {
590          template<typename T_classType, typename T_memberType>          template<typename T_classType, typename T_memberType>
591          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) {
592              const size_t offset =              const size_t offset =
593              ((const uint8_t*)(const void*)&nativeMember) -                  ((const uint8_t*)(const void*)&nativeMember) -
594              ((const uint8_t*)(const void*)&nativeObject);                  ((const uint8_t*)(const void*)&nativeObject);
595              const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);              const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
596              const DataType type = DataType::dataTypeOf(nativeMember);              const DataType type = DataType::dataTypeOf(nativeMember);
597              const Member member(memberName, uids[0], offset, type);              const Member member(memberName, uids[0], offset, type);
# Line 579  namespace Serialization { Line 615  namespace Serialization {
615              }              }
616          }          }
617    
618            /** @brief Set version number for your C++ class.
619             *
620             * By calling this method you can store a version number for your
621             * current C++ class (that is a version for its current data structure
622             * layout and method implementations) with serialized archive.
623             *
624             * Along with calling @c setMinVersion() this provides a way for you
625             * to constrain backward compatiblity regarding serialization and
626             * deserialization of your class which the Archive class will obey to.
627             * If required, then typically you might do so in your @c serialize()
628             * method implementation like:
629             * @code
630             * #define SRLZ(member) \
631             *   archive->serializeMember(*this, member, #member);
632             *
633             * void Foo::serialize(Serialization::Archive* archive) {
634             *     // when serializing: the current version of this class that is
635             *     // going to be stored with the serialized archive
636             *     archive->setVersion(*this, 6);
637             *     // when deserializing: the minimum allowed version of this class
638             *     // being serialized in the past
639             *     archive->setMinVersion(*this, 3);
640             *     // actual data mebers to serialize / deserialize
641             *     SRLZ(a);
642             *     SRLZ(b);
643             *     SRLZ(c);
644             * }
645             * @endcode
646             * In this example above, the C++ clas "Foo" would be serialized along
647             * with the version number @c 6 in the resulting archive (and its raw
648             * data stream respectively).
649             *
650             * When deserializing archives with the example C++ class code above,
651             * the Archive object would check whether your originally serialized
652             * C++ "Foo" object had at least version number @c 3, if not the
653             * deserialization process would automatically be stopped with a
654             * @c Serialization::Exception, claiming that the classes are version
655             * incompatible.
656             *
657             * Since this Serialization / deserialization framework is designed to
658             * be robust on changes to your C++ classes and aims trying to
659             * deserialize all your C++ objects correctly even if your C++ classes
660             * have seen substantial software changes in the meantime; you might
661             * sometimes see it as necessary to constrain backward compatiblity
662             * this way.
663             *
664             * @param nativeObject - your C++ object you want to set a version for
665             * @param v - the version number to set for your C++ class (by default,
666             *            that is if you do not explicitly call this method, then
667             *            your C++ object will be stored with version number @c 0 ).
668             */
669            template<typename T_classType>
670            void setVersion(const T_classType& nativeObject, Version v) {
671                const UID uid = UID::from(nativeObject);
672                Object& obj = m_allObjects[uid];
673                if (!obj) {
674                    const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
675                    const DataType type = DataType::dataTypeOf(nativeObject);
676                    obj = Object(uids, type);
677                }
678                setVersion(obj, v);
679            }
680    
681            /** @brief Set a minimum version number for your C++ class.
682             *
683             * Call this method to define a minimum version that your current C++
684             * class implementation would be compatible with when it comes to
685             * deserialization of an archive containing an object with an older
686             * version of your C++ class.
687             *
688             * @see @c setVersion() for more details about this overall topic.
689             */
690            template<typename T_classType>
691            void setMinVersion(const T_classType& nativeObject, Version v) {
692                const UID uid = UID::from(nativeObject);
693                Object& obj = m_allObjects[uid];
694                if (!obj) {
695                    const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
696                    const DataType type = DataType::dataTypeOf(nativeObject);
697                    obj = Object(uids, type);
698                }
699                setMinVersion(obj, v);
700            }
701    
702          virtual void decode(const RawData& data);          virtual void decode(const RawData& data);
703          virtual void decode(const uint8_t* data, size_t size);          virtual void decode(const uint8_t* data, size_t size);
704          void clear();          void clear();
# Line 593  namespace Serialization { Line 713  namespace Serialization {
713          void setBoolValue(Object& object, bool value);          void setBoolValue(Object& object, bool value);
714          void setEnumValue(Object& object, uint64_t value);          void setEnumValue(Object& object, uint64_t value);
715          String valueAsString(const Object& object);          String valueAsString(const Object& object);
716            int64_t valueAsInt(const Object& object);
717            double valueAsReal(const Object& object);
718            bool valueAsBool(const Object& object);
719            void setVersion(Object& object, Version v);
720            void setMinVersion(Object& object, Version v);
721          String name() const;          String name() const;
722          void setName(String name);          void setName(String name);
723          String comment() const;          String comment() const;
# Line 622  namespace Serialization { Line 747  namespace Serialization {
747          class UIDChainResolver<T*> {          class UIDChainResolver<T*> {
748          public:          public:
749              UIDChainResolver(const T*& data) {              UIDChainResolver(const T*& data) {
750                  m_uid.push_back((UID) { &data, sizeof(data) });                  const UID uids[2] = {
751                  m_uid.push_back((UID) { data, sizeof(*data) });                      { &data, sizeof(data) },
752                        { data, sizeof(*data) }
753                    };
754                    m_uid.push_back(uids[0]);
755                    m_uid.push_back(uids[1]);
756              }              }
757    
758              operator UIDChain() const { return m_uid; }              operator UIDChain() const { return m_uid; }
# Line 663  namespace Serialization { Line 792  namespace Serialization {
792    
793          // Automatically handles recursion for class/struct types, while ignoring all primitive types.          // Automatically handles recursion for class/struct types, while ignoring all primitive types.
794          template<typename T>          template<typename T>
795          struct SerializationRecursion : SerializationRecursionImpl<T, __is_class(T)> {          struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
796          };          };
797    
798          class ObjectPool : public std::map<UID,Object> {          class ObjectPool : public std::map<UID,Object> {
# Line 701  namespace Serialization { Line 830  namespace Serialization {
830              Archive& m_src;              Archive& m_src;
831          };          };
832    
833            enum operation_t {
834                OPERATION_NONE,
835                OPERATION_SERIALIZE,
836                OPERATION_DESERIALIZE
837            };
838    
839          virtual void encode();          virtual void encode();
840    
841          ObjectPool m_allObjects;          ObjectPool m_allObjects;

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

  ViewVC Help
Powered by ViewVC