/[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 3185 by schoenebeck, Wed May 17 15:42:58 2017 UTC revision 3775 by schoenebeck, Tue May 19 15:23:11 2020 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2017 Christian Schoenebeck                              *   *   Copyright (C) 2017-2020 Christian Schoenebeck                         *
4   *                      <cuse@users.sourceforge.net>                       *   *                           <cuse@users.sourceforge.net>                  *
5   *                                                                         *   *                                                                         *
6   *   This library is part of libgig.                                       *   *   This library is part of libgig.                                       *
7   *                                                                         *   *                                                                         *
# Line 21  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24    // enable implementation specific declarations in Serialization.h required to
25    // build this C++ unit, which should be ignored in the public API though
26    #define LIBGIG_SERIALIZATION_INTERNAL 1
27    
28  #include "Serialization.h"  #include "Serialization.h"
29    
30  #include <iostream>  #include <iostream>
 #include <assert.h>  
31  #include <string.h> // for memcpy()  #include <string.h> // for memcpy()
32  #include <stdlib.h> // for atof()  #include <stdlib.h> // for atof()
33  #include <cxxabi.h>  #ifdef _MSC_VER
34    # include <windows.h>
35    # include <dbghelp.h>
36    #else
37    # include <cxxabi.h>
38    #endif
39  #include "helper.h"  #include "helper.h"
40    
41  #define LIBGIG_EPOCH_TIME ((time_t)0)  #define LIBGIG_EPOCH_TIME ((time_t)0)
# Line 63  namespace Serialization { Line 70  namespace Serialization {
70      // *************** DataType ***************      // *************** DataType ***************
71      // *      // *
72    
73      /** @brief Default constructor.      /** @brief Default constructor (as "invalid" DataType).
74       *       *
75       * Initializes a DataType object as being an "invalid" DataType object.       * Initializes a DataType object as being an "invalid" DataType object.
76       * Thus calling isValid(), after creating a DataType object with this       * Thus calling isValid(), after creating a DataType object with this
# Line 77  namespace Serialization { Line 84  namespace Serialization {
84          m_isPointer = false;          m_isPointer = false;
85      }      }
86    
87        /** @brief Constructs a valid DataType object.
88         *
89         * Initializes this object as "valid" DataType object, with specific and
90         * useful data type information.
91         *
92         * This is a protected constructor which should not be called directly by
93         * applications, as its argument list is somewhat implementation specific
94         * and might change at any time. Applications should call the static
95         * function DataType::dataTypeOf() instead.
96         *
97         * @param isPointer - whether pointer type (i.e. a simple memory address)
98         * @param size - native size of data type in bytes (i.e. according to
99         *               @c sizeof() C/C++ keyword)
100         * @param baseType - this framework's internal name for specifying the base
101         *                   type in a coarse way, which must be either one of:
102         *                   "int8", "uint8", "int16", "uint16", "int32", "uint32",
103         *                   "int64", "uint64", "bool", "real32", "real64",
104         *                   "String", "Array", "enum", "union" or "class"
105         * @param customType - this is only used for base types "enum", "union",
106         *                     "class" or "Array", in which case this identifies the
107         *                     user defined type name (e.g. "Foo" for
108         *                     @c class @c Foo or e.g. "Bar" for @c Array<Bar>
109         *                     respectively), for all other types this is empty
110         */
111      DataType::DataType(bool isPointer, int size, String baseType, String customType) {      DataType::DataType(bool isPointer, int size, String baseType, String customType) {
112          m_size = size;          m_size = size;
113          m_isPointer = isPointer;          m_isPointer = isPointer;
# Line 113  namespace Serialization { Line 144  namespace Serialization {
144       * (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
145       * type.       * type.
146       *       *
147         * @note: Data types which enjoy out of the box serialization support by
148         * this framework, like @c String and @c Array<> are @b NOT handled as class
149         * data types by this framwork. So @c isClass() returns @c false for e.g.
150         * @c String and any @c Array<> based data type.
151         *
152       * Note that in the following example:       * Note that in the following example:
153       * @code       * @code
154       * struct Foo {       * struct Foo {
# Line 137  namespace Serialization { Line 173  namespace Serialization {
173       * (this DataType instance is reflecting) is a primitive, fundamental C/C++       * (this DataType instance is reflecting) is a primitive, fundamental C/C++
174       * data type. Those are fundamental data types which are already predefined       * data type. Those are fundamental data types which are already predefined
175       * by the C/C++ language, for example: @c char, @c int, @c float, @c double,       * by the C/C++ language, for example: @c char, @c int, @c float, @c double,
176       * @c bool, but also @b any pointer types like @c int*, @c double**, but       * @c bool, but also @c String objects and @b any pointer types like
177       * including pointers to user defined types like:       * @c int*, @c double**, but including pointers to user defined types like:
178       * @code       * @code
179       * struct Foo {       * struct Foo {
180       *     int  a;       *     int  a;
# Line 152  namespace Serialization { Line 188  namespace Serialization {
188       * @see isPointer()       * @see isPointer()
189       */       */
190      bool DataType::isPrimitive() const {      bool DataType::isPrimitive() const {
191          return !isClass();          return !isClass() && !isArray();
192        }
193    
194        /** @brief Whether this is a C++ @c String data type.
195         *
196         * Returns @c true if the respective native C/C++ object, member or variable
197         * (this DataType instance is reflecting) is a C++ @c String object (a.k.a.
198         * @c std::string from the C++ STL).
199         *
200         * Note that this framework handles @c String objects as if they were a
201         * fundamental, primitive C/C++ data type, so @c isPrimitive() returns
202         * @c true for strings.
203         */
204        bool DataType::isString() const {
205            return m_baseTypeName == "String";
206      }      }
207    
208      /** @brief Whether this is an integer C/C++ data type.      /** @brief Whether this is an integer C/C++ data type.
# Line 220  namespace Serialization { Line 270  namespace Serialization {
270          return m_baseTypeName == "enum";          return m_baseTypeName == "enum";
271      }      }
272    
273        /** @brief Whether this is a C++ @c Array<> object type.
274         *
275         * Returns @c true if the respective native C/C++ object, member or variable
276         * (this DataType instance is reflecting) is a C++ @c Array<> container
277         * object type.
278         *
279         * @note: This framework handles @c Array<> types neither as primitive
280         * types, nor as class types. So @c isPrimitive() and @c isClass() both
281         * return @c false for arrays.
282         *
283         * @see isPointer()
284         */
285        bool DataType::isArray() const {
286            return m_baseTypeName == "Array";
287        }
288    
289      /** @brief Whether this is a signed integer C/C++ data type.      /** @brief Whether this is a signed integer C/C++ data type.
290       *       *
291       * 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 250  namespace Serialization { Line 316  namespace Serialization {
316       * characteristic is compared as well. So a @c double type and @c double*       * characteristic is compared as well. So a @c double type and @c double*
317       * type are also considered to be not equal data types and hence this method       * type are also considered to be not equal data types and hence this method
318       * would return @c false.       * would return @c false.
319         *
320         * As an exception here, classes and structs with the same class/struct name
321         * but different sizes are also considered to be "equal". This relaxed
322         * requirement is necessary to retain backward compatiblity to older
323         * versions of the same native C++ classes/structs.
324       */       */
325      bool DataType::operator==(const DataType& other) const {      bool DataType::operator==(const DataType& other) const {
326          return m_baseTypeName   == other.m_baseTypeName &&          return m_baseTypeName   == other.m_baseTypeName &&
327                 m_customTypeName == other.m_customTypeName &&                 m_customTypeName == other.m_customTypeName &&
328                 m_size           == other.m_size &&                 (m_size == other.m_size || (isClass() && other.isClass())) &&
329                 m_isPointer      == other.m_isPointer;                 m_isPointer      == other.m_isPointer;
330      }      }
331    
# Line 281  namespace Serialization { Line 352  namespace Serialization {
352      bool DataType::operator<(const DataType& other) const {      bool DataType::operator<(const DataType& other) const {
353          return m_baseTypeName  < other.m_baseTypeName ||          return m_baseTypeName  < other.m_baseTypeName ||
354                (m_baseTypeName == other.m_baseTypeName &&                (m_baseTypeName == other.m_baseTypeName &&
355                 m_customTypeName  < other.m_customTypeName ||                (m_customTypeName  < other.m_customTypeName ||
356                (m_customTypeName == other.m_customTypeName &&                (m_customTypeName == other.m_customTypeName &&
357                 m_size  < other.m_size ||                (m_size  < other.m_size ||
358                (m_size == other.m_size &&                (m_size == other.m_size &&
359                 m_isPointer < other.m_isPointer)));                 m_isPointer < other.m_isPointer)))));
360      }      }
361    
362      /** @brief Greater than comparison.      /** @brief Greater than comparison.
# Line 361  namespace Serialization { Line 432  namespace Serialization {
432    
433      /** @brief The user defined C/C++ data type name of this data type.      /** @brief The user defined C/C++ data type name of this data type.
434       *       *
435       * 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,
436       * 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
437       * 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
438       * defined data types. For all fundamental, primitive data types (like i.e.       * for such user defined data types. For all fundamental, primitive data
439       * @c int) this method returns an empty string instead.       * types (like i.e. @c int) this method returns an empty string instead.
440       *       *
441       * This method takes an optional boolean argument @b demangle, which allows       * This method takes an optional boolean argument @b demangle, which allows
442       * 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 390  namespace Serialization { Line 461  namespace Serialization {
461       * In the latter example @c customTypeName(true) would return for both       * In the latter example @c customTypeName(true) would return for both
462       * @c foo and @c pFoo the string @c "Foo" as return value of this method.       * @c foo and @c pFoo the string @c "Foo" as return value of this method.
463       *       *
464         * @b Windows: please note that the current implementation of this method
465         * on Windows is @b not thread safe!
466         *
467       * @see isPointer(), baseTypeName()       * @see isPointer(), baseTypeName()
468       */       */
469      String DataType::customTypeName(bool demangle) const {      String DataType::customTypeName(bool demangle) const {
470          if (!demangle) return m_customTypeName;          if (!demangle) return m_customTypeName;
471    #ifdef _MSC_VER
472            const size_t MAXLENGTH = 1024;
473            char result[MAXLENGTH];
474    
475            //FIXME: calling UnDecorateSymbolName() is not thread safe!
476            //Skip the first char
477            size_t size = UnDecorateSymbolName(m_customTypeName.c_str() +1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
478            if (size)
479            {
480                return result;
481            }
482            return m_customTypeName;
483    #else
484          int status;          int status;
485          const char* result =          char* result =
486              abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);              abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
487          return (status == 0) ? result : m_customTypeName;          String sResult = result;
488            free(result);
489            return (status == 0) ? sResult : m_customTypeName;
490    #endif
491      }      }
492    
493      // *************** Member ***************      // *************** Member ***************
# Line 420  namespace Serialization { Line 510  namespace Serialization {
510          m_offset = 0;          m_offset = 0;
511      }      }
512    
513      Member::Member(String name, UID uid, size_t offset, DataType type) {      Member::Member(String name, UID uid, ssize_t offset, DataType type) {
514          m_name = name;          m_name = name;
515          m_uid  = uid;          m_uid  = uid;
516          m_offset = offset;          m_offset = offset;
# Line 502  namespace Serialization { Line 592  namespace Serialization {
592       * @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
593       * 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
594       * for member @c c.       * for member @c c.
595         *
596         * @note Offset is intended for native members only, that is member
597         * variables which are memory located directly within the associated parent
598         * data structure. For members allocated on the heap @c offset() always
599         * returns @c -1 instead since there is no constant, static offset
600         * relationship between data on the heap and the parent structure owning
601         * their life-time control.
602       */       */
603      size_t Member::offset() const {      ssize_t Member::offset() const {
604          return m_offset;          return m_offset;
605      }      }
606    
# Line 568  namespace Serialization { Line 665  namespace Serialization {
665      bool Member::operator<(const Member& other) const {      bool Member::operator<(const Member& other) const {
666          return m_uid  < other.m_uid ||          return m_uid  < other.m_uid ||
667                (m_uid == other.m_uid &&                (m_uid == other.m_uid &&
668                 m_offset  < other.m_offset ||                (m_offset  < other.m_offset ||
669                (m_offset == other.m_offset &&                (m_offset == other.m_offset &&
670                 m_name  < other.m_name ||                (m_name  < other.m_name ||
671                (m_name == other.m_name &&                (m_name == other.m_name &&
672                 m_type < other.m_type)));                 m_type < other.m_type)))));
673      }      }
674    
675      /** @brief Greater than comparison.      /** @brief Greater than comparison.
# Line 714  namespace Serialization { Line 811  namespace Serialization {
811       * In case this Object is reflecting a native C/C++ @c struct or @c class       * In case this Object is reflecting a native C/C++ @c struct or @c class
812       * type, then this method returns the version of that native C/C++ @c struct       * type, then this method returns the version of that native C/C++ @c struct
813       * or @c class layout or implementation. For primitive, fundamental C/C++       * or @c class layout or implementation. For primitive, fundamental C/C++
814       * data types the return value of this method has no meaning.       * data types (including @c String objects) the return value of this method
815         * has no meaning.
816       *       *
817       * @see Archive::setVersion() for more details about this overall topic.       * @see Archive::setVersion() for more details about this overall topic.
818       */       */
# Line 727  namespace Serialization { Line 825  namespace Serialization {
825       * In case this Object is reflecting a native C/C++ @c struct or @c class       * In case this Object is reflecting a native C/C++ @c struct or @c class
826       * type, then this method returns the "minimum" version of that native C/C++       * type, then this method returns the "minimum" version of that native C/C++
827       * @c struct or @c class layout or implementation which it may be compatible       * @c struct or @c class layout or implementation which it may be compatible
828       * with. For primitive, fundamental C/C++ data types the return value of       * with. For primitive, fundamental C/C++ data types (including @c String
829       * this method has no meaning.       * objects) the return value of this method has no meaning.
830       *       *
831       * @see Archive::setVersion() and Archive::setMinVersion() for more details       * @see Archive::setVersion() and Archive::setMinVersion() for more details
832       *      about this overall topic.       *      about this overall topic.
# Line 1058  namespace Serialization { Line 1156  namespace Serialization {
1156          m_root = NO_UID;          m_root = NO_UID;
1157          m_isModified = false;          m_isModified = false;
1158          m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;          m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1159          decode(m_rawData);          decode(data);
1160      }      }
1161    
1162      /** @brief Create and fill the archive with the given serialized raw C-buffer data.      /** @brief Create and fill the archive with the given serialized raw C-buffer data.
# Line 1194  namespace Serialization { Line 1292  namespace Serialization {
1292                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
1293              } else if (type.isBool()) {              } else if (type.isBool()) {
1294                  s = ToString(*(bool*)ptr);                  s = ToString(*(bool*)ptr);
1295                } else if (type.isString()) {
1296                    s = obj.m_data.empty() ? *(String*)ptr : String((const char*)ptr);
1297              } else {              } else {
1298                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
1299              }              }
   
1300          }          }
1301          return s;          return s;
1302      }      }
1303    
1304      template<typename T>      template<typename T>
1305        inline T _stringToNumber(const String& s) {
1306            assert(false /* String cast to unknown primitive number type */);
1307        }
1308    
1309        template<>
1310        inline int64_t _stringToNumber(const String& s) {
1311            return atoll(s.c_str());
1312        }
1313    
1314        template<>
1315        inline double _stringToNumber(const String& s) {
1316            return atof(s.c_str());
1317        }
1318    
1319        template<>
1320        inline bool _stringToNumber(const String& s) {
1321            return (bool) atoll(s.c_str());
1322        }
1323    
1324        template<typename T>
1325      static T _primitiveObjectValueToNumber(const Object& obj) {      static T _primitiveObjectValueToNumber(const Object& obj) {
1326          T value = 0;          T value = 0;
1327          const DataType& type = obj.type();          const DataType& type = obj.type();
# Line 1244  namespace Serialization { Line 1363  namespace Serialization {
1363                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
1364              } else if (type.isBool()) {              } else if (type.isBool()) {
1365                  value = (T)*(bool*)ptr;                  value = (T)*(bool*)ptr;
1366                } else if (type.isString()) {
1367                    value = _stringToNumber<T>(
1368                        obj.m_data.empty() ? *(String*)ptr : String((const char*)ptr)
1369                    );
1370              } else {              } else {
1371                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
1372              }              }
# Line 1277  namespace Serialization { Line 1400  namespace Serialization {
1400          return _encodeBlob(s);          return _encodeBlob(s);
1401      }      }
1402    
1403        /*
1404         * Srx format history:
1405         * - 1.0: Initial version.
1406         * - 1.1: Adds "String" and "Array" data types.
1407         */
1408      #define MAGIC_START "Srx1v"      #define MAGIC_START "Srx1v"
1409      #define ENCODING_FORMAT_MINOR_VERSION 0      #define ENCODING_FORMAT_MINOR_VERSION 1
1410    
1411      String Archive::_encodeRootBlob() {      String Archive::_encodeRootBlob() {
1412          String s;          String s;
# Line 1404  namespace Serialization { Line 1532  namespace Serialization {
1532          return s;          return s;
1533      }      }
1534    
1535        static void _popStringBlob(const char*& p, const char* end, RawData& rawData) {
1536            String s = _popStringBlob(p, end);
1537            rawData.resize(s.length() + 1);
1538            strcpy((char*)&rawData[0], &s[0]);
1539        }
1540    
1541      static time_t _popTimeBlob(const char*& p, const char* end) {      static time_t _popTimeBlob(const char*& p, const char* end) {
1542          const uint64_t i = _popIntBlob<uint64_t>(p, end);          const uint64_t i = _popIntBlob<uint64_t>(p, end);
1543          return (time_t) i;          return (time_t) i;
1544      }      }
1545    
1546      DataType _popDataTypeBlob(const char*& p, const char* end) {      static DataType _popDataTypeBlob(const char*& p, const char* end) {
1547          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
1548          p   = blob.p;          p   = blob.p;
1549          end = blob.end;          end = blob.end;
# Line 1460  namespace Serialization { Line 1594  namespace Serialization {
1594          if (p >= end) return m;          if (p >= end) return m;
1595    
1596          m.m_uid    = _popUIDBlob(p, end);          m.m_uid    = _popUIDBlob(p, end);
1597          m.m_offset = _popIntBlob<size_t>(p, end);          m.m_offset = _popIntBlob<ssize_t>(p, end);
1598          m.m_name   = _popStringBlob(p, end);          m.m_name   = _popStringBlob(p, end);
1599          m.m_type   = _popDataTypeBlob(p, end);          m.m_type   = _popDataTypeBlob(p, end);
1600          assert(m.type());          assert(m.type());
# Line 1522  namespace Serialization { Line 1656  namespace Serialization {
1656                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
1657              } else if (type.isBool()) {              } else if (type.isBool()) {
1658                  _popIntBlob<uint8_t>(p, end, obj.m_data);                  _popIntBlob<uint8_t>(p, end, obj.m_data);
1659                } else if (type.isString()) {
1660                    _popStringBlob(p, end, obj.m_data);
1661              } else {              } else {
1662                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
1663              }              }
# Line 2062  namespace Serialization { Line 2198  namespace Serialization {
2198          m_isModified = true;          m_isModified = true;
2199      }      }
2200    
2201        /** @brief Set new textual string for given String object.
2202         *
2203         * Sets the new textual string @a value to the given String @a object.
2204         *
2205         * @param object - the String object to be changed
2206         * @param value - the new textual string to be assigned to the @a object
2207         * @throws Exception if @a object is not a String type.
2208         */
2209        void Archive::setStringValue(Object& object, String value) {
2210            if (!object) return;
2211            if (!object.type().isString())
2212                throw Exception("Not a String data type");
2213            Object* pObject = &object;
2214            if (object.type().isPointer()) {
2215                Object& obj = objectByUID(object.uid(1));
2216                if (!obj) return;
2217                pObject = &obj;
2218            }
2219            pObject->m_data.resize(value.length() + 1);
2220            char* ptr = (char*) &pObject->m_data[0];
2221            strcpy(ptr, &value[0]);
2222            m_isModified = true;
2223        }
2224    
2225      /** @brief Automatically cast and assign appropriate value to object.      /** @brief Automatically cast and assign appropriate value to object.
2226       *       *
2227       * This method automatically converts the given @a value from textual string       * This method automatically converts the given @a value from textual string
# Line 2090  namespace Serialization { Line 2250  namespace Serialization {
2250                  setBoolValue(object, false);                  setBoolValue(object, false);
2251              else              else
2252                  setBoolValue(object, atof(value.c_str()));                  setBoolValue(object, atof(value.c_str()));
2253          } else if (type.isEnum())          } else if (type.isString())
2254                setStringValue(object, value);
2255            else if (type.isEnum())
2256              setEnumValue(object, atoll(value.c_str()));              setEnumValue(object, atoll(value.c_str()));
2257          else          else
2258              throw Exception("Not a primitive data type");              throw Exception("Not a primitive data type");
# Line 2187  namespace Serialization { Line 2349  namespace Serialization {
2349          return _primitiveObjectValueToNumber<bool>(*pObject);          return _primitiveObjectValueToNumber<bool>(*pObject);
2350      }      }
2351    
2352        Archive::operation_t Archive::operation() const {
2353            return m_operation;
2354        }
2355    
2356      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
2357      // *      // *
2358    
# Line 2208  namespace Serialization { Line 2374  namespace Serialization {
2374          memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());          memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
2375      }      }
2376    
2377        void Archive::Syncer::syncString(const Object& dstObj, const Object& srcObj) {
2378            assert(dstObj.type().isString());
2379            assert(dstObj.type() == srcObj.type());
2380            String* pDst = (String*)(void*)dstObj.uid().id;
2381            *pDst = (String) (const char*) &srcObj.rawData()[0];
2382        }
2383    
2384        void Archive::Syncer::syncArray(const Object& dstObj, const Object& srcObj) {
2385            assert(dstObj.type().isArray());
2386            assert(dstObj.type() == srcObj.type());
2387            dstObj.m_sync(const_cast<Object&>(dstObj), srcObj, this);
2388        }
2389    
2390      void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {      void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
2391          assert(dstObj.type().isPointer());          assert(dstObj.type().isPointer());
2392          assert(dstObj.type() == srcObj.type());          assert(dstObj.type() == srcObj.type());
# Line 2234  namespace Serialization { Line 2413  namespace Serialization {
2413          m_dst.m_allObjects.erase(dstObj.uid());          m_dst.m_allObjects.erase(dstObj.uid());
2414    
2415          if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {          if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2416              syncPrimitive(dstObj, srcObj);              if (dstObj.type().isString())
2417                    syncString(dstObj, srcObj);
2418                else
2419                    syncPrimitive(dstObj, srcObj);
2420              return; // end of recursion              return; // end of recursion
2421          }          }
2422    
2423            if (dstObj.type().isArray()) {
2424                syncArray(dstObj, srcObj);
2425                return;
2426            }
2427    
2428          if (dstObj.type().isPointer()) {          if (dstObj.type().isPointer()) {
2429              syncPointer(dstObj, srcObj);              syncPointer(dstObj, srcObj);
2430              return;              return;
# Line 2286  namespace Serialization { Line 2473  namespace Serialization {
2473      // *************** Exception ***************      // *************** Exception ***************
2474      // *      // *
2475    
2476        Exception::Exception() {
2477        }
2478    
2479        Exception::Exception(String format, ...) {
2480            va_list arg;
2481            va_start(arg, format);
2482            Message = assemble(format, arg);
2483            va_end(arg);
2484        }
2485    
2486        Exception::Exception(String format, va_list arg) {
2487            Message = assemble(format, arg);
2488        }
2489    
2490      /** @brief Print exception message to stdout.      /** @brief Print exception message to stdout.
2491       *       *
2492       * Prints the message of this Exception to the currently defined standard       * Prints the message of this Exception to the currently defined standard
# Line 2295  namespace Serialization { Line 2496  namespace Serialization {
2496          std::cout << "Serialization::Exception: " << Message << std::endl;          std::cout << "Serialization::Exception: " << Message << std::endl;
2497      }      }
2498    
2499        String Exception::assemble(String format, va_list arg) {
2500            char* buf = NULL;
2501            vasprintf(&buf, format.c_str(), arg);
2502            String s = buf;
2503            free(buf);
2504            return s;
2505        }
2506    
2507  } // namespace Serialization  } // namespace Serialization

Legend:
Removed from v.3185  
changed lines
  Added in v.3775

  ViewVC Help
Powered by ViewVC