libgig  4.2.0
Serialization.cpp
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017-2019 Christian Schoenebeck *
4  * <cuse@users.sourceforge.net> *
5  * *
6  * This library is part of libgig. *
7  * *
8  * This library is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  ***************************************************************************/
23 
24 // enable implementation specific declarations in Serialization.h required to
25 // build this C++ unit, which should be ignored in the public API though
26 #define LIBGIG_SERIALIZATION_INTERNAL 1
27 
28 #include "Serialization.h"
29 
30 #include <iostream>
31 #include <assert.h>
32 #include <string.h> // for memcpy()
33 #include <stdlib.h> // for atof()
34 #ifdef _MSC_VER
35 # include <windows.h>
36 # include <dbghelp.h>
37 #else
38 # include <cxxabi.h>
39 #endif
40 #include "helper.h"
41 
42 #define LIBGIG_EPOCH_TIME ((time_t)0)
43 
44 namespace Serialization {
45 
46  // *************** DataType ***************
47  // *
48 
49  static UID _createNullUID() {
50  const UID uid = { NULL, 0 };
51  return uid;
52  }
53 
54  const UID NO_UID = _createNullUID();
55 
67  bool UID::isValid() const {
68  return id != NULL && id != (void*)-1 && size;
69  }
70 
71  // *************** DataType ***************
72  // *
73 
84  m_size = 0;
85  m_isPointer = false;
86  }
87 
88  DataType::DataType(bool isPointer, int size, String baseType, String customType) {
89  m_size = size;
90  m_isPointer = isPointer;
91  m_baseTypeName = baseType;
92  m_customTypeName = customType;
93  }
94 
105  bool DataType::isValid() const {
106  return m_size;
107  }
108 
114  bool DataType::isPointer() const {
115  return m_isPointer;
116  }
117 
138  bool DataType::isClass() const {
139  return m_baseTypeName == "class";
140  }
141 
162  bool DataType::isPrimitive() const {
163  return !isClass();
164  }
165 
180  bool DataType::isInteger() const {
181  return m_baseTypeName.substr(0, 3) == "int" ||
182  m_baseTypeName.substr(0, 4) == "uint";
183  }
184 
197  bool DataType::isReal() const {
198  return m_baseTypeName.substr(0, 4) == "real";
199  }
200 
212  bool DataType::isBool() const {
213  return m_baseTypeName == "bool";
214  }
215 
227  bool DataType::isEnum() const {
228  return m_baseTypeName == "enum";
229  }
230 
244  bool DataType::isSigned() const {
245  return m_baseTypeName.substr(0, 3) == "int" ||
246  isReal();
247  }
248 
267  bool DataType::operator==(const DataType& other) const {
268  return m_baseTypeName == other.m_baseTypeName &&
269  m_customTypeName == other.m_customTypeName &&
270  (m_size == other.m_size || (isClass() && other.isClass())) &&
271  m_isPointer == other.m_isPointer;
272  }
273 
279  bool DataType::operator!=(const DataType& other) const {
280  return !operator==(other);
281  }
282 
294  bool DataType::operator<(const DataType& other) const {
295  return m_baseTypeName < other.m_baseTypeName ||
296  (m_baseTypeName == other.m_baseTypeName &&
297  (m_customTypeName < other.m_customTypeName ||
298  (m_customTypeName == other.m_customTypeName &&
299  (m_size < other.m_size ||
300  (m_size == other.m_size &&
301  m_isPointer < other.m_isPointer)))));
302  }
303 
315  bool DataType::operator>(const DataType& other) const {
316  return !(operator==(other) || operator<(other));
317  }
318 
333  String DataType::asLongDescr() const {
334  String s = m_baseTypeName;
335  if (!m_customTypeName.empty())
336  s += " " + customTypeName(true);
337  if (isPointer())
338  s += " pointer";
339  return s;
340  }
341 
371  String DataType::baseTypeName() const {
372  return m_baseTypeName;
373  }
374 
411  String DataType::customTypeName(bool demangle) const {
412  if (!demangle) return m_customTypeName;
413 #ifdef _MSC_VER
414  const size_t MAXLENGTH = 1024;
415  char result[MAXLENGTH];
416 
417  //FIXME: calling UnDecorateSymbolName() is not thread safe!
418  //Skip the first char
419  size_t size = UnDecorateSymbolName(m_customTypeName.c_str() +1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
420  if (size)
421  {
422  return result;
423  }
424  return m_customTypeName;
425 #else
426  int status;
427  char* result =
428  abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
429  String sResult = result;
430  free(result);
431  return (status == 0) ? sResult : m_customTypeName;
432 #endif
433  }
434 
435  // *************** Member ***************
436  // *
437 
451  m_uid = NO_UID;
452  m_offset = 0;
453  }
454 
455  Member::Member(String name, UID uid, size_t offset, DataType type) {
456  m_name = name;
457  m_uid = uid;
458  m_offset = offset;
459  m_type = type;
460  }
461 
476  UID Member::uid() const {
477  return m_uid;
478  }
479 
500  String Member::name() const {
501  return m_name;
502  }
503 
538  size_t Member::offset() const {
539  return m_offset;
540  }
541 
546  const DataType& Member::type() const {
547  return m_type;
548  }
549 
560  bool Member::isValid() const {
561  return m_uid && !m_name.empty() && m_type;
562  }
563 
572  bool Member::operator==(const Member& other) const {
573  return m_uid == other.m_uid &&
574  m_offset == other.m_offset &&
575  m_name == other.m_name &&
576  m_type == other.m_type;
577  }
578 
584  bool Member::operator!=(const Member& other) const {
585  return !operator==(other);
586  }
587 
600  bool Member::operator<(const Member& other) const {
601  return m_uid < other.m_uid ||
602  (m_uid == other.m_uid &&
603  (m_offset < other.m_offset ||
604  (m_offset == other.m_offset &&
605  (m_name < other.m_name ||
606  (m_name == other.m_name &&
607  m_type < other.m_type)))));
608  }
609 
622  bool Member::operator>(const Member& other) const {
623  return !(operator==(other) || operator<(other));
624  }
625 
626  // *************** Object ***************
627  // *
628 
641  m_version = 0;
642  m_minVersion = 0;
643  }
644 
662  Object::Object(UIDChain uidChain, DataType type) {
663  m_type = type;
664  m_uid = uidChain;
665  m_version = 0;
666  m_minVersion = 0;
667  //m_data.resize(type.size());
668  }
669 
680  bool Object::isValid() const {
681  return m_type && !m_uid.empty();
682  }
683 
695  UID Object::uid(int index) const {
696  return (index < m_uid.size()) ? m_uid[index] : NO_UID;
697  }
698 
705  const UIDChain& Object::uidChain() const {
706  return m_uid;
707  }
708 
714  const DataType& Object::type() const {
715  return m_type;
716  }
717 
740  const RawData& Object::rawData() const {
741  return m_data;
742  }
743 
754  return m_version;
755  }
756 
769  return m_minVersion;
770  }
771 
804  std::vector<Member>& Object::members() {
805  return m_members;
806  }
807 
814  const std::vector<Member>& Object::members() const {
815  return m_members;
816  }
817 
828  bool Object::operator==(const Object& other) const {
829  // ignoring all other member variables here
830  // (since UID stands for "unique" ;-) )
831  return m_uid == other.m_uid &&
832  m_type == other.m_type;
833  }
834 
840  bool Object::operator!=(const Object& other) const {
841  return !operator==(other);
842  }
843 
856  bool Object::operator<(const Object& other) const {
857  // ignoring all other member variables here
858  // (since UID stands for "unique" ;-) )
859  return m_uid < other.m_uid ||
860  (m_uid == other.m_uid &&
861  m_type < other.m_type);
862  }
863 
876  bool Object::operator>(const Object& other) const {
877  return !(operator==(other) || operator<(other));
878  }
879 
898  bool Object::isVersionCompatibleTo(const Object& other) const {
899  if (this->version() == other.version())
900  return true;
901  if (this->version() > other.version())
902  return this->minVersion() <= other.version();
903  else
904  return other.minVersion() <= this->version();
905  }
906 
907  void Object::setVersion(Version v) {
908  m_version = v;
909  }
910 
911  void Object::setMinVersion(Version v) {
912  m_minVersion = v;
913  }
914 
944  Member Object::memberNamed(String name) const {
945  for (int i = 0; i < m_members.size(); ++i)
946  if (m_members[i].name() == name)
947  return m_members[i];
948  return Member();
949  }
950 
965  Member Object::memberByUID(const UID& uid) const {
966  if (!uid) return Member();
967  for (int i = 0; i < m_members.size(); ++i)
968  if (m_members[i].uid() == uid)
969  return m_members[i];
970  return Member();
971  }
972 
973  void Object::remove(const Member& member) {
974  for (int i = 0; i < m_members.size(); ++i) {
975  if (m_members[i] == member) {
976  m_members.erase(m_members.begin() + i);
977  return;
978  }
979  }
980  }
981 
997  std::vector<Member> Object::membersOfType(const DataType& type) const {
998  std::vector<Member> v;
999  for (int i = 0; i < m_members.size(); ++i) {
1000  const Member& member = m_members[i];
1001  if (member.type() == type)
1002  v.push_back(member);
1003  }
1004  return v;
1005  }
1006 
1038  int Object::sequenceIndexOf(const Member& member) const {
1039  for (int i = 0; i < m_members.size(); ++i)
1040  if (m_members[i] == member)
1041  return i;
1042  return -1;
1043  }
1044 
1045  // *************** Archive ***************
1046  // *
1047 
1067  m_operation = OPERATION_NONE;
1068  m_root = NO_UID;
1069  m_isModified = false;
1070  m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1071  }
1072 
1088  Archive::Archive(const RawData& data) {
1089  m_operation = OPERATION_NONE;
1090  m_root = NO_UID;
1091  m_isModified = false;
1092  m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1093  decode(m_rawData);
1094  }
1095 
1116  Archive::Archive(const uint8_t* data, size_t size) {
1117  m_operation = OPERATION_NONE;
1118  m_root = NO_UID;
1119  m_isModified = false;
1120  m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1121  decode(data, size);
1122  }
1123 
1124  Archive::~Archive() {
1125  }
1126 
1138  return m_allObjects[m_root];
1139  }
1140 
1141  static String _encodeBlob(String data) {
1142  return ToString(data.length()) + ":" + data;
1143  }
1144 
1145  static String _encode(const UID& uid) {
1146  String s;
1147  s += _encodeBlob(ToString(size_t(uid.id)));
1148  s += _encodeBlob(ToString(size_t(uid.size)));
1149  return _encodeBlob(s);
1150  }
1151 
1152  static String _encode(const time_t& time) {
1153  return _encodeBlob(ToString(time));
1154  }
1155 
1156  static String _encode(const DataType& type) {
1157  String s;
1158  s += _encodeBlob(type.baseTypeName());
1159  s += _encodeBlob(type.customTypeName());
1160  s += _encodeBlob(ToString(type.size()));
1161  s += _encodeBlob(ToString(type.isPointer()));
1162  return _encodeBlob(s);
1163  }
1164 
1165  static String _encode(const UIDChain& chain) {
1166  String s;
1167  for (int i = 0; i < chain.size(); ++i)
1168  s += _encode(chain[i]);
1169  return _encodeBlob(s);
1170  }
1171 
1172  static String _encode(const Member& member) {
1173  String s;
1174  s += _encode(member.uid());
1175  s += _encodeBlob(ToString(member.offset()));
1176  s += _encodeBlob(member.name());
1177  s += _encode(member.type());
1178  return _encodeBlob(s);
1179  }
1180 
1181  static String _encode(const std::vector<Member>& members) {
1182  String s;
1183  for (int i = 0; i < members.size(); ++i)
1184  s += _encode(members[i]);
1185  return _encodeBlob(s);
1186  }
1187 
1188  static String _primitiveObjectValueToString(const Object& obj) {
1189  String s;
1190  const DataType& type = obj.type();
1191  const ID& id = obj.uid().id;
1192  void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
1193  if (!obj.m_data.empty())
1194  assert(type.size() == obj.m_data.size());
1195  if (type.isPrimitive() && !type.isPointer()) {
1196  if (type.isInteger() || type.isEnum()) {
1197  if (type.isSigned()) {
1198  if (type.size() == 1)
1199  s = ToString((int16_t)*(int8_t*)ptr); // int16_t: prevent ToString() to render an ASCII character
1200  else if (type.size() == 2)
1201  s = ToString(*(int16_t*)ptr);
1202  else if (type.size() == 4)
1203  s = ToString(*(int32_t*)ptr);
1204  else if (type.size() == 8)
1205  s = ToString(*(int64_t*)ptr);
1206  else
1207  assert(false /* unknown signed int type size */);
1208  } else {
1209  if (type.size() == 1)
1210  s = ToString((uint16_t)*(uint8_t*)ptr); // uint16_t: prevent ToString() to render an ASCII character
1211  else if (type.size() == 2)
1212  s = ToString(*(uint16_t*)ptr);
1213  else if (type.size() == 4)
1214  s = ToString(*(uint32_t*)ptr);
1215  else if (type.size() == 8)
1216  s = ToString(*(uint64_t*)ptr);
1217  else
1218  assert(false /* unknown unsigned int type size */);
1219  }
1220  } else if (type.isReal()) {
1221  if (type.size() == sizeof(float))
1222  s = ToString(*(float*)ptr);
1223  else if (type.size() == sizeof(double))
1224  s = ToString(*(double*)ptr);
1225  else
1226  assert(false /* unknown floating point type */);
1227  } else if (type.isBool()) {
1228  s = ToString(*(bool*)ptr);
1229  } else {
1230  assert(false /* unknown primitive type */);
1231  }
1232 
1233  }
1234  return s;
1235  }
1236 
1237  template<typename T>
1238  static T _primitiveObjectValueToNumber(const Object& obj) {
1239  T value = 0;
1240  const DataType& type = obj.type();
1241  const ID& id = obj.uid().id;
1242  void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
1243  if (!obj.m_data.empty())
1244  assert(type.size() == obj.m_data.size());
1245  if (type.isPrimitive() && !type.isPointer()) {
1246  if (type.isInteger() || type.isEnum()) {
1247  if (type.isSigned()) {
1248  if (type.size() == 1)
1249  value = (T)*(int8_t*)ptr;
1250  else if (type.size() == 2)
1251  value = (T)*(int16_t*)ptr;
1252  else if (type.size() == 4)
1253  value = (T)*(int32_t*)ptr;
1254  else if (type.size() == 8)
1255  value = (T)*(int64_t*)ptr;
1256  else
1257  assert(false /* unknown signed int type size */);
1258  } else {
1259  if (type.size() == 1)
1260  value = (T)*(uint8_t*)ptr;
1261  else if (type.size() == 2)
1262  value = (T)*(uint16_t*)ptr;
1263  else if (type.size() == 4)
1264  value = (T)*(uint32_t*)ptr;
1265  else if (type.size() == 8)
1266  value = (T)*(uint64_t*)ptr;
1267  else
1268  assert(false /* unknown unsigned int type size */);
1269  }
1270  } else if (type.isReal()) {
1271  if (type.size() == sizeof(float))
1272  value = (T)*(float*)ptr;
1273  else if (type.size() == sizeof(double))
1274  value = (T)*(double*)ptr;
1275  else
1276  assert(false /* unknown floating point type */);
1277  } else if (type.isBool()) {
1278  value = (T)*(bool*)ptr;
1279  } else {
1280  assert(false /* unknown primitive type */);
1281  }
1282  }
1283  return value;
1284  }
1285 
1286  static String _encodePrimitiveValue(const Object& obj) {
1287  return _encodeBlob( _primitiveObjectValueToString(obj) );
1288  }
1289 
1290  static String _encode(const Object& obj) {
1291  String s;
1292  s += _encode(obj.type());
1293  s += _encodeBlob(ToString(obj.version()));
1294  s += _encodeBlob(ToString(obj.minVersion()));
1295  s += _encode(obj.uidChain());
1296  s += _encode(obj.members());
1297  s += _encodePrimitiveValue(obj);
1298  return _encodeBlob(s);
1299  }
1300 
1301  String _encode(const Archive::ObjectPool& objects) {
1302  String s;
1303  for (Archive::ObjectPool::const_iterator itObject = objects.begin();
1304  itObject != objects.end(); ++itObject)
1305  {
1306  const Object& obj = itObject->second;
1307  s += _encode(obj);
1308  }
1309  return _encodeBlob(s);
1310  }
1311 
1312  #define MAGIC_START "Srx1v"
1313  #define ENCODING_FORMAT_MINOR_VERSION 0
1314 
1315  String Archive::_encodeRootBlob() {
1316  String s;
1317  s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
1318  s += _encode(m_root);
1319  s += _encode(m_allObjects);
1320  s += _encodeBlob(m_name);
1321  s += _encodeBlob(m_comment);
1322  s += _encode(m_timeCreated);
1323  s += _encode(m_timeModified);
1324  return _encodeBlob(s);
1325  }
1326 
1327  void Archive::encode() {
1328  m_rawData.clear();
1329  String s = MAGIC_START;
1330  m_timeModified = time(NULL);
1331  if (m_timeCreated == LIBGIG_EPOCH_TIME)
1332  m_timeCreated = m_timeModified;
1333  s += _encodeRootBlob();
1334  m_rawData.resize(s.length() + 1);
1335  memcpy(&m_rawData[0], &s[0], s.length() + 1);
1336  m_isModified = false;
1337  }
1338 
1339  struct _Blob {
1340  const char* p;
1341  const char* end;
1342  };
1343 
1344  static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
1345  if (!bThrow && p >= end) {
1346  const _Blob blob = { p, end };
1347  return blob;
1348  }
1349  size_t sz = 0;
1350  for (; true; ++p) {
1351  if (p >= end)
1352  throw Exception("Decode Error: Missing blob");
1353  const char& c = *p;
1354  if (c == ':') break;
1355  if (c < '0' || c > '9')
1356  throw Exception("Decode Error: Missing blob size");
1357  sz *= 10;
1358  sz += size_t(c - '0');
1359  }
1360  ++p;
1361  if (p + sz > end)
1362  throw Exception("Decode Error: Premature end of blob");
1363  const _Blob blob = { p, p + sz };
1364  return blob;
1365  }
1366 
1367  template<typename T_int>
1368  static T_int _popIntBlob(const char*& p, const char* end) {
1369  _Blob blob = _decodeBlob(p, end);
1370  p = blob.p;
1371  end = blob.end;
1372 
1373  T_int sign = 1;
1374  T_int i = 0;
1375  if (p >= end)
1376  throw Exception("Decode Error: premature end of int blob");
1377  if (*p == '-') {
1378  sign = -1;
1379  ++p;
1380  }
1381  for (; p < end; ++p) {
1382  const char& c = *p;
1383  if (c < '0' || c > '9')
1384  throw Exception("Decode Error: Invalid int blob format");
1385  i *= 10;
1386  i += size_t(c - '0');
1387  }
1388  return i * sign;
1389  }
1390 
1391  template<typename T_int>
1392  static void _popIntBlob(const char*& p, const char* end, RawData& rawData) {
1393  const T_int i = _popIntBlob<T_int>(p, end);
1394  *(T_int*)&rawData[0] = i;
1395  }
1396 
1397  template<typename T_real>
1398  static T_real _popRealBlob(const char*& p, const char* end) {
1399  _Blob blob = _decodeBlob(p, end);
1400  p = blob.p;
1401  end = blob.end;
1402 
1403  if (p >= end || (end - p) < 1)
1404  throw Exception("Decode Error: premature end of real blob");
1405 
1406  String s(p, size_t(end - p));
1407 
1408  T_real r;
1409  if (sizeof(T_real) <= sizeof(double))
1410  r = atof(s.c_str());
1411  else
1412  assert(false /* unknown real type */);
1413 
1414  p += s.length();
1415 
1416  return r;
1417  }
1418 
1419  template<typename T_real>
1420  static void _popRealBlob(const char*& p, const char* end, RawData& rawData) {
1421  const T_real r = _popRealBlob<T_real>(p, end);
1422  *(T_real*)&rawData[0] = r;
1423  }
1424 
1425  static String _popStringBlob(const char*& p, const char* end) {
1426  _Blob blob = _decodeBlob(p, end);
1427  p = blob.p;
1428  end = blob.end;
1429  if (end - p < 0)
1430  throw Exception("Decode Error: missing String blob");
1431  String s;
1432  const size_t sz = end - p;
1433  s.resize(sz);
1434  memcpy(&s[0], p, sz);
1435  p += sz;
1436  return s;
1437  }
1438 
1439  static time_t _popTimeBlob(const char*& p, const char* end) {
1440  const uint64_t i = _popIntBlob<uint64_t>(p, end);
1441  return (time_t) i;
1442  }
1443 
1444  static DataType _popDataTypeBlob(const char*& p, const char* end) {
1445  _Blob blob = _decodeBlob(p, end);
1446  p = blob.p;
1447  end = blob.end;
1448 
1449  DataType type;
1450  type.m_baseTypeName = _popStringBlob(p, end);
1451  type.m_customTypeName = _popStringBlob(p, end);
1452  type.m_size = _popIntBlob<int>(p, end);
1453  type.m_isPointer = _popIntBlob<bool>(p, end);
1454  return type;
1455  }
1456 
1457  static UID _popUIDBlob(const char*& p, const char* end) {
1458  _Blob blob = _decodeBlob(p, end);
1459  p = blob.p;
1460  end = blob.end;
1461 
1462  if (p >= end)
1463  throw Exception("Decode Error: premature end of UID blob");
1464 
1465  const ID id = (ID) _popIntBlob<size_t>(p, end);
1466  const size_t size = _popIntBlob<size_t>(p, end);
1467 
1468  const UID uid = { id, size };
1469  return uid;
1470  }
1471 
1472  static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
1473  _Blob blob = _decodeBlob(p, end);
1474  p = blob.p;
1475  end = blob.end;
1476 
1477  UIDChain chain;
1478  while (p < end) {
1479  const UID uid = _popUIDBlob(p, end);
1480  chain.push_back(uid);
1481  }
1482  assert(!chain.empty());
1483  return chain;
1484  }
1485 
1486  static Member _popMemberBlob(const char*& p, const char* end) {
1487  _Blob blob = _decodeBlob(p, end, false);
1488  p = blob.p;
1489  end = blob.end;
1490 
1491  Member m;
1492  if (p >= end) return m;
1493 
1494  m.m_uid = _popUIDBlob(p, end);
1495  m.m_offset = _popIntBlob<size_t>(p, end);
1496  m.m_name = _popStringBlob(p, end);
1497  m.m_type = _popDataTypeBlob(p, end);
1498  assert(m.type());
1499  assert(!m.name().empty());
1500  assert(m.uid().isValid());
1501  return m;
1502  }
1503 
1504  static std::vector<Member> _popMembersBlob(const char*& p, const char* end) {
1505  _Blob blob = _decodeBlob(p, end, false);
1506  p = blob.p;
1507  end = blob.end;
1508 
1509  std::vector<Member> members;
1510  while (p < end) {
1511  const Member member = _popMemberBlob(p, end);
1512  if (member)
1513  members.push_back(member);
1514  else
1515  break;
1516  }
1517  return members;
1518  }
1519 
1520  static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
1521  const DataType& type = obj.type();
1522  if (type.isPrimitive() && !type.isPointer()) {
1523  obj.m_data.resize(type.size());
1524  if (type.isInteger() || type.isEnum()) {
1525  if (type.isSigned()) {
1526  if (type.size() == 1)
1527  _popIntBlob<int8_t>(p, end, obj.m_data);
1528  else if (type.size() == 2)
1529  _popIntBlob<int16_t>(p, end, obj.m_data);
1530  else if (type.size() == 4)
1531  _popIntBlob<int32_t>(p, end, obj.m_data);
1532  else if (type.size() == 8)
1533  _popIntBlob<int64_t>(p, end, obj.m_data);
1534  else
1535  assert(false /* unknown signed int type size */);
1536  } else {
1537  if (type.size() == 1)
1538  _popIntBlob<uint8_t>(p, end, obj.m_data);
1539  else if (type.size() == 2)
1540  _popIntBlob<uint16_t>(p, end, obj.m_data);
1541  else if (type.size() == 4)
1542  _popIntBlob<uint32_t>(p, end, obj.m_data);
1543  else if (type.size() == 8)
1544  _popIntBlob<uint64_t>(p, end, obj.m_data);
1545  else
1546  assert(false /* unknown unsigned int type size */);
1547  }
1548  } else if (type.isReal()) {
1549  if (type.size() == sizeof(float))
1550  _popRealBlob<float>(p, end, obj.m_data);
1551  else if (type.size() == sizeof(double))
1552  _popRealBlob<double>(p, end, obj.m_data);
1553  else
1554  assert(false /* unknown floating point type */);
1555  } else if (type.isBool()) {
1556  _popIntBlob<uint8_t>(p, end, obj.m_data);
1557  } else {
1558  assert(false /* unknown primitive type */);
1559  }
1560 
1561  } else {
1562  // don't whine if the empty blob was not added on encoder side
1563  _Blob blob = _decodeBlob(p, end, false);
1564  p = blob.p;
1565  end = blob.end;
1566  }
1567  }
1568 
1569  static Object _popObjectBlob(const char*& p, const char* end) {
1570  _Blob blob = _decodeBlob(p, end, false);
1571  p = blob.p;
1572  end = blob.end;
1573 
1574  Object obj;
1575  if (p >= end) return obj;
1576 
1577  obj.m_type = _popDataTypeBlob(p, end);
1578  obj.m_version = _popIntBlob<Version>(p, end);
1579  obj.m_minVersion = _popIntBlob<Version>(p, end);
1580  obj.m_uid = _popUIDChainBlob(p, end);
1581  obj.m_members = _popMembersBlob(p, end);
1582  _popPrimitiveValue(p, end, obj);
1583  assert(obj.type());
1584  return obj;
1585  }
1586 
1587  void Archive::_popObjectsBlob(const char*& p, const char* end) {
1588  _Blob blob = _decodeBlob(p, end, false);
1589  p = blob.p;
1590  end = blob.end;
1591 
1592  if (p >= end)
1593  throw Exception("Decode Error: Premature end of objects blob");
1594 
1595  while (true) {
1596  const Object obj = _popObjectBlob(p, end);
1597  if (!obj) break;
1598  m_allObjects[obj.uid()] = obj;
1599  }
1600  }
1601 
1602  void Archive::_popRootBlob(const char*& p, const char* end) {
1603  _Blob blob = _decodeBlob(p, end, false);
1604  p = blob.p;
1605  end = blob.end;
1606 
1607  if (p >= end)
1608  throw Exception("Decode Error: Premature end of root blob");
1609 
1610  // just in case this encoding format will be extended in future
1611  // (currently not used)
1612  const int formatMinorVersion = _popIntBlob<int>(p, end);
1613 
1614  m_root = _popUIDBlob(p, end);
1615  if (!m_root)
1616  throw Exception("Decode Error: No root object");
1617 
1618  _popObjectsBlob(p, end);
1619  if (!m_allObjects[m_root])
1620  throw Exception("Decode Error: Missing declared root object");
1621 
1622  m_name = _popStringBlob(p, end);
1623  m_comment = _popStringBlob(p, end);
1624  m_timeCreated = _popTimeBlob(p, end);
1625  m_timeModified = _popTimeBlob(p, end);
1626  }
1627 
1643  void Archive::decode(const RawData& data) {
1644  m_rawData = data;
1645  m_allObjects.clear();
1646  m_isModified = false;
1647  m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1648  const char* p = (const char*) &data[0];
1649  const char* end = p + data.size();
1650  if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
1651  throw Exception("Decode Error: Magic start missing!");
1652  p += strlen(MAGIC_START);
1653  _popRootBlob(p, end);
1654  }
1655 
1676  void Archive::decode(const uint8_t* data, size_t size) {
1677  RawData rawData;
1678  rawData.resize(size);
1679  memcpy(&rawData[0], data, size);
1680  decode(rawData);
1681  }
1682 
1699  if (m_isModified) encode();
1700  return m_rawData;
1701  }
1702 
1708  String Archive::rawDataFormat() const {
1709  return MAGIC_START;
1710  }
1711 
1726  bool Archive::isModified() const {
1727  return m_isModified;
1728  }
1729 
1736  m_allObjects.clear();
1737  m_operation = OPERATION_NONE;
1738  m_root = NO_UID;
1739  m_rawData.clear();
1740  m_isModified = false;
1741  m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1742  }
1743 
1751  String Archive::name() const {
1752  return m_name;
1753  }
1754 
1764  void Archive::setName(String name) {
1765  if (m_name == name) return;
1766  m_name = name;
1767  m_isModified = true;
1768  }
1769 
1777  String Archive::comment() const {
1778  return m_comment;
1779  }
1780 
1790  void Archive::setComment(String comment) {
1791  if (m_comment == comment) return;
1792  m_comment = comment;
1793  m_isModified = true;
1794  }
1795 
1796  static tm _convertTimeStamp(const time_t& time, time_base_t base) {
1797  tm* pTm;
1798  switch (base) {
1799  case LOCAL_TIME:
1800  pTm = localtime(&time);
1801  break;
1802  case UTC_TIME:
1803  pTm = gmtime(&time);
1804  break;
1805  default:
1806  throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
1807  }
1808  if (!pTm)
1809  throw Exception("Failed assembling time stamp structure");
1810  return *pTm;
1811  }
1812 
1818  time_t Archive::timeStampCreated() const {
1819  return m_timeCreated;
1820  }
1821 
1828  return m_timeModified;
1829  }
1830 
1842  return _convertTimeStamp(m_timeCreated, base);
1843  }
1844 
1856  return _convertTimeStamp(m_timeModified, base);
1857  }
1858 
1876  void Archive::removeMember(Object& parent, const Member& member) {
1877  parent.remove(member);
1878  m_isModified = true;
1879  }
1880 
1896  void Archive::remove(const Object& obj) {
1897  //FIXME: Should traverse from root object and remove all members associated with this object
1898  if (!obj.uid()) return;
1899  m_allObjects.erase(obj.uid());
1900  m_isModified = true;
1901  }
1902 
1915  return m_allObjects[uid];
1916  }
1917 
1929  if (!object) return;
1930  object.setVersion(v);
1931  m_isModified = true;
1932  }
1933 
1945  if (!object) return;
1946  object.setMinVersion(v);
1947  m_isModified = true;
1948  }
1949 
1958  void Archive::setEnumValue(Object& object, uint64_t value) {
1959  if (!object) return;
1960  if (!object.type().isEnum())
1961  throw Exception("Not an enum data type");
1962  Object* pObject = &object;
1963  if (object.type().isPointer()) {
1964  Object& obj = objectByUID(object.uid(1));
1965  if (!obj) return;
1966  pObject = &obj;
1967  }
1968  const int nativeEnumSize = sizeof(enum operation_t);
1969  DataType& type = const_cast<DataType&>( pObject->type() );
1970  // original serializer ("sender") might have had a different word size
1971  // than this machine, adjust type object in this case
1972  if (type.size() != nativeEnumSize) {
1973  type.m_size = nativeEnumSize;
1974  }
1975  pObject->m_data.resize(type.size());
1976  void* ptr = &pObject->m_data[0];
1977  if (type.size() == 1)
1978  *(uint8_t*)ptr = (uint8_t)value;
1979  else if (type.size() == 2)
1980  *(uint16_t*)ptr = (uint16_t)value;
1981  else if (type.size() == 4)
1982  *(uint32_t*)ptr = (uint32_t)value;
1983  else if (type.size() == 8)
1984  *(uint64_t*)ptr = (uint64_t)value;
1985  else
1986  assert(false /* unknown enum type size */);
1987  m_isModified = true;
1988  }
1989 
2000  void Archive::setIntValue(Object& object, int64_t value) {
2001  if (!object) return;
2002  if (!object.type().isInteger())
2003  throw Exception("Not an integer data type");
2004  Object* pObject = &object;
2005  if (object.type().isPointer()) {
2006  Object& obj = objectByUID(object.uid(1));
2007  if (!obj) return;
2008  pObject = &obj;
2009  }
2010  const DataType& type = pObject->type();
2011  pObject->m_data.resize(type.size());
2012  void* ptr = &pObject->m_data[0];
2013  if (type.isSigned()) {
2014  if (type.size() == 1)
2015  *(int8_t*)ptr = (int8_t)value;
2016  else if (type.size() == 2)
2017  *(int16_t*)ptr = (int16_t)value;
2018  else if (type.size() == 4)
2019  *(int32_t*)ptr = (int32_t)value;
2020  else if (type.size() == 8)
2021  *(int64_t*)ptr = (int64_t)value;
2022  else
2023  assert(false /* unknown signed int type size */);
2024  } else {
2025  if (type.size() == 1)
2026  *(uint8_t*)ptr = (uint8_t)value;
2027  else if (type.size() == 2)
2028  *(uint16_t*)ptr = (uint16_t)value;
2029  else if (type.size() == 4)
2030  *(uint32_t*)ptr = (uint32_t)value;
2031  else if (type.size() == 8)
2032  *(uint64_t*)ptr = (uint64_t)value;
2033  else
2034  assert(false /* unknown unsigned int type size */);
2035  }
2036  m_isModified = true;
2037  }
2038 
2050  void Archive::setRealValue(Object& object, double value) {
2051  if (!object) return;
2052  if (!object.type().isReal())
2053  throw Exception("Not a real data type");
2054  Object* pObject = &object;
2055  if (object.type().isPointer()) {
2056  Object& obj = objectByUID(object.uid(1));
2057  if (!obj) return;
2058  pObject = &obj;
2059  }
2060  const DataType& type = pObject->type();
2061  pObject->m_data.resize(type.size());
2062  void* ptr = &pObject->m_data[0];
2063  if (type.size() == sizeof(float))
2064  *(float*)ptr = (float)value;
2065  else if (type.size() == sizeof(double))
2066  *(double*)ptr = (double)value;
2067  else
2068  assert(false /* unknown real type size */);
2069  m_isModified = true;
2070  }
2071 
2080  void Archive::setBoolValue(Object& object, bool value) {
2081  if (!object) return;
2082  if (!object.type().isBool())
2083  throw Exception("Not a bool data type");
2084  Object* pObject = &object;
2085  if (object.type().isPointer()) {
2086  Object& obj = objectByUID(object.uid(1));
2087  if (!obj) return;
2088  pObject = &obj;
2089  }
2090  const DataType& type = pObject->type();
2091  pObject->m_data.resize(type.size());
2092  bool* ptr = (bool*)&pObject->m_data[0];
2093  *ptr = value;
2094  m_isModified = true;
2095  }
2096 
2110  void Archive::setAutoValue(Object& object, String value) {
2111  if (!object) return;
2112  const DataType& type = object.type();
2113  if (type.isInteger())
2114  setIntValue(object, atoll(value.c_str()));
2115  else if (type.isReal())
2116  setRealValue(object, atof(value.c_str()));
2117  else if (type.isBool()) {
2118  String val = toLowerCase(value);
2119  if (val == "true" || val == "yes" || val == "1")
2120  setBoolValue(object, true);
2121  else if (val == "false" || val == "no" || val == "0")
2122  setBoolValue(object, false);
2123  else
2124  setBoolValue(object, atof(value.c_str()));
2125  } else if (type.isEnum())
2126  setEnumValue(object, atoll(value.c_str()));
2127  else
2128  throw Exception("Not a primitive data type");
2129  }
2130 
2140  String Archive::valueAsString(const Object& object) {
2141  if (!object)
2142  throw Exception("Invalid object");
2143  if (object.type().isClass())
2144  throw Exception("Object is class type");
2145  const Object* pObject = &object;
2146  if (object.type().isPointer()) {
2147  const Object& obj = objectByUID(object.uid(1));
2148  if (!obj) return "";
2149  pObject = &obj;
2150  }
2151  return _primitiveObjectValueToString(*pObject);
2152  }
2153 
2163  int64_t Archive::valueAsInt(const Object& object) {
2164  if (!object)
2165  throw Exception("Invalid object");
2166  if (!object.type().isInteger() && !object.type().isEnum())
2167  throw Exception("Object is neither an integer nor an enum");
2168  const Object* pObject = &object;
2169  if (object.type().isPointer()) {
2170  const Object& obj = objectByUID(object.uid(1));
2171  if (!obj) return 0;
2172  pObject = &obj;
2173  }
2174  return _primitiveObjectValueToNumber<int64_t>(*pObject);
2175  }
2176 
2186  double Archive::valueAsReal(const Object& object) {
2187  if (!object)
2188  throw Exception("Invalid object");
2189  if (!object.type().isReal())
2190  throw Exception("Object is not an real type");
2191  const Object* pObject = &object;
2192  if (object.type().isPointer()) {
2193  const Object& obj = objectByUID(object.uid(1));
2194  if (!obj) return 0;
2195  pObject = &obj;
2196  }
2197  return _primitiveObjectValueToNumber<double>(*pObject);
2198  }
2199 
2208  bool Archive::valueAsBool(const Object& object) {
2209  if (!object)
2210  throw Exception("Invalid object");
2211  if (!object.type().isBool())
2212  throw Exception("Object is not a bool");
2213  const Object* pObject = &object;
2214  if (object.type().isPointer()) {
2215  const Object& obj = objectByUID(object.uid(1));
2216  if (!obj) return 0;
2217  pObject = &obj;
2218  }
2219  return _primitiveObjectValueToNumber<bool>(*pObject);
2220  }
2221 
2222  // *************** Archive::Syncer ***************
2223  // *
2224 
2225  Archive::Syncer::Syncer(Archive& dst, Archive& src)
2226  : m_dst(dst), m_src(src)
2227  {
2228  const Object srcRootObj = src.rootObject();
2229  const Object dstRootObj = dst.rootObject();
2230  if (!srcRootObj)
2231  throw Exception("No source root object!");
2232  if (!dstRootObj)
2233  throw Exception("Expected destination root object not found!");
2234  syncObject(dstRootObj, srcRootObj);
2235  }
2236 
2237  void Archive::Syncer::syncPrimitive(const Object& dstObj, const Object& srcObj) {
2238  assert(srcObj.rawData().size() == dstObj.type().size());
2239  void* pDst = (void*)dstObj.uid().id;
2240  memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
2241  }
2242 
2243  void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
2244  assert(dstObj.type().isPointer());
2245  assert(dstObj.type() == srcObj.type());
2246  const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
2247  const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
2248  syncObject(pointedDstObject, pointedSrcObject);
2249  }
2250 
2251  void Archive::Syncer::syncObject(const Object& dstObj, const Object& srcObj) {
2252  if (!dstObj || !srcObj) return; // end of recursion
2253  if (!dstObj.isVersionCompatibleTo(srcObj))
2254  throw Exception("Version incompatible (destination version " +
2255  ToString(dstObj.version()) + " [min. version " +
2256  ToString(dstObj.minVersion()) + "], source version " +
2257  ToString(srcObj.version()) + " [min. version " +
2258  ToString(srcObj.minVersion()) + "])");
2259  if (dstObj.type() != srcObj.type())
2260  throw Exception("Incompatible data structure type (destination type " +
2261  dstObj.type().asLongDescr() + " vs. source type " +
2262  srcObj.type().asLongDescr() + ")");
2263 
2264  // prevent syncing this object again, and thus also prevent endless
2265  // loop on data structures with cyclic relations
2266  m_dst.m_allObjects.erase(dstObj.uid());
2267 
2268  if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2269  syncPrimitive(dstObj, srcObj);
2270  return; // end of recursion
2271  }
2272 
2273  if (dstObj.type().isPointer()) {
2274  syncPointer(dstObj, srcObj);
2275  return;
2276  }
2277 
2278  assert(dstObj.type().isClass());
2279  for (int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
2280  const Member& srcMember = srcObj.members()[iMember];
2281  Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2282  if (!dstMember)
2283  throw Exception("Expected member missing in destination object");
2284  syncMember(dstMember, srcMember);
2285  }
2286  }
2287 
2288  Member Archive::Syncer::dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember) {
2289  Member dstMember = dstObj.memberNamed(srcMember.name());
2290  if (dstMember)
2291  return (dstMember.type() == srcMember.type()) ? dstMember : Member();
2292  std::vector<Member> members = dstObj.membersOfType(srcMember.type());
2293  if (members.size() <= 0)
2294  return Member();
2295  if (members.size() == 1)
2296  return members[0];
2297  for (int i = 0; i < members.size(); ++i)
2298  if (members[i].offset() == srcMember.offset())
2299  return members[i];
2300  const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
2301  assert(srcSeqNr >= 0); // should never happen, otherwise there is a bug
2302  for (int i = 0; i < members.size(); ++i) {
2303  const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
2304  if (dstSeqNr == srcSeqNr)
2305  return members[i];
2306  }
2307  return Member(); // give up!
2308  }
2309 
2310  void Archive::Syncer::syncMember(const Member& dstMember, const Member& srcMember) {
2311  assert(dstMember && srcMember);
2312  assert(dstMember.type() == srcMember.type());
2313  const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
2314  const Object srcObj = m_src.m_allObjects[srcMember.uid()];
2315  syncObject(dstObj, srcObj);
2316  }
2317 
2318  // *************** Exception ***************
2319  // *
2320 
2321  Exception::Exception() {
2322  }
2323 
2324  Exception::Exception(String format, ...) {
2325  va_list arg;
2326  va_start(arg, format);
2327  Message = assemble(format, arg);
2328  va_end(arg);
2329  }
2330 
2331  Exception::Exception(String format, va_list arg) {
2332  Message = assemble(format, arg);
2333  }
2334 
2341  std::cout << "Serialization::Exception: " << Message << std::endl;
2342  }
2343 
2344  String Exception::assemble(String format, va_list arg) {
2345  char* buf = NULL;
2346  vasprintf(&buf, format.c_str(), arg);
2347  String s = buf;
2348  free(buf);
2349  return s;
2350  }
2351 
2352 } // namespace Serialization
Serialization::DataType::operator<
bool operator<(const DataType &other) const
Smaller than comparison.
Definition: Serialization.cpp:294
Serialization::Archive::setIntValue
void setIntValue(Object &object, int64_t value)
Set new integer value for given integer object.
Definition: Serialization.cpp:2000
Serialization::Object::memberByUID
Member memberByUID(const UID &uid) const
Get the member of this Object with given unique identifier.
Definition: Serialization.cpp:965
Serialization::Object::rawData
const RawData & rawData() const
Raw data of the original native C/C++ data.
Definition: Serialization.cpp:740
Serialization::Version
uint32_t Version
Version number data type.
Definition: Serialization.h:151
Serialization::Archive::objectByUID
Object & objectByUID(const UID &uid)
Access object by its unique identifier.
Definition: Serialization.cpp:1914
Serialization::Object::uidChain
const UIDChain & uidChain() const
Unique identifier chain of this Object.
Definition: Serialization.cpp:705
Serialization::Member::operator==
bool operator==(const Member &other) const
Comparison for equalness.
Definition: Serialization.cpp:572
Serialization::DataType::isPointer
bool isPointer() const
Whether this is reflecting a C/C++ pointer type.
Definition: Serialization.cpp:114
Serialization::Member
Abstract reflection of a native C++ class/struct's member variable.
Definition: Serialization.h:486
Serialization::DataType::operator>
bool operator>(const DataType &other) const
Greater than comparison.
Definition: Serialization.cpp:315
Serialization::DataType::isEnum
bool isEnum() const
Whether this is a C/C++ enum data type.
Definition: Serialization.cpp:227
Serialization::Archive::valueAsBool
bool valueAsBool(const Object &object)
Get boolean value of object.
Definition: Serialization.cpp:2208
Serialization::Archive::Archive
Archive()
Create an "empty" archive.
Definition: Serialization.cpp:1066
Serialization::UIDChain
std::vector< UID > UIDChain
Chain of UIDs.
Definition: Serialization.h:324
Serialization::Archive::clear
void clear()
Clear content of this archive.
Definition: Serialization.cpp:1735
Serialization::Archive::name
String name() const
Optional name of this archive.
Definition: Serialization.cpp:1751
Serialization::Archive::valueAsInt
int64_t valueAsInt(const Object &object)
Get integer value of object.
Definition: Serialization.cpp:2163
Serialization::DataType::isBool
bool isBool() const
Whether this is a boolean C/C++ data type.
Definition: Serialization.cpp:212
Serialization::Archive::setBoolValue
void setBoolValue(Object &object, bool value)
Set new boolean value for given boolean object.
Definition: Serialization.cpp:2080
Serialization::Archive::comment
String comment() const
Optional comments for this archive.
Definition: Serialization.cpp:1777
Serialization::Archive::rawDataFormat
virtual String rawDataFormat() const
Name of the encoding format used by this Archive class.
Definition: Serialization.cpp:1708
Serialization::Archive::setRealValue
void setRealValue(Object &object, double value)
Set new floating point value for given floating point object.
Definition: Serialization.cpp:2050
Serialization::Archive::dateTimeCreated
tm dateTimeCreated(time_base_t base=LOCAL_TIME) const
Date and time when this archive was initially created.
Definition: Serialization.cpp:1841
Serialization::Object::isValid
bool isValid() const
Check if this is a valid Object instance.
Definition: Serialization.cpp:680
Serialization::Object::isVersionCompatibleTo
bool isVersionCompatibleTo(const Object &other) const
Check version compatibility between Object instances.
Definition: Serialization.cpp:898
Serialization::Archive::isModified
bool isModified() const
Whether this archive was modified.
Definition: Serialization.cpp:1726
Serialization::RawData
std::vector< uint8_t > RawData
Raw data stream of serialized C++ objects.
Definition: Serialization.h:130
Serialization::LOCAL_TIME
@ LOCAL_TIME
The time stamp relates to the machine's local time zone. Request a time stamp in local time if you wa...
Definition: Serialization.h:159
Serialization::Object::operator==
bool operator==(const Object &other) const
Comparison for equalness.
Definition: Serialization.cpp:828
Serialization::Exception
Will be thrown whenever an error occurs during an serialization or deserialization process.
Definition: Serialization.h:1180
Serialization::ID
void * ID
Abstract identifier for serialized C++ objects.
Definition: Serialization.h:142
Serialization::DataType::isInteger
bool isInteger() const
Whether this is an integer C/C++ data type.
Definition: Serialization.cpp:180
Serialization::DataType::asLongDescr
String asLongDescr() const
Human readable long description for this data type.
Definition: Serialization.cpp:333
Serialization::Archive::setName
void setName(String name)
Assign a name to this archive.
Definition: Serialization.cpp:1764
Serialization::DataType::isSigned
bool isSigned() const
Whether this is a signed integer C/C++ data type.
Definition: Serialization.cpp:244
Serialization::DataType::DataType
DataType()
Default constructor.
Definition: Serialization.cpp:83
Serialization::Object::members
std::vector< Member > & members()
All members of the original native C/C++ struct or class instance.
Definition: Serialization.cpp:804
Serialization::Object
Abstract reflection of some native serialized C/C++ data.
Definition: Serialization.h:540
Serialization::Archive::rawData
const RawData & rawData()
Raw data stream of this archive content.
Definition: Serialization.cpp:1698
Serialization::UID
Unique identifier referring to one specific native C++ object, member, fundamental variable,...
Definition: Serialization.h:241
Serialization::Archive::setAutoValue
void setAutoValue(Object &object, String value)
Automatically cast and assign appropriate value to object.
Definition: Serialization.cpp:2110
Serialization::Object::version
Version version() const
Version of original user defined C/C++ struct or class.
Definition: Serialization.cpp:753
Serialization::Object::operator<
bool operator<(const Object &other) const
Smaller than comparison.
Definition: Serialization.cpp:856
Serialization::Object::type
const DataType & type() const
C/C++ data type this Object is reflecting.
Definition: Serialization.cpp:714
Serialization::time_base_t
time_base_t
To which time zone a certain timing information relates to.
Definition: Serialization.h:158
Serialization::Archive::setVersion
void setVersion(const T_classType &nativeObject, Version v)
Set current version number for your C++ class.
Definition: Serialization.h:974
Serialization::UID::size
size_t size
Memory size of the object or member in question.
Definition: Serialization.h:244
Serialization::DataType::operator!=
bool operator!=(const DataType &other) const
Comparison for inequalness.
Definition: Serialization.cpp:279
Serialization::Object::sequenceIndexOf
int sequenceIndexOf(const Member &member) const
Serialization/deserialization sequence number of the requested member.
Definition: Serialization.cpp:1038
Serialization::Exception::PrintMessage
void PrintMessage()
Print exception message to stdout.
Definition: Serialization.cpp:2340
Serialization::Archive
Destination container for serialization, and source container for deserialization.
Definition: Serialization.h:709
Serialization::Member::type
const DataType & type() const
C/C++ Data type of this member.
Definition: Serialization.cpp:546
Serialization::Object::Object
Object()
Default constructor (for an "invalid" Object).
Definition: Serialization.cpp:640
Serialization::DataType::isPrimitive
bool isPrimitive() const
Whether this is reflecting a fundamental C/C++ data type.
Definition: Serialization.cpp:162
Serialization::Archive::timeStampModified
time_t timeStampModified() const
Date and time when this archive was modified for the last time.
Definition: Serialization.cpp:1827
Serialization::Object::minVersion
Version minVersion() const
Minimum version of original user defined C/C++ struct or class.
Definition: Serialization.cpp:768
Serialization::Object::operator!=
bool operator!=(const Object &other) const
Comparison for inequalness.
Definition: Serialization.cpp:840
Serialization::DataType::operator==
bool operator==(const DataType &other) const
Comparison for equalness.
Definition: Serialization.cpp:267
Serialization::Archive::timeStampCreated
time_t timeStampCreated() const
Date and time when this archive was initially created.
Definition: Serialization.cpp:1818
Serialization::Archive::rootObject
Object & rootObject()
Root C++ object of this archive.
Definition: Serialization.cpp:1137
Serialization::Archive::valueAsString
String valueAsString(const Object &object)
Get value of object as string.
Definition: Serialization.cpp:2140
Serialization::Archive::valueAsReal
double valueAsReal(const Object &object)
Get floating point value of object.
Definition: Serialization.cpp:2186
Serialization::DataType::isClass
bool isClass() const
Whether this is reflecting a C/C++ struct or class type.
Definition: Serialization.cpp:138
Serialization::Object::memberNamed
Member memberNamed(String name) const
Get the member of this Object with given name.
Definition: Serialization.cpp:944
Serialization::Archive::decode
virtual void decode(const RawData &data)
Fill this archive with the given serialized raw data.
Definition: Serialization.cpp:1643
Serialization::Member::uid
UID uid() const
Unique identifier of this member instance.
Definition: Serialization.cpp:476
Serialization::Archive::setMinVersion
void setMinVersion(const T_classType &nativeObject, Version v)
Set a minimum version number for your C++ class.
Definition: Serialization.h:1015
Serialization::UTC_TIME
@ UTC_TIME
The time stamp relates to "Greenwhich Mean Time" zone, also known as "Coordinated Universal Time"....
Definition: Serialization.h:160
Serialization::Object::uid
UID uid(int index=0) const
Unique identifier of this Object.
Definition: Serialization.cpp:695
Serialization::DataType::isReal
bool isReal() const
Whether this is a floating point based C/C++ data type.
Definition: Serialization.cpp:197
Serialization::DataType::isValid
bool isValid() const
Check if this is a valid DataType object.
Definition: Serialization.cpp:105
Serialization::DataType
Abstract reflection of a native C++ data type.
Definition: Serialization.h:355
Serialization::Archive::removeMember
void removeMember(Object &parent, const Member &member)
Remove a member variable from the given object.
Definition: Serialization.cpp:1876
Serialization
Serialization / deserialization framework.
Definition: gig.h:91
Serialization::Archive::setComment
void setComment(String comment)
Assign a comment to this archive.
Definition: Serialization.cpp:1790
Serialization::Archive::setEnumValue
void setEnumValue(Object &object, uint64_t value)
Set new value for given enum object.
Definition: Serialization.cpp:1958
Serialization::Archive::remove
void remove(const Object &obj)
Remove an object from this archive.
Definition: Serialization.cpp:1896
Serialization::Member::isValid
bool isValid() const
Check if this is a valid Member object.
Definition: Serialization.cpp:560
Serialization::NO_UID
const UID NO_UID
Reflects an invalid UID and behaves similar to NULL as invalid value for pointer types.
Definition: Serialization.cpp:54
Serialization::Archive::dateTimeModified
tm dateTimeModified(time_base_t base=LOCAL_TIME) const
Date and time when this archive was modified for the last time.
Definition: Serialization.cpp:1855
Serialization::DataType::customTypeName
String customTypeName(bool demangle=false) const
The user defined C/C++ data type name of this data type.
Definition: Serialization.cpp:411
Serialization::Object::operator>
bool operator>(const Object &other) const
Greater than comparison.
Definition: Serialization.cpp:876
Serialization::Member::operator<
bool operator<(const Member &other) const
Smaller than comparison.
Definition: Serialization.cpp:600
Serialization::Member::operator!=
bool operator!=(const Member &other) const
Comparison for inequalness.
Definition: Serialization.cpp:584
Serialization::UID::isValid
bool isValid() const
Check whether this is a valid unique identifier.
Definition: Serialization.cpp:67
Serialization::DataType::baseTypeName
String baseTypeName() const
The base type name of this data type.
Definition: Serialization.cpp:371
Serialization::Member::Member
Member()
Default constructor.
Definition: Serialization.cpp:450
Serialization::Member::name
String name() const
Name of the member.
Definition: Serialization.cpp:500
Serialization::Member::offset
size_t offset() const
Offset of member in its containing parent data structure.
Definition: Serialization.cpp:538
Serialization::Member::operator>
bool operator>(const Member &other) const
Greater than comparison.
Definition: Serialization.cpp:622
Serialization::Object::membersOfType
std::vector< Member > membersOfType(const DataType &type) const
Get all members of this Object with given data type.
Definition: Serialization.cpp:997