/[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 3138 by schoenebeck, Wed May 3 14:41:58 2017 UTC revision 3159 by schoenebeck, Mon May 8 21:15:16 2017 UTC
# Line 26  Line 26 
26  #include <iostream>  #include <iostream>
27  #include <assert.h>  #include <assert.h>
28  #include <string.h> // for memcpy()  #include <string.h> // for memcpy()
29  #include <stdlib.h> // for atof() and atof_l()  #include <stdlib.h> // for atof()
 #include <xlocale.h> // for locale passed to atof_l()  
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 ***************
# Line 191  namespace Serialization { Line 192  namespace Serialization {
192          m_uid  = uidChain;          m_uid  = uidChain;
193          m_version = 0;          m_version = 0;
194          m_minVersion = 0;          m_minVersion = 0;
195          m_data.resize(type.size());          //m_data.resize(type.size());
196      }      }
197    
198      bool Object::isValid() const {      bool Object::isValid() const {
# Line 237  namespace Serialization { Line 238  namespace Serialization {
238          return Member();          return Member();
239      }      }
240    
241        Member Object::memberByUID(const UID& uid) const {
242            if (!uid) return Member();
243            for (int i = 0; i < m_members.size(); ++i)
244                if (m_members[i].uid() == uid)
245                    return m_members[i];
246            return Member();
247        }
248    
249      void Object::remove(const Member& member) {      void Object::remove(const Member& member) {
250          for (int i = 0; i < m_members.size(); ++i) {          for (int i = 0; i < m_members.size(); ++i) {
251              if (m_members[i] == member) {              if (m_members[i] == member) {
# Line 269  namespace Serialization { Line 278  namespace Serialization {
278      Archive::Archive() {      Archive::Archive() {
279          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
280          m_root = NO_UID;          m_root = NO_UID;
281            m_isModified = false;
282            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
283      }      }
284    
285      Archive::Archive(const RawData& data) {      Archive::Archive(const RawData& data) {
286          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
287          m_root = NO_UID;          m_root = NO_UID;
288            m_isModified = false;
289            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
290          decode(m_rawData);          decode(m_rawData);
291      }      }
292    
293      Archive::Archive(const uint8_t* data, size_t size) {      Archive::Archive(const uint8_t* data, size_t size) {
294          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
295          m_root = NO_UID;          m_root = NO_UID;
296            m_isModified = false;
297            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
298          decode(data, size);          decode(data, size);
299      }      }
300    
# Line 301  namespace Serialization { Line 316  namespace Serialization {
316          return _encodeBlob(s);          return _encodeBlob(s);
317      }      }
318    
319        static String _encode(const time_t& time) {
320            return _encodeBlob(ToString(time));
321        }
322    
323      static String _encode(const DataType& type) {      static String _encode(const DataType& type) {
324          String s;          String s;
325          s += _encodeBlob(type.baseTypeName());          s += _encodeBlob(type.baseTypeName());
# Line 333  namespace Serialization { Line 352  namespace Serialization {
352          return _encodeBlob(s);          return _encodeBlob(s);
353      }      }
354    
355      static String _encodePrimitiveValue(const Object& obj) {      static String _primitiveObjectValueToString(const Object& obj) {
356          String s;          String s;
357          const DataType& type = obj.type();          const DataType& type = obj.type();
358          const ID& id = obj.uid().id;          const ID& id = obj.uid().id;
359            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
360            if (!obj.m_data.empty())
361                assert(type.size() == obj.m_data.size());
362          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
363              if (type.isInteger() || type.isEnum()) {              if (type.isInteger() || type.isEnum()) {
364                  if (type.isSigned()) {                  if (type.isSigned()) {
365                      if (type.size() == 1)                      if (type.size() == 1)
366                          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
367                      else if (type.size() == 2)                      else if (type.size() == 2)
368                          s = ToString(*(int16_t*)id);                          s = ToString(*(int16_t*)ptr);
369                      else if (type.size() == 4)                      else if (type.size() == 4)
370                          s = ToString(*(int32_t*)id);                          s = ToString(*(int32_t*)ptr);
371                      else if (type.size() == 8)                      else if (type.size() == 8)
372                          s = ToString(*(int64_t*)id);                          s = ToString(*(int64_t*)ptr);
373                      else                      else
374                          assert(false /* unknown signed int type size */);                          assert(false /* unknown signed int type size */);
375                  } else {                  } else {
376                      if (type.size() == 1)                      if (type.size() == 1)
377                          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
378                      else if (type.size() == 2)                      else if (type.size() == 2)
379                          s = ToString(*(uint16_t*)id);                          s = ToString(*(uint16_t*)ptr);
380                      else if (type.size() == 4)                      else if (type.size() == 4)
381                          s = ToString(*(uint32_t*)id);                          s = ToString(*(uint32_t*)ptr);
382                      else if (type.size() == 8)                      else if (type.size() == 8)
383                          s = ToString(*(uint64_t*)id);                          s = ToString(*(uint64_t*)ptr);
384                      else                      else
385                          assert(false /* unknown unsigned int type size */);                          assert(false /* unknown unsigned int type size */);
386                  }                  }
387              } else if (type.isReal()) {              } else if (type.isReal()) {
388                  if (type.size() == sizeof(float))                  if (type.size() == sizeof(float))
389                      s = ToString(*(float*)id);                      s = ToString(*(float*)ptr);
390                  else if (type.size() == sizeof(double))                  else if (type.size() == sizeof(double))
391                      s = ToString(*(double*)id);                      s = ToString(*(double*)ptr);
392                  else                  else
393                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
394              } else if (type.isBool()) {              } else if (type.isBool()) {
395                  s = ToString(*(bool*)id);                  s = ToString(*(bool*)ptr);
396              } else {              } else {
397                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
398              }              }
399    
400          }          }
401          return _encodeBlob(s);          return s;
402        }
403    
404        static String _encodePrimitiveValue(const Object& obj) {
405            return _encodeBlob( _primitiveObjectValueToString(obj) );
406      }      }
407    
408      static String _encode(const Object& obj) {      static String _encode(const Object& obj) {
# Line 409  namespace Serialization { Line 435  namespace Serialization {
435          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
436          s += _encode(m_root);          s += _encode(m_root);
437          s += _encode(m_allObjects);          s += _encode(m_allObjects);
438            s += _encodeBlob(m_name);
439            s += _encodeBlob(m_comment);
440            s += _encode(m_timeCreated);
441            s += _encode(m_timeModified);
442          return _encodeBlob(s);          return _encodeBlob(s);
443      }      }
444    
445      void Archive::encode() {      void Archive::encode() {
446          m_rawData.clear();          m_rawData.clear();
447          String s = MAGIC_START;          String s = MAGIC_START;
448            m_timeModified = time(NULL);
449            if (m_timeCreated == LIBGIG_EPOCH_TIME)
450                m_timeCreated = m_timeModified;
451          s += _encodeRootBlob();          s += _encodeRootBlob();
452          m_rawData.resize(s.length() + 1);          m_rawData.resize(s.length() + 1);
453          memcpy(&m_rawData[0], &s[0], s.length() + 1);          memcpy(&m_rawData[0], &s[0], s.length() + 1);
454            m_isModified = false;
455      }      }
456    
457      struct _Blob {      struct _Blob {
# Line 487  namespace Serialization { Line 521  namespace Serialization {
521          String s(p, size_t(end - p));          String s(p, size_t(end - p));
522    
523          T_real r;          T_real r;
524          if (sizeof(T_real) == sizeof(float))          if (sizeof(T_real) <= sizeof(double))
525              r = atof(s.c_str());              r = atof(s.c_str());
         else if (sizeof(T_real) == sizeof(double))  
             r = atof_l(s.c_str(), _c_locale);  
526          else          else
527              assert(false /* unknown real type */);              assert(false /* unknown real type */);
528    
# Line 519  namespace Serialization { Line 551  namespace Serialization {
551          return s;          return s;
552      }      }
553    
554        static time_t _popTimeBlob(const char*& p, const char* end) {
555            const uint64_t i = _popIntBlob<uint64_t>(p, end);
556            return (time_t) i;
557        }
558    
559      DataType _popDataTypeBlob(const char*& p, const char* end) {      DataType _popDataTypeBlob(const char*& p, const char* end) {
560          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
561          p   = blob.p;          p   = blob.p;
# Line 560  namespace Serialization { Line 597  namespace Serialization {
597          return chain;          return chain;
598      }      }
599    
600      Member _popMemberBlob(const char*& p, const char* end) {      static Member _popMemberBlob(const char*& p, const char* end) {
601          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
602          p   = blob.p;          p   = blob.p;
603          end = blob.end;          end = blob.end;
# Line 574  namespace Serialization { Line 611  namespace Serialization {
611          m.m_type   = _popDataTypeBlob(p, end);          m.m_type   = _popDataTypeBlob(p, end);
612          assert(m.type());          assert(m.type());
613          assert(!m.name().empty());          assert(!m.name().empty());
614          assert(m.uid() != NULL);          assert(m.uid().isValid());
615          return m;          return m;
616      }      }
617    
# Line 594  namespace Serialization { Line 631  namespace Serialization {
631          return members;          return members;
632      }      }
633    
634      void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {      static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
635          const DataType& type = obj.type();          const DataType& type = obj.type();
636          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
637              obj.m_data.resize(type.size());              obj.m_data.resize(type.size());
# Line 643  namespace Serialization { Line 680  namespace Serialization {
680          }          }
681      }      }
682    
683      Object _popObjectBlob(const char*& p, const char* end) {      static Object _popObjectBlob(const char*& p, const char* end) {
684          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
685          p   = blob.p;          p   = blob.p;
686          end = blob.end;          end = blob.end;
# Line 695  namespace Serialization { Line 732  namespace Serialization {
732          _popObjectsBlob(p, end);          _popObjectsBlob(p, end);
733          if (!m_allObjects[m_root])          if (!m_allObjects[m_root])
734              throw Exception("Decode Error: Missing declared root object");              throw Exception("Decode Error: Missing declared root object");
735    
736            m_name = _popStringBlob(p, end);
737            m_comment = _popStringBlob(p, end);
738            m_timeCreated = _popTimeBlob(p, end);
739            m_timeModified = _popTimeBlob(p, end);
740      }      }
741    
742      void Archive::decode(const RawData& data) {      void Archive::decode(const RawData& data) {
743          m_rawData = data;          m_rawData = data;
744          m_allObjects.clear();          m_allObjects.clear();
745            m_isModified = false;
746            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
747          const char* p   = (const char*) &data[0];          const char* p   = (const char*) &data[0];
748          const char* end = p + data.size();          const char* end = p + data.size();
749          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 715  namespace Serialization { Line 759  namespace Serialization {
759          decode(rawData);          decode(rawData);
760      }      }
761    
762        const RawData& Archive::rawData() {
763            if (m_isModified) encode();
764            return m_rawData;
765        }
766    
767      String Archive::rawDataFormat() const {      String Archive::rawDataFormat() const {
768          return MAGIC_START;          return MAGIC_START;
769      }      }
770    
771        bool Archive::isModified() const {
772            return m_isModified;
773        }
774    
775      void Archive::clear() {      void Archive::clear() {
776          m_allObjects.clear();          m_allObjects.clear();
777          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
778          m_root = NO_UID;          m_root = NO_UID;
779          m_rawData.clear();          m_rawData.clear();
780            m_isModified = false;
781            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
782        }
783    
784        String Archive::name() const {
785            return m_name;
786        }
787    
788        void Archive::setName(String name) {
789            if (m_name == name) return;
790            m_name = name;
791            m_isModified = true;
792        }
793    
794        String Archive::comment() const {
795            return m_comment;
796        }
797    
798        void Archive::setComment(String comment) {
799            if (m_comment == comment) return;
800            m_comment = comment;
801            m_isModified = true;
802        }
803    
804        static tm _convertTimeStamp(const time_t& time, time_base_t base) {
805            tm* pTm;
806            switch (base) {
807                case LOCAL_TIME:
808                    pTm = localtime(&time);
809                    break;
810                case UTC_TIME:
811                    pTm = gmtime(&time);
812                    break;
813                default:
814                    throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
815            }
816            if (!pTm)
817                throw Exception("Failed assembling time stamp structure");
818            return *pTm;
819        }
820    
821        time_t Archive::timeStampCreated() const {
822            return m_timeCreated;
823        }
824    
825        time_t Archive::timeStampModified() const {
826            return m_timeModified;
827        }
828    
829        tm Archive::dateTimeCreated(time_base_t base) const {
830            return _convertTimeStamp(m_timeCreated, base);
831        }
832    
833        tm Archive::dateTimeModified(time_base_t base) const {
834            return _convertTimeStamp(m_timeModified, base);
835        }
836    
837        void Archive::removeMember(Object& parent, const Member& member) {
838            parent.remove(member);
839            m_isModified = true;
840      }      }
841    
842      void Archive::remove(const Object& obj) {      void Archive::remove(const Object& obj) {
843            //FIXME: Should traverse from root object and remove all members associated with this object
844          if (!obj.uid()) return;          if (!obj.uid()) return;
845          m_allObjects.erase(obj.uid());          m_allObjects.erase(obj.uid());
846            m_isModified = true;
847      }      }
848    
849      Object& Archive::objectByUID(const UID& uid) {      Object& Archive::objectByUID(const UID& uid) {
850          return m_allObjects[uid];          return m_allObjects[uid];
851      }      }
852    
853        void Archive::setEnumValue(Object& object, uint64_t value) {
854            if (!object) return;
855            if (!object.type().isEnum())
856                throw Exception("Not an enum data type");
857            Object* pObject = &object;
858            if (object.type().isPointer()) {
859                Object& obj = objectByUID(object.uid(1));
860                if (!obj) return;
861                pObject = &obj;
862            }
863            const int nativeEnumSize = sizeof(enum operation_t);
864            DataType& type = const_cast<DataType&>( pObject->type() );
865            // original serializer ("sender") might have had a different word size
866            // than this machine, adjust type object in this case
867            if (type.size() != nativeEnumSize) {
868                type.m_size = nativeEnumSize;
869            }
870            pObject->m_data.resize(type.size());
871            void* ptr = &pObject->m_data[0];
872            if (type.size() == 1)
873                *(uint8_t*)ptr = (uint8_t)value;
874            else if (type.size() == 2)
875                *(uint16_t*)ptr = (uint16_t)value;
876            else if (type.size() == 4)
877                *(uint32_t*)ptr = (uint32_t)value;
878            else if (type.size() == 8)
879                *(uint64_t*)ptr = (uint64_t)value;
880            else
881                assert(false /* unknown enum type size */);
882            m_isModified = true;
883        }
884    
885        void Archive::setIntValue(Object& object, int64_t value) {
886            if (!object) return;
887            if (!object.type().isInteger())
888                throw Exception("Not an integer data type");
889            Object* pObject = &object;
890            if (object.type().isPointer()) {
891                Object& obj = objectByUID(object.uid(1));
892                if (!obj) return;
893                pObject = &obj;
894            }
895            const DataType& type = pObject->type();
896            pObject->m_data.resize(type.size());
897            void* ptr = &pObject->m_data[0];
898            if (type.isSigned()) {
899                if (type.size() == 1)
900                    *(int8_t*)ptr = (int8_t)value;
901                else if (type.size() == 2)
902                    *(int16_t*)ptr = (int16_t)value;
903                else if (type.size() == 4)
904                    *(int32_t*)ptr = (int32_t)value;
905                else if (type.size() == 8)
906                    *(int64_t*)ptr = (int64_t)value;
907                else
908                    assert(false /* unknown signed int type size */);
909            } else {
910                if (type.size() == 1)
911                    *(uint8_t*)ptr = (uint8_t)value;
912                else if (type.size() == 2)
913                    *(uint16_t*)ptr = (uint16_t)value;
914                else if (type.size() == 4)
915                    *(uint32_t*)ptr = (uint32_t)value;
916                else if (type.size() == 8)
917                    *(uint64_t*)ptr = (uint64_t)value;
918                else
919                    assert(false /* unknown unsigned int type size */);
920            }
921            m_isModified = true;
922        }
923    
924        void Archive::setRealValue(Object& object, double value) {
925            if (!object) return;
926            if (!object.type().isReal())
927                throw Exception("Not a real data type");
928            Object* pObject = &object;
929            if (object.type().isPointer()) {
930                Object& obj = objectByUID(object.uid(1));
931                if (!obj) return;
932                pObject = &obj;
933            }
934            const DataType& type = pObject->type();
935            pObject->m_data.resize(type.size());
936            void* ptr = &pObject->m_data[0];
937            if (type.size() == sizeof(float))
938                *(float*)ptr = (float)value;
939            else if (type.size() == sizeof(double))
940                *(double*)ptr = (double)value;
941            else
942                assert(false /* unknown real type size */);
943            m_isModified = true;
944        }
945    
946        void Archive::setBoolValue(Object& object, bool value) {
947            if (!object) return;
948            if (!object.type().isBool())
949                throw Exception("Not a bool data type");
950            Object* pObject = &object;
951            if (object.type().isPointer()) {
952                Object& obj = objectByUID(object.uid(1));
953                if (!obj) return;
954                pObject = &obj;
955            }
956            const DataType& type = pObject->type();
957            pObject->m_data.resize(type.size());
958            bool* ptr = (bool*)&pObject->m_data[0];
959            *ptr = value;
960            m_isModified = true;
961        }
962    
963        void Archive::setAutoValue(Object& object, String value) {
964            if (!object) return;
965            const DataType& type = object.type();
966            if (type.isInteger())
967                setIntValue(object, atoll(value.c_str()));
968            else if (type.isReal())
969                setRealValue(object, atof(value.c_str()));
970            else if (type.isBool())
971                setBoolValue(object, atof(value.c_str()));
972            else if (type.isEnum())
973                setEnumValue(object, atoll(value.c_str()));
974            else
975                throw Exception("Not a primitive data type");
976        }
977    
978        String Archive::valueAsString(const Object& object) {
979            if (!object)
980                throw Exception("Invalid object");
981            if (object.type().isClass())
982                throw Exception("Object is class type");
983            const Object* pObject = &object;
984            if (object.type().isPointer()) {
985                const Object& obj = objectByUID(object.uid(1));
986                if (!obj) return "";
987                pObject = &obj;
988            }
989            return _primitiveObjectValueToString(*pObject);
990        }
991    
992      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
993      // *      // *
994    

Legend:
Removed from v.3138  
changed lines
  Added in v.3159

  ViewVC Help
Powered by ViewVC