/[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 3173 by schoenebeck, Wed May 10 23:07:28 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()
30  #include <xlocale.h> // for locale passed to atof_l()  #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 125  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 191  namespace Serialization { Line 201  namespace Serialization {
201          m_uid  = uidChain;          m_uid  = uidChain;
202          m_version = 0;          m_version = 0;
203          m_minVersion = 0;          m_minVersion = 0;
204          m_data.resize(type.size());          //m_data.resize(type.size());
205      }      }
206    
207      bool Object::isValid() const {      bool Object::isValid() const {
# Line 237  namespace Serialization { Line 247  namespace Serialization {
247          return Member();          return Member();
248      }      }
249    
250        Member Object::memberByUID(const UID& uid) const {
251            if (!uid) return Member();
252            for (int i = 0; i < m_members.size(); ++i)
253                if (m_members[i].uid() == uid)
254                    return m_members[i];
255            return Member();
256        }
257    
258      void Object::remove(const Member& member) {      void Object::remove(const Member& member) {
259          for (int i = 0; i < m_members.size(); ++i) {          for (int i = 0; i < m_members.size(); ++i) {
260              if (m_members[i] == member) {              if (m_members[i] == member) {
# Line 269  namespace Serialization { Line 287  namespace Serialization {
287      Archive::Archive() {      Archive::Archive() {
288          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
289          m_root = NO_UID;          m_root = NO_UID;
290            m_isModified = false;
291            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
292      }      }
293    
294      Archive::Archive(const RawData& data) {      Archive::Archive(const RawData& data) {
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(m_rawData);          decode(m_rawData);
300      }      }
301    
302      Archive::Archive(const uint8_t* data, size_t size) {      Archive::Archive(const uint8_t* data, size_t size) {
303          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
304          m_root = NO_UID;          m_root = NO_UID;
305            m_isModified = false;
306            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
307          decode(data, size);          decode(data, size);
308      }      }
309    
# Line 301  namespace Serialization { Line 325  namespace Serialization {
325          return _encodeBlob(s);          return _encodeBlob(s);
326      }      }
327    
328        static String _encode(const time_t& time) {
329            return _encodeBlob(ToString(time));
330        }
331    
332      static String _encode(const DataType& type) {      static String _encode(const DataType& type) {
333          String s;          String s;
334          s += _encodeBlob(type.baseTypeName());          s += _encodeBlob(type.baseTypeName());
# Line 333  namespace Serialization { Line 361  namespace Serialization {
361          return _encodeBlob(s);          return _encodeBlob(s);
362      }      }
363    
364      static String _encodePrimitiveValue(const Object& obj) {      static String _primitiveObjectValueToString(const Object& obj) {
365          String s;          String s;
366          const DataType& type = obj.type();          const DataType& type = obj.type();
367          const ID& id = obj.uid().id;          const ID& id = obj.uid().id;
368            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
369            if (!obj.m_data.empty())
370                assert(type.size() == obj.m_data.size());
371          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
372              if (type.isInteger() || type.isEnum()) {              if (type.isInteger() || type.isEnum()) {
373                  if (type.isSigned()) {                  if (type.isSigned()) {
374                      if (type.size() == 1)                      if (type.size() == 1)
375                          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
376                      else if (type.size() == 2)                      else if (type.size() == 2)
377                          s = ToString(*(int16_t*)id);                          s = ToString(*(int16_t*)ptr);
378                      else if (type.size() == 4)                      else if (type.size() == 4)
379                          s = ToString(*(int32_t*)id);                          s = ToString(*(int32_t*)ptr);
380                      else if (type.size() == 8)                      else if (type.size() == 8)
381                          s = ToString(*(int64_t*)id);                          s = ToString(*(int64_t*)ptr);
382                      else                      else
383                          assert(false /* unknown signed int type size */);                          assert(false /* unknown signed int type size */);
384                  } else {                  } else {
385                      if (type.size() == 1)                      if (type.size() == 1)
386                          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
387                      else if (type.size() == 2)                      else if (type.size() == 2)
388                          s = ToString(*(uint16_t*)id);                          s = ToString(*(uint16_t*)ptr);
389                      else if (type.size() == 4)                      else if (type.size() == 4)
390                          s = ToString(*(uint32_t*)id);                          s = ToString(*(uint32_t*)ptr);
391                      else if (type.size() == 8)                      else if (type.size() == 8)
392                          s = ToString(*(uint64_t*)id);                          s = ToString(*(uint64_t*)ptr);
393                      else                      else
394                          assert(false /* unknown unsigned int type size */);                          assert(false /* unknown unsigned int type size */);
395                  }                  }
396              } else if (type.isReal()) {              } else if (type.isReal()) {
397                  if (type.size() == sizeof(float))                  if (type.size() == sizeof(float))
398                      s = ToString(*(float*)id);                      s = ToString(*(float*)ptr);
399                  else if (type.size() == sizeof(double))                  else if (type.size() == sizeof(double))
400                      s = ToString(*(double*)id);                      s = ToString(*(double*)ptr);
401                  else                  else
402                      assert(false /* unknown floating point type */);                      assert(false /* unknown floating point type */);
403              } else if (type.isBool()) {              } else if (type.isBool()) {
404                  s = ToString(*(bool*)id);                  s = ToString(*(bool*)ptr);
405              } else {              } else {
406                  assert(false /* unknown primitive type */);                  assert(false /* unknown primitive type */);
407              }              }
408    
409          }          }
410          return _encodeBlob(s);          return s;
411        }
412    
413        template<typename T>
414        static T _primitiveObjectValueToNumber(const Object& obj) {
415            T value = 0;
416            const DataType& type = obj.type();
417            const ID& id = obj.uid().id;
418            void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
419            if (!obj.m_data.empty())
420                assert(type.size() == obj.m_data.size());
421            if (type.isPrimitive() && !type.isPointer()) {
422                if (type.isInteger() || type.isEnum()) {
423                    if (type.isSigned()) {
424                        if (type.size() == 1)
425                            value = (T)*(int8_t*)ptr;
426                        else if (type.size() == 2)
427                            value = (T)*(int16_t*)ptr;
428                        else if (type.size() == 4)
429                            value = (T)*(int32_t*)ptr;
430                        else if (type.size() == 8)
431                            value = (T)*(int64_t*)ptr;
432                        else
433                            assert(false /* unknown signed int type size */);
434                    } else {
435                        if (type.size() == 1)
436                            value = (T)*(uint8_t*)ptr;
437                        else if (type.size() == 2)
438                            value = (T)*(uint16_t*)ptr;
439                        else if (type.size() == 4)
440                            value = (T)*(uint32_t*)ptr;
441                        else if (type.size() == 8)
442                            value = (T)*(uint64_t*)ptr;
443                        else
444                            assert(false /* unknown unsigned int type size */);
445                    }
446                } else if (type.isReal()) {
447                    if (type.size() == sizeof(float))
448                        value = (T)*(float*)ptr;
449                    else if (type.size() == sizeof(double))
450                        value = (T)*(double*)ptr;
451                    else
452                        assert(false /* unknown floating point type */);
453                } else if (type.isBool()) {
454                    value = (T)*(bool*)ptr;
455                } else {
456                    assert(false /* unknown primitive type */);
457                }
458            }
459            return value;
460        }
461    
462        static String _encodePrimitiveValue(const Object& obj) {
463            return _encodeBlob( _primitiveObjectValueToString(obj) );
464      }      }
465    
466      static String _encode(const Object& obj) {      static String _encode(const Object& obj) {
# Line 409  namespace Serialization { Line 493  namespace Serialization {
493          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));          s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
494          s += _encode(m_root);          s += _encode(m_root);
495          s += _encode(m_allObjects);          s += _encode(m_allObjects);
496            s += _encodeBlob(m_name);
497            s += _encodeBlob(m_comment);
498            s += _encode(m_timeCreated);
499            s += _encode(m_timeModified);
500          return _encodeBlob(s);          return _encodeBlob(s);
501      }      }
502    
503      void Archive::encode() {      void Archive::encode() {
504          m_rawData.clear();          m_rawData.clear();
505          String s = MAGIC_START;          String s = MAGIC_START;
506            m_timeModified = time(NULL);
507            if (m_timeCreated == LIBGIG_EPOCH_TIME)
508                m_timeCreated = m_timeModified;
509          s += _encodeRootBlob();          s += _encodeRootBlob();
510          m_rawData.resize(s.length() + 1);          m_rawData.resize(s.length() + 1);
511          memcpy(&m_rawData[0], &s[0], s.length() + 1);          memcpy(&m_rawData[0], &s[0], s.length() + 1);
512            m_isModified = false;
513      }      }
514    
515      struct _Blob {      struct _Blob {
# Line 426  namespace Serialization { Line 518  namespace Serialization {
518      };      };
519    
520      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {      static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
521          if (!bThrow && p >= end)          if (!bThrow && p >= end) {
522              return (_Blob) { p, end };              const _Blob blob =  { p, end };
523                return blob;
524            }
525          size_t sz = 0;          size_t sz = 0;
526          for (; true; ++p) {          for (; true; ++p) {
527              if (p >= end)              if (p >= end)
# Line 442  namespace Serialization { Line 536  namespace Serialization {
536          ++p;          ++p;
537          if (p + sz > end)          if (p + sz > end)
538              throw Exception("Decode Error: Premature end of blob");              throw Exception("Decode Error: Premature end of blob");
539          return (_Blob) { p, p + sz };          const _Blob blob = { p, p + sz };
540            return blob;
541      }      }
542    
543      template<typename T_int>      template<typename T_int>
# Line 487  namespace Serialization { Line 582  namespace Serialization {
582          String s(p, size_t(end - p));          String s(p, size_t(end - p));
583    
584          T_real r;          T_real r;
585          if (sizeof(T_real) == sizeof(float))          if (sizeof(T_real) <= sizeof(double))
586              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);  
587          else          else
588              assert(false /* unknown real type */);              assert(false /* unknown real type */);
589    
# Line 519  namespace Serialization { Line 612  namespace Serialization {
612          return s;          return s;
613      }      }
614    
615        static time_t _popTimeBlob(const char*& p, const char* end) {
616            const uint64_t i = _popIntBlob<uint64_t>(p, end);
617            return (time_t) i;
618        }
619    
620      DataType _popDataTypeBlob(const char*& p, const char* end) {      DataType _popDataTypeBlob(const char*& p, const char* end) {
621          _Blob blob = _decodeBlob(p, end);          _Blob blob = _decodeBlob(p, end);
622          p   = blob.p;          p   = blob.p;
# Line 543  namespace Serialization { Line 641  namespace Serialization {
641          const ID id = (ID) _popIntBlob<size_t>(p, end);          const ID id = (ID) _popIntBlob<size_t>(p, end);
642          const size_t size = _popIntBlob<size_t>(p, end);          const size_t size = _popIntBlob<size_t>(p, end);
643    
644          return (UID) { id, size };          const UID uid = { id, size };
645            return uid;
646      }      }
647    
648      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {      static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
# Line 560  namespace Serialization { Line 659  namespace Serialization {
659          return chain;          return chain;
660      }      }
661    
662      Member _popMemberBlob(const char*& p, const char* end) {      static Member _popMemberBlob(const char*& p, const char* end) {
663          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
664          p   = blob.p;          p   = blob.p;
665          end = blob.end;          end = blob.end;
# Line 574  namespace Serialization { Line 673  namespace Serialization {
673          m.m_type   = _popDataTypeBlob(p, end);          m.m_type   = _popDataTypeBlob(p, end);
674          assert(m.type());          assert(m.type());
675          assert(!m.name().empty());          assert(!m.name().empty());
676          assert(m.uid() != NULL);          assert(m.uid().isValid());
677          return m;          return m;
678      }      }
679    
# Line 594  namespace Serialization { Line 693  namespace Serialization {
693          return members;          return members;
694      }      }
695    
696      void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {      static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
697          const DataType& type = obj.type();          const DataType& type = obj.type();
698          if (type.isPrimitive() && !type.isPointer()) {          if (type.isPrimitive() && !type.isPointer()) {
699              obj.m_data.resize(type.size());              obj.m_data.resize(type.size());
# Line 643  namespace Serialization { Line 742  namespace Serialization {
742          }          }
743      }      }
744    
745      Object _popObjectBlob(const char*& p, const char* end) {      static Object _popObjectBlob(const char*& p, const char* end) {
746          _Blob blob = _decodeBlob(p, end, false);          _Blob blob = _decodeBlob(p, end, false);
747          p   = blob.p;          p   = blob.p;
748          end = blob.end;          end = blob.end;
# Line 695  namespace Serialization { Line 794  namespace Serialization {
794          _popObjectsBlob(p, end);          _popObjectsBlob(p, end);
795          if (!m_allObjects[m_root])          if (!m_allObjects[m_root])
796              throw Exception("Decode Error: Missing declared root object");              throw Exception("Decode Error: Missing declared root object");
797    
798            m_name = _popStringBlob(p, end);
799            m_comment = _popStringBlob(p, end);
800            m_timeCreated = _popTimeBlob(p, end);
801            m_timeModified = _popTimeBlob(p, end);
802      }      }
803    
804      void Archive::decode(const RawData& data) {      void Archive::decode(const RawData& data) {
805          m_rawData = data;          m_rawData = data;
806          m_allObjects.clear();          m_allObjects.clear();
807            m_isModified = false;
808            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
809          const char* p   = (const char*) &data[0];          const char* p   = (const char*) &data[0];
810          const char* end = p + data.size();          const char* end = p + data.size();
811          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 821  namespace Serialization {
821          decode(rawData);          decode(rawData);
822      }      }
823    
824        const RawData& Archive::rawData() {
825            if (m_isModified) encode();
826            return m_rawData;
827        }
828    
829      String Archive::rawDataFormat() const {      String Archive::rawDataFormat() const {
830          return MAGIC_START;          return MAGIC_START;
831      }      }
832    
833        bool Archive::isModified() const {
834            return m_isModified;
835        }
836    
837      void Archive::clear() {      void Archive::clear() {
838          m_allObjects.clear();          m_allObjects.clear();
839          m_operation = OPERATION_NONE;          m_operation = OPERATION_NONE;
840          m_root = NO_UID;          m_root = NO_UID;
841          m_rawData.clear();          m_rawData.clear();
842            m_isModified = false;
843            m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
844        }
845    
846        String Archive::name() const {
847            return m_name;
848        }
849    
850        void Archive::setName(String name) {
851            if (m_name == name) return;
852            m_name = name;
853            m_isModified = true;
854        }
855    
856        String Archive::comment() const {
857            return m_comment;
858        }
859    
860        void Archive::setComment(String comment) {
861            if (m_comment == comment) return;
862            m_comment = comment;
863            m_isModified = true;
864        }
865    
866        static tm _convertTimeStamp(const time_t& time, time_base_t base) {
867            tm* pTm;
868            switch (base) {
869                case LOCAL_TIME:
870                    pTm = localtime(&time);
871                    break;
872                case UTC_TIME:
873                    pTm = gmtime(&time);
874                    break;
875                default:
876                    throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
877            }
878            if (!pTm)
879                throw Exception("Failed assembling time stamp structure");
880            return *pTm;
881        }
882    
883        time_t Archive::timeStampCreated() const {
884            return m_timeCreated;
885        }
886    
887        time_t Archive::timeStampModified() const {
888            return m_timeModified;
889        }
890    
891        tm Archive::dateTimeCreated(time_base_t base) const {
892            return _convertTimeStamp(m_timeCreated, base);
893        }
894    
895        tm Archive::dateTimeModified(time_base_t base) const {
896            return _convertTimeStamp(m_timeModified, base);
897        }
898    
899        void Archive::removeMember(Object& parent, const Member& member) {
900            parent.remove(member);
901            m_isModified = true;
902      }      }
903    
904      void Archive::remove(const Object& obj) {      void Archive::remove(const Object& obj) {
905            //FIXME: Should traverse from root object and remove all members associated with this object
906          if (!obj.uid()) return;          if (!obj.uid()) return;
907          m_allObjects.erase(obj.uid());          m_allObjects.erase(obj.uid());
908            m_isModified = true;
909      }      }
910    
911      Object& Archive::objectByUID(const UID& uid) {      Object& Archive::objectByUID(const UID& uid) {
912          return m_allObjects[uid];          return m_allObjects[uid];
913      }      }
914    
915        void Archive::setEnumValue(Object& object, uint64_t value) {
916            if (!object) return;
917            if (!object.type().isEnum())
918                throw Exception("Not an enum data type");
919            Object* pObject = &object;
920            if (object.type().isPointer()) {
921                Object& obj = objectByUID(object.uid(1));
922                if (!obj) return;
923                pObject = &obj;
924            }
925            const int nativeEnumSize = sizeof(enum operation_t);
926            DataType& type = const_cast<DataType&>( pObject->type() );
927            // original serializer ("sender") might have had a different word size
928            // than this machine, adjust type object in this case
929            if (type.size() != nativeEnumSize) {
930                type.m_size = nativeEnumSize;
931            }
932            pObject->m_data.resize(type.size());
933            void* ptr = &pObject->m_data[0];
934            if (type.size() == 1)
935                *(uint8_t*)ptr = (uint8_t)value;
936            else if (type.size() == 2)
937                *(uint16_t*)ptr = (uint16_t)value;
938            else if (type.size() == 4)
939                *(uint32_t*)ptr = (uint32_t)value;
940            else if (type.size() == 8)
941                *(uint64_t*)ptr = (uint64_t)value;
942            else
943                assert(false /* unknown enum type size */);
944            m_isModified = true;
945        }
946    
947        void Archive::setIntValue(Object& object, int64_t value) {
948            if (!object) return;
949            if (!object.type().isInteger())
950                throw Exception("Not an integer data type");
951            Object* pObject = &object;
952            if (object.type().isPointer()) {
953                Object& obj = objectByUID(object.uid(1));
954                if (!obj) return;
955                pObject = &obj;
956            }
957            const DataType& type = pObject->type();
958            pObject->m_data.resize(type.size());
959            void* ptr = &pObject->m_data[0];
960            if (type.isSigned()) {
961                if (type.size() == 1)
962                    *(int8_t*)ptr = (int8_t)value;
963                else if (type.size() == 2)
964                    *(int16_t*)ptr = (int16_t)value;
965                else if (type.size() == 4)
966                    *(int32_t*)ptr = (int32_t)value;
967                else if (type.size() == 8)
968                    *(int64_t*)ptr = (int64_t)value;
969                else
970                    assert(false /* unknown signed int type size */);
971            } else {
972                if (type.size() == 1)
973                    *(uint8_t*)ptr = (uint8_t)value;
974                else if (type.size() == 2)
975                    *(uint16_t*)ptr = (uint16_t)value;
976                else if (type.size() == 4)
977                    *(uint32_t*)ptr = (uint32_t)value;
978                else if (type.size() == 8)
979                    *(uint64_t*)ptr = (uint64_t)value;
980                else
981                    assert(false /* unknown unsigned int type size */);
982            }
983            m_isModified = true;
984        }
985    
986        void Archive::setRealValue(Object& object, double value) {
987            if (!object) return;
988            if (!object.type().isReal())
989                throw Exception("Not a real data type");
990            Object* pObject = &object;
991            if (object.type().isPointer()) {
992                Object& obj = objectByUID(object.uid(1));
993                if (!obj) return;
994                pObject = &obj;
995            }
996            const DataType& type = pObject->type();
997            pObject->m_data.resize(type.size());
998            void* ptr = &pObject->m_data[0];
999            if (type.size() == sizeof(float))
1000                *(float*)ptr = (float)value;
1001            else if (type.size() == sizeof(double))
1002                *(double*)ptr = (double)value;
1003            else
1004                assert(false /* unknown real type size */);
1005            m_isModified = true;
1006        }
1007    
1008        void Archive::setBoolValue(Object& object, bool value) {
1009            if (!object) return;
1010            if (!object.type().isBool())
1011                throw Exception("Not a bool data type");
1012            Object* pObject = &object;
1013            if (object.type().isPointer()) {
1014                Object& obj = objectByUID(object.uid(1));
1015                if (!obj) return;
1016                pObject = &obj;
1017            }
1018            const DataType& type = pObject->type();
1019            pObject->m_data.resize(type.size());
1020            bool* ptr = (bool*)&pObject->m_data[0];
1021            *ptr = value;
1022            m_isModified = true;
1023        }
1024    
1025        void Archive::setAutoValue(Object& object, String value) {
1026            if (!object) return;
1027            const DataType& type = object.type();
1028            if (type.isInteger())
1029                setIntValue(object, atoll(value.c_str()));
1030            else if (type.isReal())
1031                setRealValue(object, atof(value.c_str()));
1032            else if (type.isBool())
1033                setBoolValue(object, atof(value.c_str()));
1034            else if (type.isEnum())
1035                setEnumValue(object, atoll(value.c_str()));
1036            else
1037                throw Exception("Not a primitive data type");
1038        }
1039    
1040        String Archive::valueAsString(const Object& object) {
1041            if (!object)
1042                throw Exception("Invalid object");
1043            if (object.type().isClass())
1044                throw Exception("Object is class type");
1045            const Object* pObject = &object;
1046            if (object.type().isPointer()) {
1047                const Object& obj = objectByUID(object.uid(1));
1048                if (!obj) return "";
1049                pObject = &obj;
1050            }
1051            return _primitiveObjectValueToString(*pObject);
1052        }
1053    
1054        int64_t Archive::valueAsInt(const Object& object) {
1055            if (!object)
1056                throw Exception("Invalid object");
1057            if (!object.type().isInteger() && !object.type().isEnum())
1058                throw Exception("Object is neither an integer nor an enum");
1059            const Object* pObject = &object;
1060            if (object.type().isPointer()) {
1061                const Object& obj = objectByUID(object.uid(1));
1062                if (!obj) return 0;
1063                pObject = &obj;
1064            }
1065            return _primitiveObjectValueToNumber<int64_t>(*pObject);
1066        }
1067    
1068        double Archive::valueAsReal(const Object& object) {
1069            if (!object)
1070                throw Exception("Invalid object");
1071            if (!object.type().isReal())
1072                throw Exception("Object is not an real type");
1073            const Object* pObject = &object;
1074            if (object.type().isPointer()) {
1075                const Object& obj = objectByUID(object.uid(1));
1076                if (!obj) return 0;
1077                pObject = &obj;
1078            }
1079            return _primitiveObjectValueToNumber<double>(*pObject);
1080        }
1081    
1082        bool Archive::valueAsBool(const Object& object) {
1083            if (!object)
1084                throw Exception("Invalid object");
1085            if (!object.type().isBool())
1086                throw Exception("Object is not a bool");
1087            const Object* pObject = &object;
1088            if (object.type().isPointer()) {
1089                const Object& obj = objectByUID(object.uid(1));
1090                if (!obj) return 0;
1091                pObject = &obj;
1092            }
1093            return _primitiveObjectValueToNumber<bool>(*pObject);
1094        }
1095    
1096      // *************** Archive::Syncer ***************      // *************** Archive::Syncer ***************
1097      // *      // *
1098    

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

  ViewVC Help
Powered by ViewVC