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

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

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

revision 3774 by schoenebeck, Tue May 19 14:55:48 2020 UTC revision 3777 by schoenebeck, Sat May 23 19:55:32 2020 UTC
# Line 101  namespace Serialization { Line 101  namespace Serialization {
101       *                   type in a coarse way, which must be either one of:       *                   type in a coarse way, which must be either one of:
102       *                   "int8", "uint8", "int16", "uint16", "int32", "uint32",       *                   "int8", "uint8", "int16", "uint16", "int32", "uint32",
103       *                   "int64", "uint64", "bool", "real32", "real64",       *                   "int64", "uint64", "bool", "real32", "real64",
104       *                   "String", "enum", "union" or "class"       *                   "String", "Array", "Set", "enum", "union" or "class"
105       * @param customType - this is only used for base types "enum", "union" or       * @param customType1 - this is only used for base types "enum", "union",
106       *                     "class", in which case this identifies the user       *                     "class", "Array", "Set" or "Map", in which case this
107       *                     defined type name (e.g. "Foo" for @c class @c Foo ),       *                      identifies the user defined type name (e.g. "Foo" for
108       *                     for all other types this is empty       *                      @c class @c Foo or e.g. "Bar" for @c Array<Bar>
109         *                      respectively), for all other types this is empty
110         * @param customType2 - this is only used for @c Map<> objects in which case
111         *                      it identifies the map's value type (i.e. 2nd
112         *                      template parameter of map)
113       */       */
114      DataType::DataType(bool isPointer, int size, String baseType, String customType) {      DataType::DataType(bool isPointer, int size, String baseType,
115                           String customType1, String customType2)
116        {
117          m_size = size;          m_size = size;
118          m_isPointer = isPointer;          m_isPointer = isPointer;
119          m_baseTypeName = baseType;          m_baseTypeName = baseType;
120          m_customTypeName = customType;          m_customTypeName = customType1;
121            m_customTypeName2 = customType2;
122      }      }
123    
124      /** @brief Check if this is a valid DataType object.      /** @brief Check if this is a valid DataType object.
# Line 141  namespace Serialization { Line 148  namespace Serialization {
148       *       *
149       * Returns @c true if the respective native C/C++ object, member or variable       * Returns @c true if the respective native C/C++ object, member or variable
150       * (this DataType instance is reflecting) is a C/C++ @c struct or @c class       * (this DataType instance is reflecting) is a C/C++ @c struct or @c class
151       * type, with one exception: @c String objects are handled by this framework       * type.
152       * as if they were a primitive type.       *
153         * @note: Data types which enjoy out of the box serialization support by
154         * this framework, like @c String and @c Array<> are @b NOT handled as class
155         * data types by this framwork. So @c isClass() returns @c false for e.g.
156         * @c String and any @c Array<> based data type.
157       *       *
158       * Note that in the following example:       * Note that in the following example:
159       * @code       * @code
# Line 183  namespace Serialization { Line 194  namespace Serialization {
194       * @see isPointer()       * @see isPointer()
195       */       */
196      bool DataType::isPrimitive() const {      bool DataType::isPrimitive() const {
197          return !isClass();          return !isClass() && !isArray() && !isSet() && !isMap();
198      }      }
199    
200      /** @brief Whether this is a C++ @c String data type.      /** @brief Whether this is a C++ @c String data type.
# Line 265  namespace Serialization { Line 276  namespace Serialization {
276          return m_baseTypeName == "enum";          return m_baseTypeName == "enum";
277      }      }
278    
279        /** @brief Whether this is a C++ @c Array<> object type.
280         *
281         * Returns @c true if the respective native C/C++ object, member or variable
282         * (this DataType instance is reflecting) is a C++ @c Array<> container
283         * object type.
284         *
285         * @note: This framework handles @c Array<> types neither as primitive
286         * types, nor as class types. So @c isPrimitive() and @c isClass() both
287         * return @c false for arrays.
288         *
289         * @see isPointer()
290         */
291        bool DataType::isArray() const {
292            return m_baseTypeName == "Array";
293        }
294    
295        /** @brief Whether this is a C++ @c Set<> object type.
296         *
297         * Returns @c true if the respective native C/C++ object, member or variable
298         * (this DataType instance is reflecting) is a C++ @c Set<> unique container
299         * object type.
300         *
301         * @note: This framework handles @c Set<> types neither as primitive
302         * types, nor as class types. So @c isPrimitive() and @c isClass() both
303         * return @c false for sets.
304         *
305         * @see isPointer()
306         */
307        bool DataType::isSet() const {
308            return m_baseTypeName == "Set";
309        }
310    
311        /** @brief Whether this is a C++ @c Map<> object type.
312         *
313         * Returns @c true if the respective native C/C++ object, member or variable
314         * (this DataType instance is reflecting) is an associative sorted C++
315         * @c Map<> container object type.
316         *
317         * @note: This framework handles @c Map<> types neither as primitive
318         * types, nor as class types. So @c isPrimitive() and @c isClass() both
319         * return @c false for maps.
320         *
321         * @see isPointer()
322         */
323        bool DataType::isMap() const {
324            return m_baseTypeName == "Map";
325        }
326    
327      /** @brief Whether this is a signed integer C/C++ data type.      /** @brief Whether this is a signed integer C/C++ data type.
328       *       *
329       * Returns @c true if the respective native C/C++ object, member or variable       * Returns @c true if the respective native C/C++ object, member or variable
# Line 304  namespace Serialization { Line 363  namespace Serialization {
363      bool DataType::operator==(const DataType& other) const {      bool DataType::operator==(const DataType& other) const {
364          return m_baseTypeName   == other.m_baseTypeName &&          return m_baseTypeName   == other.m_baseTypeName &&
365                 m_customTypeName == other.m_customTypeName &&                 m_customTypeName == other.m_customTypeName &&
366                   m_customTypeName2 == other.m_customTypeName2 &&
367                 (m_size == other.m_size || (isClass() && other.isClass())) &&                 (m_size == other.m_size || (isClass() && other.isClass())) &&
368                 m_isPointer      == other.m_isPointer;                 m_isPointer      == other.m_isPointer;
369      }      }
# Line 333  namespace Serialization { Line 393  namespace Serialization {
393                (m_baseTypeName == other.m_baseTypeName &&                (m_baseTypeName == other.m_baseTypeName &&
394                (m_customTypeName  < other.m_customTypeName ||                (m_customTypeName  < other.m_customTypeName ||
395                (m_customTypeName == other.m_customTypeName &&                (m_customTypeName == other.m_customTypeName &&
396                  (m_customTypeName2  < other.m_customTypeName2 ||
397                  (m_customTypeName2 == other.m_customTypeName2 &&
398                (m_size  < other.m_size ||                (m_size  < other.m_size ||
399                (m_size == other.m_size &&                (m_size == other.m_size &&
400                 m_isPointer < other.m_isPointer)))));                 m_isPointer < other.m_isPointer)))))));
401      }      }
402    
403      /** @brief Greater than comparison.      /** @brief Greater than comparison.
# Line 371  namespace Serialization { Line 433  namespace Serialization {
433          String s = m_baseTypeName;          String s = m_baseTypeName;
434          if (!m_customTypeName.empty())          if (!m_customTypeName.empty())
435              s += " " + customTypeName(true);              s += " " + customTypeName(true);
436            if (!m_customTypeName2.empty())
437                s += " " + customTypeName2(true);
438          if (isPointer())          if (isPointer())
439              s += " pointer";              s += " pointer";
440          return s;          return s;
# Line 403  namespace Serialization { Line 467  namespace Serialization {
467       * @endcode       * @endcode
468       * this method would return for both @c i and @c pi the string @c "uint64" !       * this method would return for both @c i and @c pi the string @c "uint64" !
469       *       *
470       * @see isPointer(), customTypeName()       * @see isPointer(), customTypeName(), customTypeName2()
471       */       */
472      String DataType::baseTypeName() const {      String DataType::baseTypeName() const {
473          return m_baseTypeName;          return m_baseTypeName;
474      }      }
475    
476      /** @brief The user defined C/C++ data type name of this data type.      static String _demangleTypeName(const char* name) {
477    #ifdef _MSC_VER
478            const size_t MAXLENGTH = 1024;
479            char result[MAXLENGTH];
480    
481            //FIXME: calling UnDecorateSymbolName() is not thread safe!
482            //Skip the first char
483            size_t size = UnDecorateSymbolName(name + 1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
484            if (size)
485            {
486                return result;
487            }
488            return name;
489    #else
490            int status;
491            char* result =
492                abi::__cxa_demangle(name, 0, 0, &status);
493            String sResult = result;
494            free(result);
495            return (status == 0) ? sResult : name;
496    #endif
497        }
498    
499        /** @brief The 1st user defined C/C++ data type name of this data type.
500       *       *
501       * Call this method on user defined C/C++ data types like @c enum, @c struct       * Call this method on user defined C/C++ data types like @c enum,
502       * and @c class types to retrieve the user defined type name portion of       * @c struct, @c class or @c Array<> types to retrieve the user defined type
503       * those data types. Note that this method is only intended for such user       * name portion of those data types. Note that this method is only intended
504       * defined data types. For all fundamental, primitive data types (like i.e.       * for such user defined data types. For all fundamental, primitive data
505       * @c int) this method returns an empty string instead.       * types (like i.e. @c int) this method returns an empty string instead.
506       *       *
507       * This method takes an optional boolean argument @b demangle, which allows       * This method takes an optional boolean argument @b demangle, which allows
508       * you define whether you are interested in the raw C++ type name or rather       * you define whether you are interested in the raw C++ type name or rather
# Line 443  namespace Serialization { Line 530  namespace Serialization {
530       * @b Windows: please note that the current implementation of this method       * @b Windows: please note that the current implementation of this method
531       * on Windows is @b not thread safe!       * on Windows is @b not thread safe!
532       *       *
533       * @see isPointer(), baseTypeName()       * @see baseTypeName(), customTypeName2(), isPointer()
534       */       */
535      String DataType::customTypeName(bool demangle) const {      String DataType::customTypeName(bool demangle) const {
536          if (!demangle) return m_customTypeName;          if (!demangle) return m_customTypeName;
537  #ifdef _MSC_VER          return _demangleTypeName(m_customTypeName.c_str());
538          const size_t MAXLENGTH = 1024;      }
         char result[MAXLENGTH];  
539    
540          //FIXME: calling UnDecorateSymbolName() is not thread safe!      /** @brief The 2nd user defined C/C++ data type name of this data type.
541          //Skip the first char       *
542          size_t size = UnDecorateSymbolName(m_customTypeName.c_str() +1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);       * This is currently only used for @c Map<> data types in which case this
543          if (size)       * method returns the map's value type (i.e. map's 2nd template parameter).
544          {       *
545              return result;       * @see baseTypeName(), customTypeName()
546          }       */
547          return m_customTypeName;      String DataType::customTypeName2(bool demangle) const {
548  #else          if (!demangle) return m_customTypeName2;
549          int status;          return _demangleTypeName(m_customTypeName2.c_str());
         char* result =  
             abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);  
         String sResult = result;  
         free(result);  
         return (status == 0) ? sResult : m_customTypeName;  
 #endif  
550      }      }
551    
552      // *************** Member ***************      // *************** Member ***************
# Line 489  namespace Serialization { Line 569  namespace Serialization {
569          m_offset = 0;          m_offset = 0;
570      }      }
571    
572      Member::Member(String name, UID uid, size_t offset, DataType type) {      Member::Member(String name, UID uid, ssize_t offset, DataType type) {
573          m_name = name;          m_name = name;
574          m_uid  = uid;          m_uid  = uid;
575          m_offset = offset;          m_offset = offset;
# Line 571  namespace Serialization { Line 651  namespace Serialization {
651       * @c b and @c c instead. For most 64 bit architectures this example would       * @c b and @c c instead. For most 64 bit architectures this example would
652       * now still return @c 0 for member @c a, but @c 8 for member @c b and @c 16       * now still return @c 0 for member @c a, but @c 8 for member @c b and @c 16
653       * for member @c c.       * for member @c c.
654         *
655         * @note Offset is intended for native members only, that is member
656         * variables which are memory located directly within the associated parent
657         * data structure. For members allocated on the heap @c offset() always
658         * returns @c -1 instead since there is no constant, static offset
659         * relationship between data on the heap and the parent structure owning
660         * their life-time control.
661       */       */
662      size_t Member::offset() const {      ssize_t Member::offset() const {
663          return m_offset;          return m_offset;
664      }      }
665    
# Line 733  namespace Serialization { Line 820  namespace Serialization {
820          return (index < m_uid.size()) ? m_uid[index] : NO_UID;          return (index < m_uid.size()) ? m_uid[index] : NO_UID;
821      }      }
822    
823        static void _setNativeValueFromString(void* ptr, const DataType& type, const char* s) {
824            if (type.isPrimitive() && !type.isPointer()) {
825                if (type.isInteger() || type.isEnum()) {
826                    if (type.isSigned()) {
827                        if (type.size() == 1)
828                            *(int8_t*)ptr = (int8_t) atoll(s);
829                        else if (type.size() == 2)
830                            *(int16_t*)ptr = (int16_t) atoll(s);
831                        else if (type.size() == 4)
832                            *(int32_t*)ptr = (int32_t) atoll(s);
833                        else if (type.size() == 8)
834                            *(int64_t*)ptr = (int64_t) atoll(s);
835                        else
836                            assert(false /* unknown signed int type size */);
837                    } else {
838                        if (type.size() == 1)
839                            *(uint8_t*)ptr = (uint8_t) atoll(s);
840                        else if (type.size() == 2)
841                            *(uint16_t*)ptr = (uint16_t) atoll(s);
842                        else if (type.size() == 4)
843                            *(uint32_t*)ptr = (uint32_t) atoll(s);
844                        else if (type.size() == 8)
845                            *(uint64_t*)ptr = (uint64_t) atoll(s);
846                        else
847                            assert(false /* unknown unsigned int type size */);
848                    }
849                } else if (type.isReal()) {
850                    if (type.size() == sizeof(float))
851                        *(float*)ptr = (float) atof(s);
852                    else if (type.size() == sizeof(double))
853                        *(double*)ptr = (double) atof(s);
854                    else
855                        assert(false /* unknown floating point type */);
856                } else if (type.isBool()) {
857                    String lower = toLowerCase(s);
858                    const bool b = lower != "0" && lower != "false" && lower != "no";
859                    *(bool*)ptr = b;
860                } else if (type.isString()) {
861                    *(String*)ptr = s;
862                } else {
863                    assert(false /* no built-in cast from string support for this data type */);
864                }
865            }
866        }
867    
868        /** @brief Cast from string to object's data type and assign value natively.
869         *
870         * The passed String @a s is decoded from its string representation to this
871         * object's corresponding native data type, then that casted value is
872         * assigned to the native memory location this Object is referring to.
873         *
874         * Note: This method may only be called for data types which enjoy built-in
875         * support for casting from string to their native data type, which are
876         * basically primitive data types (e.g. @c int, @c bool, @c double, etc.) or
877         * @c String objects. For all other data types calling this method will
878         * cause an assertion fault at runtime.
879         *
880         * @param s - textual string representation of the value to be assigned to
881         *            this object
882         */
883        void Object::setNativeValueFromString(const String& s) {
884            const ID& id = uid().id;
885            void* ptr = (void*)id;
886            _setNativeValueFromString(ptr, m_type, s.c_str());
887        }
888    
889      /** @brief Unique identifier chain of this Object.      /** @brief Unique identifier chain of this Object.
890       *       *
891       * Returns the entire unique identifier chain of this Object.       * Returns the entire unique identifier chain of this Object.
# Line 1195  namespace Serialization { Line 1348  namespace Serialization {
1348          String s;          String s;
1349          s += _encodeBlob(type.baseTypeName());          s += _encodeBlob(type.baseTypeName());
1350          s += _encodeBlob(type.customTypeName());          s += _encodeBlob(type.customTypeName());
1351            if (!type.customTypeName2().empty())
1352                s += _encodeBlob(type.customTypeName2());
1353          s += _encodeBlob(ToString(type.size()));          s += _encodeBlob(ToString(type.size()));
1354          s += _encodeBlob(ToString(type.isPointer()));          s += _encodeBlob(ToString(type.isPointer()));
1355          return _encodeBlob(s);          return _encodeBlob(s);
# Line 1269  namespace Serialization { Line 1424  namespace Serialization {
1424              } else {              } else {
1425                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
1426              }              }
   
1427          }          }
1428          return s;          return s;
1429      }      }
# Line 1376  namespace Serialization { Line 1530  namespace Serialization {
1530      /*      /*
1531       * Srx format history:       * Srx format history:
1532       * - 1.0: Initial version.       * - 1.0: Initial version.
1533       * - 1.1: Adds "String" data type.       * - 1.1: Adds "String", "Array", "Set" and "Map" data types and an optional
1534         *        2nd custom type name (e.g. "Map" types which always contain two
1535         *        user defined types).
1536       */       */
1537      #define MAGIC_START "Srx1v"      #define MAGIC_START "Srx1v"
1538      #define ENCODING_FORMAT_MINOR_VERSION 1      #define ENCODING_FORMAT_MINOR_VERSION 1
# Line 1524  namespace Serialization { Line 1680  namespace Serialization {
1680          DataType type;          DataType type;
1681          type.m_baseTypeName   = _popStringBlob(p, end);          type.m_baseTypeName   = _popStringBlob(p, end);
1682          type.m_customTypeName = _popStringBlob(p, end);          type.m_customTypeName = _popStringBlob(p, end);
1683            if (type.isMap())
1684                type.m_customTypeName2 = _popStringBlob(p, end);
1685          type.m_size           = _popIntBlob<int>(p, end);          type.m_size           = _popIntBlob<int>(p, end);
1686          type.m_isPointer      = _popIntBlob<bool>(p, end);          type.m_isPointer      = _popIntBlob<bool>(p, end);
1687          return type;          return type;
# Line 1567  namespace Serialization { Line 1725  namespace Serialization {
1725          if (p >= end) return m;          if (p >= end) return m;
1726    
1727          m.m_uid    = _popUIDBlob(p, end);          m.m_uid    = _popUIDBlob(p, end);
1728          m.m_offset = _popIntBlob<size_t>(p, end);          m.m_offset = _popIntBlob<ssize_t>(p, end);
1729          m.m_name   = _popStringBlob(p, end);          m.m_name   = _popStringBlob(p, end);
1730          m.m_type   = _popDataTypeBlob(p, end);          m.m_type   = _popDataTypeBlob(p, end);
1731          assert(m.type());          assert(m.type());
# Line 2354  namespace Serialization { Line 2512  namespace Serialization {
2512          *pDst = (String) (const char*) &srcObj.rawData()[0];          *pDst = (String) (const char*) &srcObj.rawData()[0];
2513      }      }
2514    
2515        void Archive::Syncer::syncArray(const Object& dstObj, const Object& srcObj) {
2516            assert(dstObj.type().isArray());
2517            assert(dstObj.type() == srcObj.type());
2518            dstObj.m_sync(const_cast<Object&>(dstObj), srcObj, this);
2519        }
2520    
2521        void Archive::Syncer::syncSet(const Object& dstObj, const Object& srcObj) {
2522            assert(dstObj.type().isSet());
2523            assert(dstObj.type() == srcObj.type());
2524            dstObj.m_sync(const_cast<Object&>(dstObj), srcObj, this);
2525        }
2526    
2527        void Archive::Syncer::syncMap(const Object& dstObj, const Object& srcObj) {
2528            assert(dstObj.type().isMap());
2529            assert(dstObj.type() == srcObj.type());
2530            dstObj.m_sync(const_cast<Object&>(dstObj), srcObj, this);
2531        }
2532    
2533      void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {      void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
2534          assert(dstObj.type().isPointer());          assert(dstObj.type().isPointer());
2535          assert(dstObj.type() == srcObj.type());          assert(dstObj.type() == srcObj.type());
# Line 2387  namespace Serialization { Line 2563  namespace Serialization {
2563              return; // end of recursion              return; // end of recursion
2564          }          }
2565    
2566            if (dstObj.type().isArray()) {
2567                syncArray(dstObj, srcObj);
2568                return;
2569            }
2570    
2571            if (dstObj.type().isSet()) {
2572                syncSet(dstObj, srcObj);
2573                return;
2574            }
2575    
2576            if (dstObj.type().isMap()) {
2577                syncMap(dstObj, srcObj);
2578                return;
2579            }
2580    
2581          if (dstObj.type().isPointer()) {          if (dstObj.type().isPointer()) {
2582              syncPointer(dstObj, srcObj);              syncPointer(dstObj, srcObj);
2583              return;              return;

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

  ViewVC Help
Powered by ViewVC