/[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 3153 by schoenebeck, Sat May 6 13:43:43 2017 UTC revision 3182 by schoenebeck, Sun May 14 20:40:02 2017 UTC
# Line 27  Line 27 
27  #include <assert.h>  #include <assert.h>
28  #include <string.h> // for memcpy()  #include <string.h> // for memcpy()
29  #include <stdlib.h> // for atof()  #include <stdlib.h> // for atof()
30    #include <cxxabi.h>
31    
32  #include "helper.h"  #include "helper.h"
33    
34    #define LIBGIG_EPOCH_TIME ((time_t)0)
35    
36  namespace Serialization {  namespace Serialization {
37    
38      // *************** DataType ***************      // *************** DataType ***************
39      // *      // *
40    
41      static UID _createNullUID() {      static UID _createNullUID() {
42          return (UID) { NULL, 0 };          const UID uid = { NULL, 0 };
43            return uid;
44      }      }
45    
46      const UID NO_UID = _createNullUID();      const UID NO_UID = _createNullUID();
# Line 124  namespace Serialization { Line 128  namespace Serialization {
128      }      }
129    
130      String DataType::asLongDescr() const {      String DataType::asLongDescr() const {
         //TODO: Demangling of C++ raw type names  
131          String s = m_baseTypeName;          String s = m_baseTypeName;
132          if (!m_customTypeName.empty())          if (!m_customTypeName.empty())
133              s += " " + m_customTypeName;              s += " " + customTypeName(true);
134          if (isPointer())          if (isPointer())
135              s += " pointer";              s += " pointer";
136          return s;          return s;
137      }      }
138    
139        String DataType::customTypeName(bool demangle) const {
140            if (!demangle) return m_customTypeName;
141            int status;
142            const char* result =
143                abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
144            return (status == 0) ? result : m_customTypeName;
145        }
146    
147      // *************** Member ***************      // *************** Member ***************
148      // *      // *
149    
# Line 229  namespace Serialization { Line 240  namespace Serialization {
240              return other.minVersion() <= this->version();              return other.minVersion() <= this->version();
241      }      }
242    
243        void Object::setVersion(Version v) {
244            m_version = v;
245        }
246    
247        void Object::setMinVersion(Version v) {
248            m_minVersion = v;
249        }
250    
251      Member Object::memberNamed(String name) const {      Member Object::memberNamed(String name) const {
252          for (int i = 0; i < m_members.size(); ++i)          for (int i = 0; i < m_members.size(); ++i)
253              if (m_members[i].name() == name)              if (m_members[i].name() == name)
# Line 277  namespace Serialization { Line 296  namespace Serialization {
296          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
297          m_root = NO_UID;          m_root = NO_UID;
298          m_isModified = false;          m_isModified = false;
299            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
300      }      }
301    
302      Archive::Archive(const RawData& data) {      Archive::Archive(const RawData& data) {
303          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
304          m_root = NO_UID;          m_root = NO_UID;
305          m_isModified = false;          m_isModified = false;
306            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
307          decode(m_rawData);          decode(m_rawData);
308      }      }
309    
# Line 290  namespace Serialization { Line 311  namespace Serialization {
311          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
312          m_root = NO_UID;          m_root = NO_UID;
313          m_isModified = false;          m_isModified = false;
314            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
315          decode(data, size);          decode(data, size);
316      }      }
317    
# Line 311  namespace Serialization { Line 333  namespace Serialization {
333          return _encodeBlob(s);          return _encodeBlob(s);
334      }      }
335    
336        static String _encode(const time_t& time) {
337            return _encodeBlob(ToString(time));
338        }
339    
340      static String _encode(const DataType& type) {      static String _encode(const DataType& type) {
341          String s;          String s;
342          s += _encodeBlob(type.baseTypeName());          s += _encodeBlob(type.baseTypeName());
# Line 392  namespace Serialization { Line 418  namespace Serialization {
418          return s;          return s;
419      }      }
420    
421        template<typename T>
422        static T _primitiveObjectValueToNumber(const Object& obj) {
423            T value = 0;
424            const DataType& type = obj.type();
425            const ID& id = obj.uid().id;
426            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
427            if (!obj.m_data.empty())
428                assert(type.size() == obj.m_data.size());
429            if (type.isPrimitive() && !type.isPointer()) {
430                if (type.isInteger() || type.isEnum()) {
431                    if (type.isSigned()) {
432                        if (type.size() == 1)
433                            value = (T)*(int8_t*)ptr;
434                        else if (type.size() == 2)
435                            value = (T)*(int16_t*)ptr;
436                        else if (type.size() == 4)
437                            value = (T)*(int32_t*)ptr;
438                        else if (type.size() == 8)
439                            value = (T)*(int64_t*)ptr;
440                        else
441                            assert(false /* unknown signed int type size */);
442                    } else {
443                        if (type.size() == 1)
444                            value = (T)*(uint8_t*)ptr;
445                        else if (type.size() == 2)
446                            value = (T)*(uint16_t*)ptr;
447                        else if (type.size() == 4)
448                            value = (T)*(uint32_t*)ptr;
449                        else if (type.size() == 8)
450                            value = (T)*(uint64_t*)ptr;
451                        else
452                            assert(false /* unknown unsigned int type size */);
453                    }
454                } else if (type.isReal()) {
455                    if (type.size() == sizeof(float))
456                        value = (T)*(float*)ptr;
457                    else if (type.size() == sizeof(double))
458                        value = (T)*(double*)ptr;
459                    else
460                        assert(false /* unknown floating point type */);
461                } else if (type.isBool()) {
462                    value = (T)*(bool*)ptr;
463                } else {
464                    assert(false /* unknown primitive type */);
465                }
466            }
467            return value;
468        }
469    
470      static String _encodePrimitiveValue(const Object& obj) {      static String _encodePrimitiveValue(const Object& obj) {
471          return _encodeBlob( _primitiveObjectValueToString(obj) );          return _encodeBlob( _primitiveObjectValueToString(obj) );
472      }      }
# Line 426  namespace Serialization { Line 501  namespace Serialization {
501          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
502          s += _encode(m_root);          s += _encode(m_root);
503          s += _encode(m_allObjects);          s += _encode(m_allObjects);
504            s += _encodeBlob(m_name);
505            s += _encodeBlob(m_comment);
506            s += _encode(m_timeCreated);
507            s += _encode(m_timeModified);
508          return _encodeBlob(s);          return _encodeBlob(s);
509      }      }
510    
511      void Archive::encode() {      void Archive::encode() {
512          m_rawData.clear();          m_rawData.clear();
513          String s = MAGIC_START;          String s = MAGIC_START;
514            m_timeModified = time(NULL);
515            if (m_timeCreated == LIBGIG_EPOCH_TIME)
516                m_timeCreated = m_timeModified;
517          s += _encodeRootBlob();          s += _encodeRootBlob();
518          m_rawData.resize(s.length() + 1);          m_rawData.resize(s.length() + 1);
519          memcpy(&m_rawData[0], &s[0], s.length() + 1);          memcpy(&m_rawData[0], &s[0], s.length() + 1);
# Line 444  namespace Serialization { Line 526  namespace Serialization {
526      };      };
527    
528      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
529          if (!bThrow && p >= end)          if (!bThrow && p >= end) {
530              return (_Blob) { p, end };              const _Blob blob =  { p, end };
531                return blob;
532            }
533          size_t sz = 0;          size_t sz = 0;
534          for (; true; ++p) {          for (; true; ++p) {
535              if (p >= end)              if (p >= end)
# Line 460  namespace Serialization { Line 544  namespace Serialization {
544          ++p;          ++p;
545          if (p + sz > end)          if (p + sz > end)
546              throw Exception("Decode Error: Premature end of blob");              throw Exception("Decode Error: Premature end of blob");
547          return (_Blob) { p, p + sz };          const _Blob blob = { p, p + sz };
548            return blob;
549      }      }
550    
551      template<typename T_int>      template<typename T_int>
# Line 535  namespace Serialization { Line 620  namespace Serialization {
620          return s;          return s;
621      }      }
622    
623        static time_t _popTimeBlob(const char*& p, const char* end) {
624            const uint64_t i = _popIntBlob<uint64_t>(p, end);
625            return (time_t) i;
626        }
627    
628      DataType _popDataTypeBlob(const char*& p, const char* end) {      DataType _popDataTypeBlob(const char*& p, const char* end) {
629          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
630          p   = blob.p;          p   = blob.p;
# Line 559  namespace Serialization { Line 649  namespace Serialization {
649          const ID id = (ID) _popIntBlob<size_t>(p, end);          const ID id = (ID) _popIntBlob<size_t>(p, end);
650          const size_t size = _popIntBlob<size_t>(p, end);          const size_t size = _popIntBlob<size_t>(p, end);
651    
652          return (UID) { id, size };          const UID uid = { id, size };
653            return uid;
654      }      }
655    
656      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
# Line 711  namespace Serialization { Line 802  namespace Serialization {
802          _popObjectsBlob(p, end);          _popObjectsBlob(p, end);
803          if (!m_allObjects[m_root])          if (!m_allObjects[m_root])
804              throw Exception("Decode Error: Missing declared root object");              throw Exception("Decode Error: Missing declared root object");
805    
806            m_name = _popStringBlob(p, end);
807            m_comment = _popStringBlob(p, end);
808            m_timeCreated = _popTimeBlob(p, end);
809            m_timeModified = _popTimeBlob(p, end);
810      }      }
811    
812      void Archive::decode(const RawData& data) {      void Archive::decode(const RawData& data) {
813          m_rawData = data;          m_rawData = data;
814          m_allObjects.clear();          m_allObjects.clear();
815          m_isModified = false;          m_isModified = false;
816            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
817          const char* p   = (const char*) &data[0];          const char* p   = (const char*) &data[0];
818          const char* end = p + data.size();          const char* end = p + data.size();
819          if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))          if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
# Line 751  namespace Serialization { Line 848  namespace Serialization {
848          m_root = NO_UID;          m_root = NO_UID;
849          m_rawData.clear();          m_rawData.clear();
850          m_isModified = false;          m_isModified = false;
851            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
852        }
853    
854        String Archive::name() const {
855            return m_name;
856        }
857    
858        void Archive::setName(String name) {
859            if (m_name == name) return;
860            m_name = name;
861            m_isModified = true;
862        }
863    
864        String Archive::comment() const {
865            return m_comment;
866        }
867    
868        void Archive::setComment(String comment) {
869            if (m_comment == comment) return;
870            m_comment = comment;
871            m_isModified = true;
872        }
873    
874        static tm _convertTimeStamp(const time_t& time, time_base_t base) {
875            tm* pTm;
876            switch (base) {
877                case LOCAL_TIME:
878                    pTm = localtime(&time);
879                    break;
880                case UTC_TIME:
881                    pTm = gmtime(&time);
882                    break;
883                default:
884                    throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
885            }
886            if (!pTm)
887                throw Exception("Failed assembling time stamp structure");
888            return *pTm;
889        }
890    
891        time_t Archive::timeStampCreated() const {
892            return m_timeCreated;
893        }
894    
895        time_t Archive::timeStampModified() const {
896            return m_timeModified;
897        }
898    
899        tm Archive::dateTimeCreated(time_base_t base) const {
900            return _convertTimeStamp(m_timeCreated, base);
901        }
902    
903        tm Archive::dateTimeModified(time_base_t base) const {
904            return _convertTimeStamp(m_timeModified, base);
905      }      }
906    
907      void Archive::removeMember(Object& parent, const Member& member) {      void Archive::removeMember(Object& parent, const Member& member) {
# Line 769  namespace Serialization { Line 920  namespace Serialization {
920          return m_allObjects[uid];          return m_allObjects[uid];
921      }      }
922    
923        void Archive::setVersion(Object& object, Version v) {
924            if (!object) return;
925            object.setVersion(v);
926            m_isModified = true;
927        }
928    
929        void Archive::setMinVersion(Object& object, Version v) {
930            if (!object) return;
931            object.setMinVersion(v);
932            m_isModified = true;
933        }
934    
935      void Archive::setEnumValue(Object& object, uint64_t value) {      void Archive::setEnumValue(Object& object, uint64_t value) {
936          if (!object) return;          if (!object) return;
937          if (!object.type().isEnum())          if (!object.type().isEnum())
# Line 908  namespace Serialization { Line 1071  namespace Serialization {
1071          return _primitiveObjectValueToString(*pObject);          return _primitiveObjectValueToString(*pObject);
1072      }      }
1073    
1074        int64_t Archive::valueAsInt(const Object& object) {
1075            if (!object)
1076                throw Exception("Invalid object");
1077            if (!object.type().isInteger() && !object.type().isEnum())
1078                throw Exception("Object is neither an integer nor an enum");
1079            const Object* pObject = &object;
1080            if (object.type().isPointer()) {
1081                const Object& obj = objectByUID(object.uid(1));
1082                if (!obj) return 0;
1083                pObject = &obj;
1084            }
1085            return _primitiveObjectValueToNumber<int64_t>(*pObject);
1086        }
1087    
1088        double Archive::valueAsReal(const Object& object) {
1089            if (!object)
1090                throw Exception("Invalid object");
1091            if (!object.type().isReal())
1092                throw Exception("Object is not an real type");
1093            const Object* pObject = &object;
1094            if (object.type().isPointer()) {
1095                const Object& obj = objectByUID(object.uid(1));
1096                if (!obj) return 0;
1097                pObject = &obj;
1098            }
1099            return _primitiveObjectValueToNumber<double>(*pObject);
1100        }
1101    
1102        bool Archive::valueAsBool(const Object& object) {
1103            if (!object)
1104                throw Exception("Invalid object");
1105            if (!object.type().isBool())
1106                throw Exception("Object is not a bool");
1107            const Object* pObject = &object;
1108            if (object.type().isPointer()) {
1109                const Object& obj = objectByUID(object.uid(1));
1110                if (!obj) return 0;
1111                pObject = &obj;
1112            }
1113            return _primitiveObjectValueToNumber<bool>(*pObject);
1114        }
1115    
1116      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
1117      // *      // *
1118    

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

  ViewVC Help
Powered by ViewVC