/[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 3776 by schoenebeck, Sat May 23 19:26:07 2020 UTC revision 3777 by schoenebeck, Sat May 23 19:55:32 2020 UTC
# Line 156  namespace Serialization { Line 156  namespace Serialization {
156      template<class T>      template<class T>
157      using Set = std::set<T>;      using Set = std::set<T>;
158    
159        /** @brief Map<> template.
160         *
161         * This type is used for built-in automatic serialization / deserialization
162         * of C++ associative sorted map containers (a.k.a. @c std::map from the
163         * STL). This framework supports serializing this common data type out of
164         * the box, with the following 2 constraints:
165         *
166         * 1. The precise key type (i.e. 1st template parameter) used with maps must
167         *    be either a primitive data type (e.g. @c int, @c double, @c bool,
168         *    etc.) or a @c String object.
169         *
170         * 2. The value type (i.e. 2nd template parameter) must be serializable. So
171         *    the map's value type should either be a) any primitive data type (e.g.
172         *    @c int, @c double, etc.) or b) any other data structure or class types
173         *    enjoying out of the box serialization support by this framework, or c)
174         *    if it is a custom @c struct or @c class then it must have a
175         *    @c serialize() method implementation.
176         */
177        template<class T_key, class T_value>
178        using Map = std::map<T_key,T_value>;
179    
180      /** @brief Raw data stream of serialized C++ objects.      /** @brief Raw data stream of serialized C++ objects.
181       *       *
182       * This data type is used for the data stream as a result of serializing       * This data type is used for the data stream as a result of serializing
# Line 424  namespace Serialization { Line 445  namespace Serialization {
445          bool isEnum() const;          bool isEnum() const;
446          bool isArray() const;          bool isArray() const;
447          bool isSet() const;          bool isSet() const;
448            bool isMap() const;
449          bool isSigned() const;          bool isSigned() const;
450          operator bool() const { return isValid(); } ///< Same as calling isValid().          operator bool() const { return isValid(); } ///< Same as calling isValid().
451          //bool operator()() const { return isValid(); }          //bool operator()() const { return isValid(); }
# Line 434  namespace Serialization { Line 456  namespace Serialization {
456          String asLongDescr() const;          String asLongDescr() const;
457          String baseTypeName() const;          String baseTypeName() const;
458          String customTypeName(bool demangle = false) const;          String customTypeName(bool demangle = false) const;
459            String customTypeName2(bool demangle = false) const;
460    
461          /** @brief Construct a DataType object for the given native C++ data.          /** @brief Construct a DataType object for the given native C++ data.
462           *           *
# Line 451  namespace Serialization { Line 474  namespace Serialization {
474          }          }
475    
476      protected:      protected:
477          DataType(bool isPointer, int size, String baseType, String customType = "");          DataType(bool isPointer, int size, String baseType,
478                     String customType1 = "", String customType2 = "");
479    
480          template<typename T, bool T_isPointer>          template<typename T, bool T_isPointer>
481          struct ResolverBase {          struct ResolverBase {
# Line 553  namespace Serialization { Line 577  namespace Serialization {
577              }              }
578          };          };
579    
580            // DataType resolver for non-pointer Map<> container object types.
581            template<typename T_key, typename T_value>
582            struct Resolver<Map<T_key,T_value>> {
583                static DataType resolve(const Map<T_key,T_value>& data) {
584                    const int sz = sizeof(data);
585                    T_key unused1;
586                    T_value unused2;
587                    return DataType(false, sz, "Map", rawCppTypeNameOf(unused1),
588                                    rawCppTypeNameOf(unused2));
589                }
590            };
591    
592            // DataType resolver for Map<> pointer types (of 1st degree).
593            template<typename T_key, typename T_value>
594            struct Resolver<Map<T_key,T_value>*> {
595                static DataType resolve(const Map<T_key,T_value>*& data) {
596                    const int sz = sizeof(*data);
597                    T_key unused1;
598                    T_value unused2;
599                    return DataType(true, sz, "Map", rawCppTypeNameOf(unused1),
600                                    rawCppTypeNameOf(unused2));
601                }
602            };
603    
604          template<typename T>          template<typename T>
605          static String rawCppTypeNameOf(const T& data) {          static String rawCppTypeNameOf(const T& data) {
606              #if defined _MSC_VER // Microsoft compiler ...              #if defined _MSC_VER // Microsoft compiler ...
# Line 568  namespace Serialization { Line 616  namespace Serialization {
616      private:      private:
617          String m_baseTypeName;          String m_baseTypeName;
618          String m_customTypeName;          String m_customTypeName;
619            String m_customTypeName2;
620          int m_size;          int m_size;
621          bool m_isPointer;          bool m_isPointer;
622    
# Line 744  namespace Serialization { Line 793  namespace Serialization {
793       * a >> myRootObject;       * a >> myRootObject;
794       * @endcode       * @endcode
795       * Now this framework automatically handles serialization and       * Now this framework automatically handles serialization and
796       * deserialization of fundamental data types automatically for you (like       * deserialization of fundamental data types (like i.e. @c char, @c int,
797       * i.e. char, int, long int, float, double, etc.). However for your own       * @c long @c int, @c float, @c double, etc.) and common C++ classes
798       * custom C++ classes and structs you must implement one method which       * (currently: @c std::string, @c std::vector, @c std::set and @c std::map)
799       * defines which members of your class should actually be serialized and       * automatically for you. However for your own custom C++ classes and
800       * deserialized. That method to be added must have the following signature:       * structs you must implement one method which defines which members of your
801         * class / struct should actually be serialized and deserialized. That
802         * method to be added must have the following signature:
803       * @code       * @code
804       * void serialize(Serialization::Archive* archive);       * void serialize(Serialization::Archive* archive);
805       * @endcode       * @endcode
# Line 758  namespace Serialization { Line 809  namespace Serialization {
809       *     int a;       *     int a;
810       *     bool b;       *     bool b;
811       *     double c;       *     double c;
812         *     std::string text;
813         *     std::vector<int> v;
814       * };       * };
815       *       *
816       * struct Bar {       * struct Bar {
# Line 766  namespace Serialization { Line 819  namespace Serialization {
819       *     Foo   foo1;       *     Foo   foo1;
820       *     Foo*  pFoo2;       *     Foo*  pFoo2;
821       *     Foo*  pFoo3DontTouchMe; // shall not be serialized/deserialized       *     Foo*  pFoo3DontTouchMe; // shall not be serialized/deserialized
822         *     std::set<int> someSet;
823         *     std::map<double,Foo> someMap;
824       * };       * };
825       * @endcode       * @endcode
826       * So in order to be able to serialize and deserialize objects of those two       * So in order to be able to serialize and deserialize objects of those two
# Line 776  namespace Serialization { Line 831  namespace Serialization {
831       *     int a;       *     int a;
832       *     bool b;       *     bool b;
833       *     double c;       *     double c;
834         *     std::string text;
835         *     std::vector<int> v;
836       *       *
837       *     void serialize(Serialization::Archive* archive);       *     void serialize(Serialization::Archive* archive);
838       * };       * };
# Line 786  namespace Serialization { Line 843  namespace Serialization {
843       *     Foo   foo1;       *     Foo   foo1;
844       *     Foo*  pFoo2;       *     Foo*  pFoo2;
845       *     Foo*  pFoo3DontTouchMe; // shall not be serialized/deserialized       *     Foo*  pFoo3DontTouchMe; // shall not be serialized/deserialized
846         *     std::set<int> someSet;
847         *     std::map<double,Foo> someMap;
848       *       *
849       *     void serialize(Serialization::Archive* archive);       *     void serialize(Serialization::Archive* archive);
850       * };       * };
# Line 800  namespace Serialization { Line 859  namespace Serialization {
859       *     SRLZ(a);       *     SRLZ(a);
860       *     SRLZ(b);       *     SRLZ(b);
861       *     SRLZ(c);       *     SRLZ(c);
862         *     SRLZ(text);
863         *     SRLZ(v);
864       * }       * }
865       *       *
866       * void Bar::serialize(Serialization::Archive* archive) {       * void Bar::serialize(Serialization::Archive* archive) {
# Line 808  namespace Serialization { Line 869  namespace Serialization {
869       *     SRLZ(foo1);       *     SRLZ(foo1);
870       *     SRLZ(pFoo2);       *     SRLZ(pFoo2);
871       *     // leaving out pFoo3DontTouchMe here       *     // leaving out pFoo3DontTouchMe here
872         *     SRLZ(someSet);
873         *     SRLZ(someMap);
874       * }       * }
875       * @endcode       * @endcode
876       * Now when you serialize such a Bar object, this framework will also       * And that's it!
877       * automatically serialize the respective Foo object(s) accordingly, also       *
878       * for the pFoo2 pointer for instance (as long as it is not a NULL pointer       * Now when you serialize such a @c Bar object, this framework will also
879       * that is).       * automatically serialize the respective @c Foo object(s) accordingly, also
880         * for the @c pFoo2 pointer for instance (as long as it is not a @c NULL
881         * pointer that is).
882       *       *
883       * 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
884       * respective serialize() method implementation of your classes/structs are       * respective @c serialize() method implementation of your classes/structs
885       * both called for serialization, as well as for deserialization!       * are both called for serialization, as well as for deserialization!
886         * Usually you don't need to know whether your @c serialize() method was
887         * called for serialization or deserialization, however if you need to do
888         * know for some reason you can call @c archive->operation() inside your
889         * @c serialize() method to distinguish between the two.
890       *       *
891       * In case you need to enforce backward incompatiblity for one of your C++       * In case you need to enforce backward incompatibility for one of your C++
892       * classes, you can do so by setting a version and minimum version for your       * classes, you can do so by setting a version and minimum version for your
893       * class (see @c setVersion() and @c setMinVersion() for details).       * class (see @c setVersion() and @c setMinVersion() for details).
894       */       */
# Line 1050  namespace Serialization { Line 1119  namespace Serialization {
1119           * @discussion To avoid member name conflicts with native members, it is           * @discussion To avoid member name conflicts with native members, it is
1120           * recommended to always choose member names which would be impossible           * recommended to always choose member names which would be impossible
1121           * as names to be declared in C/C++ code. For instance this framework           * as names to be declared in C/C++ code. For instance this framework
1122           * uses heap member names "[0]", "[1]", "[3]", ... in its out of the box           * uses heap member names "[0]", "[1]", "[2]", ... in its out of the box
1123           * support when serializing elements of @c Array<> objects, since           * support when serializing elements of @c Array<> objects, since
1124           * brackets in general cannot be used as part of variable names in C++,           * brackets in general cannot be used as part of variable names in C++,
1125           * so using such or other special characters in heap member names, makes           * so using such or other special characters in heap member names, makes
# Line 1435  namespace Serialization { Line 1504  namespace Serialization {
1504              }              }
1505          };          };
1506    
1507            // SerializationRecursion for Map<> objects.
1508            template<typename T_key, typename T_value, bool T_isRecursive>
1509            struct SerializationRecursionImpl<Map<T_key,T_value>,T_isRecursive> {
1510                static void serializeObject(Archive* archive, const Map<T_key,T_value>& obj) {
1511                    const UIDChain uids = UIDChainResolver<Map<T_key,T_value>>(obj);
1512                    const Object& object = archive->objectByUID(uids[0]);
1513                    if (archive->operation() == OPERATION_SERIALIZE) {
1514                        for (const auto& it : obj) {
1515                            archive->serializeHeapMember(
1516                                obj, it.second, ("[" + toString(it.first) + "]").c_str()
1517                            );
1518                        }
1519                    } else {
1520                        const_cast<Object&>(object).m_sync =
1521                            [&obj,archive](Object& dstObj, const Object& srcObj,
1522                                           void* syncer)
1523                        {
1524                            const size_t n = srcObj.members().size();
1525                            const_cast<Map<T_key,T_value>&>(obj).clear();
1526                            for (size_t i = 0; i < n; ++i) {
1527                                const Member& member = srcObj.members()[i];
1528                                String name = member.name();
1529                                if (name.length() < 2 || name[0] != '[' ||
1530                                    *name.rbegin() != ']') continue;
1531                                name = name.substr(1, name.length() - 2);
1532                                T_key key;
1533                                const UIDChain uids = UIDChainResolver<T_key>(key);
1534                                const DataType type = DataType::dataTypeOf(key);
1535                                Object tmpObj(uids, type);
1536                                tmpObj.setNativeValueFromString(name);
1537                                const_cast<Map<T_key,T_value>&>(obj)[key] = T_value();
1538                            }
1539                            for (const auto& it : obj) {
1540                                archive->serializeHeapMember(
1541                                    obj, it.second, ("[" + toString(it.first) + "]").c_str()
1542                                );
1543                            }
1544                            // updating dstObj required as serializeHeapMember()
1545                            // replaced the original object by a new one
1546                            dstObj = archive->objectByUID(dstObj.uid());
1547                            for (size_t i = 0; i < n; ++i) {
1548                                Member srcMember = srcObj.members()[i];
1549                                Member dstMember = dstObj.memberNamed(srcMember.name());
1550                                ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1551                            }
1552                        };
1553                    }
1554                }
1555            };
1556    
1557            // SerializationRecursion for Map<> pointers (of 1st degree).
1558            template<typename T_key, typename T_value, bool T_isRecursive>
1559            struct SerializationRecursionImpl<Map<T_key,T_value>*,T_isRecursive> {
1560                static void serializeObject(Archive* archive, const Map<T_key,T_value>*& obj) {
1561                    if (!obj) return;
1562                    SerializationRecursionImpl<Map<T_key,T_value>,T_isRecursive>::serializeObject(
1563                        archive, *obj
1564                    );
1565                }
1566            };
1567    
1568          // Automatically handles recursion for class/struct types, while ignoring all primitive types.          // Automatically handles recursion for class/struct types, while ignoring all primitive types.
1569          template<typename T>          template<typename T>
1570          struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {          struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
# Line 1508  namespace Serialization { Line 1638  namespace Serialization {
1638              void syncString(const Object& dst, const Object& src);              void syncString(const Object& dst, const Object& src);
1639              void syncArray(const Object& dst, const Object& src);              void syncArray(const Object& dst, const Object& src);
1640              void syncSet(const Object& dst, const Object& src);              void syncSet(const Object& dst, const Object& src);
1641                void syncMap(const Object& dst, const Object& src);
1642              void syncPointer(const Object& dst, const Object& src);              void syncPointer(const Object& dst, const Object& src);
1643              void syncMember(const Member& dstMember, const Member& srcMember);              void syncMember(const Member& dstMember, const Member& srcMember);
1644          protected:          protected:

Legend:
Removed from v.3776  
changed lines
  Added in v.3777

  ViewVC Help
Powered by ViewVC