/[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 3146 by schoenebeck, Wed May 3 19:54:08 2017 UTC revision 3169 by schoenebeck, Wed May 10 21:17:10 2017 UTC
# Line 30  Line 30 
30    
31  #include "helper.h"  #include "helper.h"
32    
33    #define LIBGIG_EPOCH_TIME ((time_t)0)
34    
35  namespace Serialization {  namespace Serialization {
36    
37      // *************** DataType ***************      // *************** DataType ***************
38      // *      // *
39    
40      static UID _createNullUID() {      static UID _createNullUID() {
41          return (UID) { NULL, 0 };          const UID uid = { NULL, 0 };
42            return uid;
43      }      }
44    
45      const UID NO_UID = _createNullUID();      const UID NO_UID = _createNullUID();
# Line 190  namespace Serialization { Line 193  namespace Serialization {
193          m_uid  = uidChain;          m_uid  = uidChain;
194          m_version = 0;          m_version = 0;
195          m_minVersion = 0;          m_minVersion = 0;
196          m_data.resize(type.size());          //m_data.resize(type.size());
197      }      }
198    
199      bool Object::isValid() const {      bool Object::isValid() const {
# Line 236  namespace Serialization { Line 239  namespace Serialization {
239          return Member();          return Member();
240      }      }
241    
242        Member Object::memberByUID(const UID& uid) const {
243            if (!uid) return Member();
244            for (int i = 0; i < m_members.size(); ++i)
245                if (m_members[i].uid() == uid)
246                    return m_members[i];
247            return Member();
248        }
249    
250      void Object::remove(const Member& member) {      void Object::remove(const Member& member) {
251          for (int i = 0; i < m_members.size(); ++i) {          for (int i = 0; i < m_members.size(); ++i) {
252              if (m_members[i] == member) {              if (m_members[i] == member) {
# Line 268  namespace Serialization { Line 279  namespace Serialization {
279      Archive::Archive() {      Archive::Archive() {
280          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
281          m_root = NO_UID;          m_root = NO_UID;
282            m_isModified = false;
283            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
284      }      }
285    
286      Archive::Archive(const RawData& data) {      Archive::Archive(const RawData& data) {
287          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
288          m_root = NO_UID;          m_root = NO_UID;
289            m_isModified = false;
290            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
291          decode(m_rawData);          decode(m_rawData);
292      }      }
293    
294      Archive::Archive(const uint8_t* data, size_t size) {      Archive::Archive(const uint8_t* data, size_t size) {
295          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
296          m_root = NO_UID;          m_root = NO_UID;
297            m_isModified = false;
298            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
299          decode(data, size);          decode(data, size);
300      }      }
301    
# Line 300  namespace Serialization { Line 317  namespace Serialization {
317          return _encodeBlob(s);          return _encodeBlob(s);
318      }      }
319    
320        static String _encode(const time_t& time) {
321            return _encodeBlob(ToString(time));
322        }
323    
324      static String _encode(const DataType& type) {      static String _encode(const DataType& type) {
325          String s;          String s;
326          s += _encodeBlob(type.baseTypeName());          s += _encodeBlob(type.baseTypeName());
# Line 332  namespace Serialization { Line 353  namespace Serialization {
353          return _encodeBlob(s);          return _encodeBlob(s);
354      }      }
355    
356      static String _encodePrimitiveValue(const Object& obj) {      static String _primitiveObjectValueToString(const Object& obj) {
357          String s;          String s;
358          const DataType& type = obj.type();          const DataType& type = obj.type();
359          const ID& id = obj.uid().id;          const ID& id = obj.uid().id;
360            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
361            if (!obj.m_data.empty())
362                assert(type.size() == obj.m_data.size());
363          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
364              if (type.isInteger() || type.isEnum()) {              if (type.isInteger() || type.isEnum()) {
365                  if (type.isSigned()) {                  if (type.isSigned()) {
366                      if (type.size() == 1)                      if (type.size() == 1)
367                          s = ToString((int16_t)*(int8_t*)id); // int16_t: prevent ToString() to render an ASCII character                          s = ToString((int16_t)*(int8_t*)ptr); // int16_t: prevent ToString() to render an ASCII character
368                      else if (type.size() == 2)                      else if (type.size() == 2)
369                          s = ToString(*(int16_t*)id);                          s = ToString(*(int16_t*)ptr);
370                      else if (type.size() == 4)                      else if (type.size() == 4)
371                          s = ToString(*(int32_t*)id);                          s = ToString(*(int32_t*)ptr);
372                      else if (type.size() == 8)                      else if (type.size() == 8)
373                          s = ToString(*(int64_t*)id);                          s = ToString(*(int64_t*)ptr);
374                      else                      else
375                          assert(false /* unknown signed int type size */);                          assert(false /* unknown signed int type size */);
376                  } else {                  } else {
377                      if (type.size() == 1)                      if (type.size() == 1)
378                          s = ToString((uint16_t)*(uint8_t*)id); // uint16_t: prevent ToString() to render an ASCII character                          s = ToString((uint16_t)*(uint8_t*)ptr); // uint16_t: prevent ToString() to render an ASCII character
379                      else if (type.size() == 2)                      else if (type.size() == 2)
380                          s = ToString(*(uint16_t*)id);                          s = ToString(*(uint16_t*)ptr);
381                      else if (type.size() == 4)                      else if (type.size() == 4)
382                          s = ToString(*(uint32_t*)id);                          s = ToString(*(uint32_t*)ptr);
383                      else if (type.size() == 8)                      else if (type.size() == 8)
384                          s = ToString(*(uint64_t*)id);                          s = ToString(*(uint64_t*)ptr);
385                      else                      else
386                          assert(false /* unknown unsigned int type size */);                          assert(false /* unknown unsigned int type size */);
387                  }                  }
388              } else if (type.isReal()) {              } else if (type.isReal()) {
389                  if (type.size() == sizeof(float))                  if (type.size() == sizeof(float))
390                      s = ToString(*(float*)id);                      s = ToString(*(float*)ptr);
391                  else if (type.size() == sizeof(double))                  else if (type.size() == sizeof(double))
392                      s = ToString(*(double*)id);                      s = ToString(*(double*)ptr);
393                  else                  else
394                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
395              } else if (type.isBool()) {              } else if (type.isBool()) {
396                  s = ToString(*(bool*)id);                  s = ToString(*(bool*)ptr);
397              } else {              } else {
398                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
399              }              }
400    
401          }          }
402          return _encodeBlob(s);          return s;
403        }
404    
405        template<typename T>
406        static T _primitiveObjectValueToNumber(const Object& obj) {
407            T value = 0;
408            const DataType& type = obj.type();
409            const ID& id = obj.uid().id;
410            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
411            if (!obj.m_data.empty())
412                assert(type.size() == obj.m_data.size());
413            if (type.isPrimitive() && !type.isPointer()) {
414                if (type.isInteger() || type.isEnum()) {
415                    if (type.isSigned()) {
416                        if (type.size() == 1)
417                            value = (T)*(int8_t*)ptr;
418                        else if (type.size() == 2)
419                            value = (T)*(int16_t*)ptr;
420                        else if (type.size() == 4)
421                            value = (T)*(int32_t*)ptr;
422                        else if (type.size() == 8)
423                            value = (T)*(int64_t*)ptr;
424                        else
425                            assert(false /* unknown signed int type size */);
426                    } else {
427                        if (type.size() == 1)
428                            value = (T)*(uint8_t*)ptr;
429                        else if (type.size() == 2)
430                            value = (T)*(uint16_t*)ptr;
431                        else if (type.size() == 4)
432                            value = (T)*(uint32_t*)ptr;
433                        else if (type.size() == 8)
434                            value = (T)*(uint64_t*)ptr;
435                        else
436                            assert(false /* unknown unsigned int type size */);
437                    }
438                } else if (type.isReal()) {
439                    if (type.size() == sizeof(float))
440                        value = (T)*(float*)ptr;
441                    else if (type.size() == sizeof(double))
442                        value = (T)*(double*)ptr;
443                    else
444                        assert(false /* unknown floating point type */);
445                } else if (type.isBool()) {
446                    value = (T)*(bool*)ptr;
447                } else {
448                    assert(false /* unknown primitive type */);
449                }
450            }
451            return value;
452        }
453    
454        static String _encodePrimitiveValue(const Object& obj) {
455            return _encodeBlob( _primitiveObjectValueToString(obj) );
456      }      }
457    
458      static String _encode(const Object& obj) {      static String _encode(const Object& obj) {
# Line 408  namespace Serialization { Line 485  namespace Serialization {
485          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
486          s += _encode(m_root);          s += _encode(m_root);
487          s += _encode(m_allObjects);          s += _encode(m_allObjects);
488            s += _encodeBlob(m_name);
489            s += _encodeBlob(m_comment);
490            s += _encode(m_timeCreated);
491            s += _encode(m_timeModified);
492          return _encodeBlob(s);          return _encodeBlob(s);
493      }      }
494    
495      void Archive::encode() {      void Archive::encode() {
496          m_rawData.clear();          m_rawData.clear();
497          String s = MAGIC_START;          String s = MAGIC_START;
498            m_timeModified = time(NULL);
499            if (m_timeCreated == LIBGIG_EPOCH_TIME)
500                m_timeCreated = m_timeModified;
501          s += _encodeRootBlob();          s += _encodeRootBlob();
502          m_rawData.resize(s.length() + 1);          m_rawData.resize(s.length() + 1);
503          memcpy(&m_rawData[0], &s[0], s.length() + 1);          memcpy(&m_rawData[0], &s[0], s.length() + 1);
504            m_isModified = false;
505      }      }
506    
507      struct _Blob {      struct _Blob {
# Line 425  namespace Serialization { Line 510  namespace Serialization {
510      };      };
511    
512      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
513          if (!bThrow && p >= end)          if (!bThrow && p >= end) {
514              return (_Blob) { p, end };              const _Blob blob =  { p, end };
515                return blob;
516            }
517          size_t sz = 0;          size_t sz = 0;
518          for (; true; ++p) {          for (; true; ++p) {
519              if (p >= end)              if (p >= end)
# Line 441  namespace Serialization { Line 528  namespace Serialization {
528          ++p;          ++p;
529          if (p + sz > end)          if (p + sz > end)
530              throw Exception("Decode Error: Premature end of blob");              throw Exception("Decode Error: Premature end of blob");
531          return (_Blob) { p, p + sz };          const _Blob blob = { p, p + sz };
532            return blob;
533      }      }
534    
535      template<typename T_int>      template<typename T_int>
# Line 516  namespace Serialization { Line 604  namespace Serialization {
604          return s;          return s;
605      }      }
606    
607        static time_t _popTimeBlob(const char*& p, const char* end) {
608            const uint64_t i = _popIntBlob<uint64_t>(p, end);
609            return (time_t) i;
610        }
611    
612      DataType _popDataTypeBlob(const char*& p, const char* end) {      DataType _popDataTypeBlob(const char*& p, const char* end) {
613          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
614          p   = blob.p;          p   = blob.p;
# Line 540  namespace Serialization { Line 633  namespace Serialization {
633          const ID id = (ID) _popIntBlob<size_t>(p, end);          const ID id = (ID) _popIntBlob<size_t>(p, end);
634          const size_t size = _popIntBlob<size_t>(p, end);          const size_t size = _popIntBlob<size_t>(p, end);
635    
636          return (UID) { id, size };          const UID uid = { id, size };
637            return uid;
638      }      }
639    
640      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
# Line 692  namespace Serialization { Line 786  namespace Serialization {
786          _popObjectsBlob(p, end);          _popObjectsBlob(p, end);
787          if (!m_allObjects[m_root])          if (!m_allObjects[m_root])
788              throw Exception("Decode Error: Missing declared root object");              throw Exception("Decode Error: Missing declared root object");
789    
790            m_name = _popStringBlob(p, end);
791            m_comment = _popStringBlob(p, end);
792            m_timeCreated = _popTimeBlob(p, end);
793            m_timeModified = _popTimeBlob(p, end);
794      }      }
795    
796      void Archive::decode(const RawData& data) {      void Archive::decode(const RawData& data) {
797          m_rawData = data;          m_rawData = data;
798          m_allObjects.clear();          m_allObjects.clear();
799            m_isModified = false;
800            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
801          const char* p   = (const char*) &data[0];          const char* p   = (const char*) &data[0];
802          const char* end = p + data.size();          const char* end = p + data.size();
803          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 712  namespace Serialization { Line 813  namespace Serialization {
813          decode(rawData);          decode(rawData);
814      }      }
815    
816        const RawData& Archive::rawData() {
817            if (m_isModified) encode();
818            return m_rawData;
819        }
820    
821      String Archive::rawDataFormat() const {      String Archive::rawDataFormat() const {
822          return MAGIC_START;          return MAGIC_START;
823      }      }
824    
825        bool Archive::isModified() const {
826            return m_isModified;
827        }
828    
829      void Archive::clear() {      void Archive::clear() {
830          m_allObjects.clear();          m_allObjects.clear();
831          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
832          m_root = NO_UID;          m_root = NO_UID;
833          m_rawData.clear();          m_rawData.clear();
834            m_isModified = false;
835            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
836        }
837    
838        String Archive::name() const {
839            return m_name;
840        }
841    
842        void Archive::setName(String name) {
843            if (m_name == name) return;
844            m_name = name;
845            m_isModified = true;
846        }
847    
848        String Archive::comment() const {
849            return m_comment;
850        }
851    
852        void Archive::setComment(String comment) {
853            if (m_comment == comment) return;
854            m_comment = comment;
855            m_isModified = true;
856        }
857    
858        static tm _convertTimeStamp(const time_t& time, time_base_t base) {
859            tm* pTm;
860            switch (base) {
861                case LOCAL_TIME:
862                    pTm = localtime(&time);
863                    break;
864                case UTC_TIME:
865                    pTm = gmtime(&time);
866                    break;
867                default:
868                    throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
869            }
870            if (!pTm)
871                throw Exception("Failed assembling time stamp structure");
872            return *pTm;
873        }
874    
875        time_t Archive::timeStampCreated() const {
876            return m_timeCreated;
877        }
878    
879        time_t Archive::timeStampModified() const {
880            return m_timeModified;
881        }
882    
883        tm Archive::dateTimeCreated(time_base_t base) const {
884            return _convertTimeStamp(m_timeCreated, base);
885        }
886    
887        tm Archive::dateTimeModified(time_base_t base) const {
888            return _convertTimeStamp(m_timeModified, base);
889        }
890    
891        void Archive::removeMember(Object& parent, const Member& member) {
892            parent.remove(member);
893            m_isModified = true;
894      }      }
895    
896      void Archive::remove(const Object& obj) {      void Archive::remove(const Object& obj) {
897            //FIXME: Should traverse from root object and remove all members associated with this object
898          if (!obj.uid()) return;          if (!obj.uid()) return;
899          m_allObjects.erase(obj.uid());          m_allObjects.erase(obj.uid());
900            m_isModified = true;
901      }      }
902    
903      Object& Archive::objectByUID(const UID& uid) {      Object& Archive::objectByUID(const UID& uid) {
904          return m_allObjects[uid];          return m_allObjects[uid];
905      }      }
906    
907        void Archive::setEnumValue(Object& object, uint64_t value) {
908            if (!object) return;
909            if (!object.type().isEnum())
910                throw Exception("Not an enum data type");
911            Object* pObject = &object;
912            if (object.type().isPointer()) {
913                Object& obj = objectByUID(object.uid(1));
914                if (!obj) return;
915                pObject = &obj;
916            }
917            const int nativeEnumSize = sizeof(enum operation_t);
918            DataType& type = const_cast<DataType&>( pObject->type() );
919            // original serializer ("sender") might have had a different word size
920            // than this machine, adjust type object in this case
921            if (type.size() != nativeEnumSize) {
922                type.m_size = nativeEnumSize;
923            }
924            pObject->m_data.resize(type.size());
925            void* ptr = &pObject->m_data[0];
926            if (type.size() == 1)
927                *(uint8_t*)ptr = (uint8_t)value;
928            else if (type.size() == 2)
929                *(uint16_t*)ptr = (uint16_t)value;
930            else if (type.size() == 4)
931                *(uint32_t*)ptr = (uint32_t)value;
932            else if (type.size() == 8)
933                *(uint64_t*)ptr = (uint64_t)value;
934            else
935                assert(false /* unknown enum type size */);
936            m_isModified = true;
937        }
938    
939        void Archive::setIntValue(Object& object, int64_t value) {
940            if (!object) return;
941            if (!object.type().isInteger())
942                throw Exception("Not an integer data type");
943            Object* pObject = &object;
944            if (object.type().isPointer()) {
945                Object& obj = objectByUID(object.uid(1));
946                if (!obj) return;
947                pObject = &obj;
948            }
949            const DataType& type = pObject->type();
950            pObject->m_data.resize(type.size());
951            void* ptr = &pObject->m_data[0];
952            if (type.isSigned()) {
953                if (type.size() == 1)
954                    *(int8_t*)ptr = (int8_t)value;
955                else if (type.size() == 2)
956                    *(int16_t*)ptr = (int16_t)value;
957                else if (type.size() == 4)
958                    *(int32_t*)ptr = (int32_t)value;
959                else if (type.size() == 8)
960                    *(int64_t*)ptr = (int64_t)value;
961                else
962                    assert(false /* unknown signed int type size */);
963            } else {
964                if (type.size() == 1)
965                    *(uint8_t*)ptr = (uint8_t)value;
966                else if (type.size() == 2)
967                    *(uint16_t*)ptr = (uint16_t)value;
968                else if (type.size() == 4)
969                    *(uint32_t*)ptr = (uint32_t)value;
970                else if (type.size() == 8)
971                    *(uint64_t*)ptr = (uint64_t)value;
972                else
973                    assert(false /* unknown unsigned int type size */);
974            }
975            m_isModified = true;
976        }
977    
978        void Archive::setRealValue(Object& object, double value) {
979            if (!object) return;
980            if (!object.type().isReal())
981                throw Exception("Not a real data type");
982            Object* pObject = &object;
983            if (object.type().isPointer()) {
984                Object& obj = objectByUID(object.uid(1));
985                if (!obj) return;
986                pObject = &obj;
987            }
988            const DataType& type = pObject->type();
989            pObject->m_data.resize(type.size());
990            void* ptr = &pObject->m_data[0];
991            if (type.size() == sizeof(float))
992                *(float*)ptr = (float)value;
993            else if (type.size() == sizeof(double))
994                *(double*)ptr = (double)value;
995            else
996                assert(false /* unknown real type size */);
997            m_isModified = true;
998        }
999    
1000        void Archive::setBoolValue(Object& object, bool value) {
1001            if (!object) return;
1002            if (!object.type().isBool())
1003                throw Exception("Not a bool data type");
1004            Object* pObject = &object;
1005            if (object.type().isPointer()) {
1006                Object& obj = objectByUID(object.uid(1));
1007                if (!obj) return;
1008                pObject = &obj;
1009            }
1010            const DataType& type = pObject->type();
1011            pObject->m_data.resize(type.size());
1012            bool* ptr = (bool*)&pObject->m_data[0];
1013            *ptr = value;
1014            m_isModified = true;
1015        }
1016    
1017        void Archive::setAutoValue(Object& object, String value) {
1018            if (!object) return;
1019            const DataType& type = object.type();
1020            if (type.isInteger())
1021                setIntValue(object, atoll(value.c_str()));
1022            else if (type.isReal())
1023                setRealValue(object, atof(value.c_str()));
1024            else if (type.isBool())
1025                setBoolValue(object, atof(value.c_str()));
1026            else if (type.isEnum())
1027                setEnumValue(object, atoll(value.c_str()));
1028            else
1029                throw Exception("Not a primitive data type");
1030        }
1031    
1032        String Archive::valueAsString(const Object& object) {
1033            if (!object)
1034                throw Exception("Invalid object");
1035            if (object.type().isClass())
1036                throw Exception("Object is class type");
1037            const Object* pObject = &object;
1038            if (object.type().isPointer()) {
1039                const Object& obj = objectByUID(object.uid(1));
1040                if (!obj) return "";
1041                pObject = &obj;
1042            }
1043            return _primitiveObjectValueToString(*pObject);
1044        }
1045    
1046        int64_t Archive::valueAsInt(const Object& object) {
1047            if (!object)
1048                throw Exception("Invalid object");
1049            if (!object.type().isInteger() && !object.type().isEnum())
1050                throw Exception("Object is neither an integer nor an enum");
1051            const Object* pObject = &object;
1052            if (object.type().isPointer()) {
1053                const Object& obj = objectByUID(object.uid(1));
1054                if (!obj) return 0;
1055                pObject = &obj;
1056            }
1057            return _primitiveObjectValueToNumber<int64_t>(*pObject);
1058        }
1059    
1060        double Archive::valueAsReal(const Object& object) {
1061            if (!object)
1062                throw Exception("Invalid object");
1063            if (!object.type().isReal())
1064                throw Exception("Object is not an real type");
1065            const Object* pObject = &object;
1066            if (object.type().isPointer()) {
1067                const Object& obj = objectByUID(object.uid(1));
1068                if (!obj) return 0;
1069                pObject = &obj;
1070            }
1071            return _primitiveObjectValueToNumber<double>(*pObject);
1072        }
1073    
1074        bool Archive::valueAsBool(const Object& object) {
1075            if (!object)
1076                throw Exception("Invalid object");
1077            if (!object.type().isBool())
1078                throw Exception("Object is not a bool");
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<bool>(*pObject);
1086        }
1087    
1088      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
1089      // *      // *
1090    

Legend:
Removed from v.3146  
changed lines
  Added in v.3169

  ViewVC Help
Powered by ViewVC