/[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 3139 by schoenebeck, Wed May 3 15:15:10 2017 UTC revision 3168 by schoenebeck, Tue May 9 19:12:32 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        static String _encodePrimitiveValue(const Object& obj) {
406            return _encodeBlob( _primitiveObjectValueToString(obj) );
407      }      }
408    
409      static String _encode(const Object& obj) {      static String _encode(const Object& obj) {
# Line 408  namespace Serialization { Line 436  namespace Serialization {
436          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
437          s += _encode(m_root);          s += _encode(m_root);
438          s += _encode(m_allObjects);          s += _encode(m_allObjects);
439            s += _encodeBlob(m_name);
440            s += _encodeBlob(m_comment);
441            s += _encode(m_timeCreated);
442            s += _encode(m_timeModified);
443          return _encodeBlob(s);          return _encodeBlob(s);
444      }      }
445    
446      void Archive::encode() {      void Archive::encode() {
447          m_rawData.clear();          m_rawData.clear();
448          String s = MAGIC_START;          String s = MAGIC_START;
449            m_timeModified = time(NULL);
450            if (m_timeCreated == LIBGIG_EPOCH_TIME)
451                m_timeCreated = m_timeModified;
452          s += _encodeRootBlob();          s += _encodeRootBlob();
453          m_rawData.resize(s.length() + 1);          m_rawData.resize(s.length() + 1);
454          memcpy(&m_rawData[0], &s[0], s.length() + 1);          memcpy(&m_rawData[0], &s[0], s.length() + 1);
455            m_isModified = false;
456      }      }
457    
458      struct _Blob {      struct _Blob {
# Line 425  namespace Serialization { Line 461  namespace Serialization {
461      };      };
462    
463      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
464          if (!bThrow && p >= end)          if (!bThrow && p >= end) {
465              return (_Blob) { p, end };              const _Blob blob =  { p, end };
466                return blob;
467            }
468          size_t sz = 0;          size_t sz = 0;
469          for (; true; ++p) {          for (; true; ++p) {
470              if (p >= end)              if (p >= end)
# Line 441  namespace Serialization { Line 479  namespace Serialization {
479          ++p;          ++p;
480          if (p + sz > end)          if (p + sz > end)
481              throw Exception("Decode Error: Premature end of blob");              throw Exception("Decode Error: Premature end of blob");
482          return (_Blob) { p, p + sz };          const _Blob blob = { p, p + sz };
483            return blob;
484      }      }
485    
486      template<typename T_int>      template<typename T_int>
# Line 516  namespace Serialization { Line 555  namespace Serialization {
555          return s;          return s;
556      }      }
557    
558        static time_t _popTimeBlob(const char*& p, const char* end) {
559            const uint64_t i = _popIntBlob<uint64_t>(p, end);
560            return (time_t) i;
561        }
562    
563      DataType _popDataTypeBlob(const char*& p, const char* end) {      DataType _popDataTypeBlob(const char*& p, const char* end) {
564          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
565          p   = blob.p;          p   = blob.p;
# Line 540  namespace Serialization { Line 584  namespace Serialization {
584          const ID id = (ID) _popIntBlob<size_t>(p, end);          const ID id = (ID) _popIntBlob<size_t>(p, end);
585          const size_t size = _popIntBlob<size_t>(p, end);          const size_t size = _popIntBlob<size_t>(p, end);
586    
587          return (UID) { id, size };          const UID uid = { id, size };
588            return uid;
589      }      }
590    
591      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
# Line 557  namespace Serialization { Line 602  namespace Serialization {
602          return chain;          return chain;
603      }      }
604    
605      Member _popMemberBlob(const char*& p, const char* end) {      static Member _popMemberBlob(const char*& p, const char* end) {
606          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
607          p   = blob.p;          p   = blob.p;
608          end = blob.end;          end = blob.end;
# Line 571  namespace Serialization { Line 616  namespace Serialization {
616          m.m_type   = _popDataTypeBlob(p, end);          m.m_type   = _popDataTypeBlob(p, end);
617          assert(m.type());          assert(m.type());
618          assert(!m.name().empty());          assert(!m.name().empty());
619          assert(m.uid() != NULL);          assert(m.uid().isValid());
620          return m;          return m;
621      }      }
622    
# Line 591  namespace Serialization { Line 636  namespace Serialization {
636          return members;          return members;
637      }      }
638    
639      void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {      static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
640          const DataType& type = obj.type();          const DataType& type = obj.type();
641          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
642              obj.m_data.resize(type.size());              obj.m_data.resize(type.size());
# Line 640  namespace Serialization { Line 685  namespace Serialization {
685          }          }
686      }      }
687    
688      Object _popObjectBlob(const char*& p, const char* end) {      static Object _popObjectBlob(const char*& p, const char* end) {
689          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
690          p   = blob.p;          p   = blob.p;
691          end = blob.end;          end = blob.end;
# Line 692  namespace Serialization { Line 737  namespace Serialization {
737          _popObjectsBlob(p, end);          _popObjectsBlob(p, end);
738          if (!m_allObjects[m_root])          if (!m_allObjects[m_root])
739              throw Exception("Decode Error: Missing declared root object");              throw Exception("Decode Error: Missing declared root object");
740    
741            m_name = _popStringBlob(p, end);
742            m_comment = _popStringBlob(p, end);
743            m_timeCreated = _popTimeBlob(p, end);
744            m_timeModified = _popTimeBlob(p, end);
745      }      }
746    
747      void Archive::decode(const RawData& data) {      void Archive::decode(const RawData& data) {
748          m_rawData = data;          m_rawData = data;
749          m_allObjects.clear();          m_allObjects.clear();
750            m_isModified = false;
751            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
752          const char* p   = (const char*) &data[0];          const char* p   = (const char*) &data[0];
753          const char* end = p + data.size();          const char* end = p + data.size();
754          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 764  namespace Serialization {
764          decode(rawData);          decode(rawData);
765      }      }
766    
767        const RawData& Archive::rawData() {
768            if (m_isModified) encode();
769            return m_rawData;
770        }
771    
772      String Archive::rawDataFormat() const {      String Archive::rawDataFormat() const {
773          return MAGIC_START;          return MAGIC_START;
774      }      }
775    
776        bool Archive::isModified() const {
777            return m_isModified;
778        }
779    
780      void Archive::clear() {      void Archive::clear() {
781          m_allObjects.clear();          m_allObjects.clear();
782          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
783          m_root = NO_UID;          m_root = NO_UID;
784          m_rawData.clear();          m_rawData.clear();
785            m_isModified = false;
786            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
787        }
788    
789        String Archive::name() const {
790            return m_name;
791        }
792    
793        void Archive::setName(String name) {
794            if (m_name == name) return;
795            m_name = name;
796            m_isModified = true;
797        }
798    
799        String Archive::comment() const {
800            return m_comment;
801        }
802    
803        void Archive::setComment(String comment) {
804            if (m_comment == comment) return;
805            m_comment = comment;
806            m_isModified = true;
807        }
808    
809        static tm _convertTimeStamp(const time_t& time, time_base_t base) {
810            tm* pTm;
811            switch (base) {
812                case LOCAL_TIME:
813                    pTm = localtime(&time);
814                    break;
815                case UTC_TIME:
816                    pTm = gmtime(&time);
817                    break;
818                default:
819                    throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
820            }
821            if (!pTm)
822                throw Exception("Failed assembling time stamp structure");
823            return *pTm;
824        }
825    
826        time_t Archive::timeStampCreated() const {
827            return m_timeCreated;
828        }
829    
830        time_t Archive::timeStampModified() const {
831            return m_timeModified;
832        }
833    
834        tm Archive::dateTimeCreated(time_base_t base) const {
835            return _convertTimeStamp(m_timeCreated, base);
836        }
837    
838        tm Archive::dateTimeModified(time_base_t base) const {
839            return _convertTimeStamp(m_timeModified, base);
840        }
841    
842        void Archive::removeMember(Object& parent, const Member& member) {
843            parent.remove(member);
844            m_isModified = true;
845      }      }
846    
847      void Archive::remove(const Object& obj) {      void Archive::remove(const Object& obj) {
848            //FIXME: Should traverse from root object and remove all members associated with this object
849          if (!obj.uid()) return;          if (!obj.uid()) return;
850          m_allObjects.erase(obj.uid());          m_allObjects.erase(obj.uid());
851            m_isModified = true;
852      }      }
853    
854      Object& Archive::objectByUID(const UID& uid) {      Object& Archive::objectByUID(const UID& uid) {
855          return m_allObjects[uid];          return m_allObjects[uid];
856      }      }
857    
858        void Archive::setEnumValue(Object& object, uint64_t value) {
859            if (!object) return;
860            if (!object.type().isEnum())
861                throw Exception("Not an enum data type");
862            Object* pObject = &object;
863            if (object.type().isPointer()) {
864                Object& obj = objectByUID(object.uid(1));
865                if (!obj) return;
866                pObject = &obj;
867            }
868            const int nativeEnumSize = sizeof(enum operation_t);
869            DataType& type = const_cast<DataType&>( pObject->type() );
870            // original serializer ("sender") might have had a different word size
871            // than this machine, adjust type object in this case
872            if (type.size() != nativeEnumSize) {
873                type.m_size = nativeEnumSize;
874            }
875            pObject->m_data.resize(type.size());
876            void* ptr = &pObject->m_data[0];
877            if (type.size() == 1)
878                *(uint8_t*)ptr = (uint8_t)value;
879            else if (type.size() == 2)
880                *(uint16_t*)ptr = (uint16_t)value;
881            else if (type.size() == 4)
882                *(uint32_t*)ptr = (uint32_t)value;
883            else if (type.size() == 8)
884                *(uint64_t*)ptr = (uint64_t)value;
885            else
886                assert(false /* unknown enum type size */);
887            m_isModified = true;
888        }
889    
890        void Archive::setIntValue(Object& object, int64_t value) {
891            if (!object) return;
892            if (!object.type().isInteger())
893                throw Exception("Not an integer data type");
894            Object* pObject = &object;
895            if (object.type().isPointer()) {
896                Object& obj = objectByUID(object.uid(1));
897                if (!obj) return;
898                pObject = &obj;
899            }
900            const DataType& type = pObject->type();
901            pObject->m_data.resize(type.size());
902            void* ptr = &pObject->m_data[0];
903            if (type.isSigned()) {
904                if (type.size() == 1)
905                    *(int8_t*)ptr = (int8_t)value;
906                else if (type.size() == 2)
907                    *(int16_t*)ptr = (int16_t)value;
908                else if (type.size() == 4)
909                    *(int32_t*)ptr = (int32_t)value;
910                else if (type.size() == 8)
911                    *(int64_t*)ptr = (int64_t)value;
912                else
913                    assert(false /* unknown signed int type size */);
914            } else {
915                if (type.size() == 1)
916                    *(uint8_t*)ptr = (uint8_t)value;
917                else if (type.size() == 2)
918                    *(uint16_t*)ptr = (uint16_t)value;
919                else if (type.size() == 4)
920                    *(uint32_t*)ptr = (uint32_t)value;
921                else if (type.size() == 8)
922                    *(uint64_t*)ptr = (uint64_t)value;
923                else
924                    assert(false /* unknown unsigned int type size */);
925            }
926            m_isModified = true;
927        }
928    
929        void Archive::setRealValue(Object& object, double value) {
930            if (!object) return;
931            if (!object.type().isReal())
932                throw Exception("Not a real data type");
933            Object* pObject = &object;
934            if (object.type().isPointer()) {
935                Object& obj = objectByUID(object.uid(1));
936                if (!obj) return;
937                pObject = &obj;
938            }
939            const DataType& type = pObject->type();
940            pObject->m_data.resize(type.size());
941            void* ptr = &pObject->m_data[0];
942            if (type.size() == sizeof(float))
943                *(float*)ptr = (float)value;
944            else if (type.size() == sizeof(double))
945                *(double*)ptr = (double)value;
946            else
947                assert(false /* unknown real type size */);
948            m_isModified = true;
949        }
950    
951        void Archive::setBoolValue(Object& object, bool value) {
952            if (!object) return;
953            if (!object.type().isBool())
954                throw Exception("Not a bool data type");
955            Object* pObject = &object;
956            if (object.type().isPointer()) {
957                Object& obj = objectByUID(object.uid(1));
958                if (!obj) return;
959                pObject = &obj;
960            }
961            const DataType& type = pObject->type();
962            pObject->m_data.resize(type.size());
963            bool* ptr = (bool*)&pObject->m_data[0];
964            *ptr = value;
965            m_isModified = true;
966        }
967    
968        void Archive::setAutoValue(Object& object, String value) {
969            if (!object) return;
970            const DataType& type = object.type();
971            if (type.isInteger())
972                setIntValue(object, atoll(value.c_str()));
973            else if (type.isReal())
974                setRealValue(object, atof(value.c_str()));
975            else if (type.isBool())
976                setBoolValue(object, atof(value.c_str()));
977            else if (type.isEnum())
978                setEnumValue(object, atoll(value.c_str()));
979            else
980                throw Exception("Not a primitive data type");
981        }
982    
983        String Archive::valueAsString(const Object& object) {
984            if (!object)
985                throw Exception("Invalid object");
986            if (object.type().isClass())
987                throw Exception("Object is class type");
988            const Object* pObject = &object;
989            if (object.type().isPointer()) {
990                const Object& obj = objectByUID(object.uid(1));
991                if (!obj) return "";
992                pObject = &obj;
993            }
994            return _primitiveObjectValueToString(*pObject);
995        }
996    
997      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
998      // *      // *
999    

Legend:
Removed from v.3139  
changed lines
  Added in v.3168

  ViewVC Help
Powered by ViewVC