26 #define LIBGIG_SERIALIZATION_INTERNAL 1 28 #include "Serialization.h" 41 #define LIBGIG_EPOCH_TIME ((time_t)0) 48 static UID _createNullUID() {
49 const UID uid = { NULL, 0 };
67 return id != NULL &&
id != (
void*)-1 &&
size;
118 m_isPointer = isPointer;
119 m_baseTypeName = baseType;
120 m_customTypeName = customType1;
121 m_customTypeName2 = customType2;
173 return m_baseTypeName ==
"class";
197 return !isClass() && !isArray() && !isSet() && !isMap();
211 return m_baseTypeName ==
"String";
229 return m_baseTypeName.substr(0, 3) ==
"int" ||
230 m_baseTypeName.substr(0, 4) ==
"uint";
246 return m_baseTypeName.substr(0, 4) ==
"real";
261 return m_baseTypeName ==
"bool";
276 return m_baseTypeName ==
"enum";
292 return m_baseTypeName ==
"Array";
308 return m_baseTypeName ==
"Set";
324 return m_baseTypeName ==
"Map";
341 return m_baseTypeName.substr(0, 3) ==
"int" ||
364 return m_baseTypeName == other.m_baseTypeName &&
365 m_customTypeName == other.m_customTypeName &&
366 m_customTypeName2 == other.m_customTypeName2 &&
367 (m_size == other.m_size || (isClass() && other.
isClass())) &&
368 m_isPointer == other.m_isPointer;
377 return !operator==(other);
392 return m_baseTypeName < other.m_baseTypeName ||
393 (m_baseTypeName == other.m_baseTypeName &&
394 (m_customTypeName < other.m_customTypeName ||
395 (m_customTypeName == other.m_customTypeName &&
396 (m_customTypeName2 < other.m_customTypeName2 ||
397 (m_customTypeName2 == other.m_customTypeName2 &&
398 (m_size < other.m_size ||
399 (m_size == other.m_size &&
400 m_isPointer < other.m_isPointer)))))));
415 return !(operator==(other) || operator<(other));
433 String s = m_baseTypeName;
434 if (!m_customTypeName.empty())
435 s +=
" " + customTypeName(
true);
436 if (!m_customTypeName2.empty())
437 s +=
" " + customTypeName2(
true);
473 return m_baseTypeName;
476 static String _demangleTypeName(
const char* name) {
478 const size_t MAXLENGTH = 1024;
479 char result[MAXLENGTH];
483 size_t size = UnDecorateSymbolName(name + 1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
492 abi::__cxa_demangle(name, 0, 0, &status);
495 return (status == 0) ? sResult : name;
536 if (!demangle)
return m_customTypeName;
537 return _demangleTypeName(m_customTypeName.c_str());
548 if (!demangle)
return m_customTypeName2;
549 return _demangleTypeName(m_customTypeName2.c_str());
685 return m_uid && !m_name.empty() && m_type;
697 return m_uid == other.m_uid &&
698 m_offset == other.m_offset &&
699 m_name == other.m_name &&
700 m_type == other.m_type;
709 return !operator==(other);
725 return m_uid < other.m_uid ||
726 (m_uid == other.m_uid &&
727 (m_offset < other.m_offset ||
728 (m_offset == other.m_offset &&
729 (m_name < other.m_name ||
730 (m_name == other.m_name &&
731 m_type < other.m_type)))));
747 return !(operator==(other) || operator<(other));
805 return m_type && !m_uid.empty();
820 return (index < m_uid.size()) ? m_uid[index] : NO_UID;
823 static void _setNativeValueFromString(
void* ptr,
const DataType& type,
const char* s) {
827 if (type.
size() == 1)
828 *(int8_t*)ptr = (int8_t) atoll(s);
829 else if (type.
size() == 2)
830 *(int16_t*)ptr = (int16_t) atoll(s);
831 else if (type.
size() == 4)
832 *(int32_t*)ptr = (int32_t) atoll(s);
833 else if (type.
size() == 8)
834 *(int64_t*)ptr = (int64_t) atoll(s);
838 if (type.
size() == 1)
839 *(uint8_t*)ptr = (uint8_t) atoll(s);
840 else if (type.
size() == 2)
841 *(uint16_t*)ptr = (uint16_t) atoll(s);
842 else if (type.
size() == 4)
843 *(uint32_t*)ptr = (uint32_t) atoll(s);
844 else if (type.
size() == 8)
845 *(uint64_t*)ptr = (uint64_t) atoll(s);
849 }
else if (type.
isReal()) {
850 if (type.
size() ==
sizeof(float))
851 *(
float*)ptr = (
float) atof(s);
852 else if (type.
size() ==
sizeof(double))
853 *(
double*)ptr = (
double) atof(s);
856 }
else if (type.
isBool()) {
857 String lower = toLowerCase(s);
858 const bool b = lower !=
"0" && lower !=
"false" && lower !=
"no";
884 const ID&
id = uid().
id;
885 void* ptr = (
void*)
id;
886 _setNativeValueFromString(ptr, m_type, s.c_str());
1022 return m_uid == other.m_uid &&
1023 m_type == other.m_type;
1032 return !operator==(other);
1050 return m_uid < other.m_uid ||
1051 (m_uid == other.m_uid &&
1052 m_type < other.m_type);
1068 return !(operator==(other) || operator<(other));
1090 if (this->version() == other.
version())
1092 if (this->version() > other.
version())
1093 return this->minVersion() <= other.
version();
1095 return other.
minVersion() <= this->version();
1098 void Object::setVersion(
Version v) {
1102 void Object::setMinVersion(
Version v) {
1136 for (
int i = 0; i < m_members.size(); ++i)
1137 if (m_members[i].name() == name)
1138 return m_members[i];
1157 if (!uid)
return Member();
1158 for (
int i = 0; i < m_members.size(); ++i)
1159 if (m_members[i].uid() == uid)
1160 return m_members[i];
1164 void Object::remove(
const Member& member) {
1165 for (
int i = 0; i < m_members.size(); ++i) {
1166 if (m_members[i] == member) {
1167 m_members.erase(m_members.begin() + i);
1189 std::vector<Member> v;
1190 for (
int i = 0; i < m_members.size(); ++i) {
1191 const Member& member = m_members[i];
1192 if (member.
type() == type)
1193 v.push_back(member);
1230 for (
int i = 0; i < m_members.size(); ++i)
1231 if (m_members[i] == member)
1258 m_operation = OPERATION_NONE;
1260 m_isModified =
false;
1261 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1280 m_operation = OPERATION_NONE;
1282 m_isModified =
false;
1283 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1308 m_operation = OPERATION_NONE;
1310 m_isModified =
false;
1311 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1315 Archive::~Archive() {
1329 return m_allObjects[m_root];
1333 return ToString(data.length()) +
":" + data;
1338 s += _encodeBlob(ToString(
size_t(uid.
id)));
1339 s += _encodeBlob(ToString(
size_t(uid.
size)));
1340 return _encodeBlob(s);
1343 static String _encode(
const time_t& time) {
1344 return _encodeBlob(ToString(time));
1353 s += _encodeBlob(ToString(type.
size()));
1354 s += _encodeBlob(ToString(type.
isPointer()));
1359 return _encodeBlob(s);
1364 for (
int i = 0; i < chain.size(); ++i)
1365 s += _encode(chain[i]);
1366 return _encodeBlob(s);
1371 s += _encode(member.
uid());
1372 s += _encodeBlob(ToString(member.
offset()));
1373 s += _encodeBlob(member.
name());
1374 s += _encode(member.
type());
1375 return _encodeBlob(s);
1378 static String _encode(
const std::vector<Member>& members) {
1380 for (
int i = 0; i < members.size(); ++i)
1381 s += _encode(members[i]);
1382 return _encodeBlob(s);
1385 static String _primitiveObjectValueToString(
const Object& obj) {
1389 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1390 if (!obj.m_data.empty())
1391 assert(type.
size() == obj.m_data.size());
1395 if (type.
size() == 1)
1396 s = ToString((int16_t)*(int8_t*)ptr);
1397 else if (type.
size() == 2)
1398 s = ToString(*(int16_t*)ptr);
1399 else if (type.
size() == 4)
1400 s = ToString(*(int32_t*)ptr);
1401 else if (type.
size() == 8)
1402 s = ToString(*(int64_t*)ptr);
1406 if (type.
size() == 1)
1407 s = ToString((uint16_t)*(uint8_t*)ptr);
1408 else if (type.
size() == 2)
1409 s = ToString(*(uint16_t*)ptr);
1410 else if (type.
size() == 4)
1411 s = ToString(*(uint32_t*)ptr);
1412 else if (type.
size() == 8)
1413 s = ToString(*(uint64_t*)ptr);
1417 }
else if (type.
isReal()) {
1418 if (type.
size() ==
sizeof(float))
1419 s = ToString(*(
float*)ptr);
1420 else if (type.
size() ==
sizeof(double))
1421 s = ToString(*(
double*)ptr);
1424 }
else if (type.
isBool()) {
1425 s = ToString(*(
bool*)ptr);
1427 s = obj.m_data.empty() ? *(
String*)ptr :
String((
const char*)ptr);
1435 template<
typename T>
1436 inline T _stringToNumber(
const String& s) {
1441 inline int64_t _stringToNumber(
const String& s) {
1442 return atoll(s.c_str());
1446 inline double _stringToNumber(
const String& s) {
1447 return atof(s.c_str());
1451 inline bool _stringToNumber(
const String& s) {
1452 return (
bool) atoll(s.c_str());
1455 template<
typename T>
1456 static T _primitiveObjectValueToNumber(
const Object& obj) {
1460 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1461 if (!obj.m_data.empty())
1462 assert(type.
size() == obj.m_data.size());
1466 if (type.
size() == 1)
1467 value = (T)*(int8_t*)ptr;
1468 else if (type.
size() == 2)
1469 value = (T)*(int16_t*)ptr;
1470 else if (type.
size() == 4)
1471 value = (T)*(int32_t*)ptr;
1472 else if (type.
size() == 8)
1473 value = (T)*(int64_t*)ptr;
1477 if (type.
size() == 1)
1478 value = (T)*(uint8_t*)ptr;
1479 else if (type.
size() == 2)
1480 value = (T)*(uint16_t*)ptr;
1481 else if (type.
size() == 4)
1482 value = (T)*(uint32_t*)ptr;
1483 else if (type.
size() == 8)
1484 value = (T)*(uint64_t*)ptr;
1488 }
else if (type.
isReal()) {
1489 if (type.
size() ==
sizeof(float))
1490 value = (T)*(
float*)ptr;
1491 else if (type.
size() ==
sizeof(double))
1492 value = (T)*(
double*)ptr;
1495 }
else if (type.
isBool()) {
1496 value = (T)*(
bool*)ptr;
1498 value = _stringToNumber<T>(
1499 obj.m_data.empty() ? *(
String*)ptr :
String((
const char*)ptr)
1508 static String _encodePrimitiveValue(
const Object& obj) {
1509 return _encodeBlob( _primitiveObjectValueToString(obj) );
1514 s += _encode(obj.
type());
1515 s += _encodeBlob(ToString(obj.
version()));
1516 s += _encodeBlob(ToString(obj.
minVersion()));
1519 s += _encodePrimitiveValue(obj);
1520 return _encodeBlob(s);
1523 String _encode(
const Archive::ObjectPool& objects) {
1525 for (Archive::ObjectPool::const_iterator itObject = objects.begin();
1526 itObject != objects.end(); ++itObject)
1528 const Object& obj = itObject->second;
1531 return _encodeBlob(s);
1541 #define MAGIC_START "Srx1v" 1542 #define ENCODING_FORMAT_MINOR_VERSION 1 1544 String Archive::_encodeRootBlob() {
1546 s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
1547 s += _encode(m_root);
1548 s += _encode(m_allObjects);
1549 s += _encodeBlob(m_name);
1550 s += _encodeBlob(m_comment);
1551 s += _encode(m_timeCreated);
1552 s += _encode(m_timeModified);
1553 return _encodeBlob(s);
1556 void Archive::encode() {
1559 m_timeModified = time(NULL);
1560 if (m_timeCreated == LIBGIG_EPOCH_TIME)
1561 m_timeCreated = m_timeModified;
1562 s += _encodeRootBlob();
1563 m_rawData.resize(s.length() + 1);
1564 memcpy(&m_rawData[0], &s[0], s.length() + 1);
1565 m_isModified =
false;
1573 static _Blob _decodeBlob(
const char* p,
const char* end,
bool bThrow =
true) {
1574 if (!bThrow && p >= end) {
1575 const _Blob blob = { p, end };
1581 throw Exception(
"Decode Error: Missing blob");
1583 if (c ==
':')
break;
1584 if (c < '0' || c >
'9')
1585 throw Exception(
"Decode Error: Missing blob size");
1587 sz += size_t(c -
'0');
1591 throw Exception(
"Decode Error: Premature end of blob");
1592 const _Blob blob = { p, p + sz };
1596 template<
typename T_
int>
1597 static T_int _popIntBlob(
const char*& p,
const char* end) {
1598 _Blob blob = _decodeBlob(p, end);
1605 throw Exception(
"Decode Error: premature end of int blob");
1610 for (; p < end; ++p) {
1612 if (c < '0' || c >
'9')
1613 throw Exception(
"Decode Error: Invalid int blob format");
1615 i += size_t(c -
'0');
1620 template<
typename T_
int>
1621 static void _popIntBlob(
const char*& p,
const char* end,
RawData& rawData) {
1622 const T_int i = _popIntBlob<T_int>(p, end);
1623 *(T_int*)&rawData[0] = i;
1626 template<
typename T_real>
1627 static T_real _popRealBlob(
const char*& p,
const char* end) {
1628 _Blob blob = _decodeBlob(p, end);
1632 if (p >= end || (end - p) < 1)
1633 throw Exception(
"Decode Error: premature end of real blob");
1635 String s(p,
size_t(end - p));
1638 if (
sizeof(T_real) <=
sizeof(
double))
1639 r = atof(s.c_str());
1648 template<
typename T_real>
1649 static void _popRealBlob(
const char*& p,
const char* end,
RawData& rawData) {
1650 const T_real r = _popRealBlob<T_real>(p, end);
1651 *(T_real*)&rawData[0] = r;
1654 static String _popStringBlob(
const char*& p,
const char* end) {
1655 _Blob blob = _decodeBlob(p, end);
1659 throw Exception(
"Decode Error: missing String blob");
1661 const size_t sz = end - p;
1663 memcpy(&s[0], p, sz);
1668 static void _popStringBlob(
const char*& p,
const char* end,
RawData& rawData) {
1669 String s = _popStringBlob(p, end);
1670 rawData.resize(s.length() + 1);
1671 strcpy((
char*)&rawData[0], &s[0]);
1674 static time_t _popTimeBlob(
const char*& p,
const char* end) {
1675 const uint64_t i = _popIntBlob<uint64_t>(p, end);
1679 static DataType _popDataTypeBlob(
const char*& p,
const char* end) {
1680 _Blob blob = _decodeBlob(p, end);
1687 type.m_baseTypeName = _popStringBlob(p, end);
1688 type.m_customTypeName = _popStringBlob(p, end);
1689 type.m_size = _popIntBlob<int>(p, end);
1690 type.m_isPointer = _popIntBlob<bool>(p, end);
1694 type.m_customTypeName2 = _popStringBlob(p, end);
1699 static UID _popUIDBlob(
const char*& p,
const char* end) {
1700 _Blob blob = _decodeBlob(p, end);
1705 throw Exception(
"Decode Error: premature end of UID blob");
1707 const ID id = (
ID) _popIntBlob<size_t>(p, end);
1708 const size_t size = _popIntBlob<size_t>(p, end);
1710 const UID uid = {
id, size };
1714 static UIDChain _popUIDChainBlob(
const char*& p,
const char* end) {
1715 _Blob blob = _decodeBlob(p, end);
1721 const UID uid = _popUIDBlob(p, end);
1722 chain.push_back(uid);
1724 assert(!chain.empty());
1728 static Member _popMemberBlob(
const char*& p,
const char* end) {
1729 _Blob blob = _decodeBlob(p, end,
false);
1734 if (p >= end)
return m;
1736 m.m_uid = _popUIDBlob(p, end);
1737 m.m_offset = _popIntBlob<ssize_t>(p, end);
1738 m.m_name = _popStringBlob(p, end);
1739 m.m_type = _popDataTypeBlob(p, end);
1741 assert(!m.
name().empty());
1746 static std::vector<Member> _popMembersBlob(
const char*& p,
const char* end) {
1747 _Blob blob = _decodeBlob(p, end,
false);
1751 std::vector<Member> members;
1753 const Member member = _popMemberBlob(p, end);
1755 members.push_back(member);
1762 static void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj) {
1765 obj.m_data.resize(type.
size());
1768 if (type.
size() == 1)
1769 _popIntBlob<int8_t>(p, end, obj.m_data);
1770 else if (type.
size() == 2)
1771 _popIntBlob<int16_t>(p, end, obj.m_data);
1772 else if (type.
size() == 4)
1773 _popIntBlob<int32_t>(p, end, obj.m_data);
1774 else if (type.
size() == 8)
1775 _popIntBlob<int64_t>(p, end, obj.m_data);
1779 if (type.
size() == 1)
1780 _popIntBlob<uint8_t>(p, end, obj.m_data);
1781 else if (type.
size() == 2)
1782 _popIntBlob<uint16_t>(p, end, obj.m_data);
1783 else if (type.
size() == 4)
1784 _popIntBlob<uint32_t>(p, end, obj.m_data);
1785 else if (type.
size() == 8)
1786 _popIntBlob<uint64_t>(p, end, obj.m_data);
1790 }
else if (type.
isReal()) {
1791 if (type.
size() ==
sizeof(float))
1792 _popRealBlob<float>(p, end, obj.m_data);
1793 else if (type.
size() ==
sizeof(double))
1794 _popRealBlob<double>(p, end, obj.m_data);
1797 }
else if (type.
isBool()) {
1798 _popIntBlob<uint8_t>(p, end, obj.m_data);
1800 _popStringBlob(p, end, obj.m_data);
1807 _Blob blob = _decodeBlob(p, end,
false);
1813 static Object _popObjectBlob(
const char*& p,
const char* end) {
1814 _Blob blob = _decodeBlob(p, end,
false);
1819 if (p >= end)
return obj;
1821 obj.m_type = _popDataTypeBlob(p, end);
1822 obj.m_version = _popIntBlob<Version>(p, end);
1823 obj.m_minVersion = _popIntBlob<Version>(p, end);
1824 obj.m_uid = _popUIDChainBlob(p, end);
1825 obj.m_members = _popMembersBlob(p, end);
1826 _popPrimitiveValue(p, end, obj);
1831 void Archive::_popObjectsBlob(
const char*& p,
const char* end) {
1832 _Blob blob = _decodeBlob(p, end,
false);
1837 throw Exception(
"Decode Error: Premature end of objects blob");
1840 const Object obj = _popObjectBlob(p, end);
1842 m_allObjects[obj.
uid()] = obj;
1846 void Archive::_popRootBlob(
const char*& p,
const char* end) {
1847 _Blob blob = _decodeBlob(p, end,
false);
1852 throw Exception(
"Decode Error: Premature end of root blob");
1856 const int formatMinorVersion = _popIntBlob<int>(p, end);
1858 m_root = _popUIDBlob(p, end);
1860 throw Exception(
"Decode Error: No root object");
1862 _popObjectsBlob(p, end);
1863 if (!m_allObjects[m_root])
1864 throw Exception(
"Decode Error: Missing declared root object");
1866 m_name = _popStringBlob(p, end);
1867 m_comment = _popStringBlob(p, end);
1868 m_timeCreated = _popTimeBlob(p, end);
1869 m_timeModified = _popTimeBlob(p, end);
1889 m_allObjects.clear();
1890 m_isModified =
false;
1891 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1892 const char* p = (
const char*) &data[0];
1893 const char* end = p + data.size();
1894 if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
1895 throw Exception(
"Decode Error: Magic start missing!");
1896 p += strlen(MAGIC_START);
1897 _popRootBlob(p, end);
1922 rawData.resize(size);
1923 memcpy(&rawData[0], data, size);
1943 if (m_isModified) encode();
1971 return m_isModified;
1980 m_allObjects.clear();
1981 m_operation = OPERATION_NONE;
1984 m_isModified =
false;
1985 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
2009 if (m_name == name)
return;
2011 m_isModified =
true;
2035 if (m_comment == comment)
return;
2036 m_comment = comment;
2037 m_isModified =
true;
2040 static tm _convertTimeStamp(
const time_t& time,
time_base_t base) {
2044 pTm = localtime(&time);
2047 pTm = gmtime(&time);
2050 throw Exception(
"Time stamp with unknown time base (" + ToString((int64_t)base) +
") requested");
2053 throw Exception(
"Failed assembling time stamp structure");
2063 return m_timeCreated;
2072 return m_timeModified;
2086 return _convertTimeStamp(m_timeCreated, base);
2100 return _convertTimeStamp(m_timeModified, base);
2121 parent.remove(member);
2122 m_isModified =
true;
2142 if (!obj.
uid())
return;
2143 m_allObjects.erase(obj.
uid());
2144 m_isModified =
true;
2159 return m_allObjects[uid];
2173 if (!
object)
return;
2174 object.setVersion(v);
2175 m_isModified =
true;
2189 if (!
object)
return;
2190 object.setMinVersion(v);
2191 m_isModified =
true;
2203 if (!
object)
return;
2204 if (!
object.type().isEnum())
2205 throw Exception(
"Not an enum data type");
2206 Object* pObject = &object;
2207 if (
object.type().isPointer()) {
2208 Object& obj = objectByUID(
object.uid(1));
2212 const int nativeEnumSize =
sizeof(
enum operation_t);
2216 if (type.
size() != nativeEnumSize) {
2217 type.m_size = nativeEnumSize;
2219 pObject->m_data.resize(type.
size());
2220 void* ptr = &pObject->m_data[0];
2221 if (type.
size() == 1)
2222 *(uint8_t*)ptr = (uint8_t)value;
2223 else if (type.
size() == 2)
2224 *(uint16_t*)ptr = (uint16_t)value;
2225 else if (type.
size() == 4)
2226 *(uint32_t*)ptr = (uint32_t)value;
2227 else if (type.
size() == 8)
2228 *(uint64_t*)ptr = (uint64_t)value;
2231 m_isModified =
true;
2245 if (!
object)
return;
2246 if (!
object.type().isInteger())
2247 throw Exception(
"Not an integer data type");
2248 Object* pObject = &object;
2249 if (
object.type().isPointer()) {
2250 Object& obj = objectByUID(
object.uid(1));
2255 pObject->m_data.resize(type.
size());
2256 void* ptr = &pObject->m_data[0];
2258 if (type.
size() == 1)
2259 *(int8_t*)ptr = (int8_t)value;
2260 else if (type.
size() == 2)
2261 *(int16_t*)ptr = (int16_t)value;
2262 else if (type.
size() == 4)
2263 *(int32_t*)ptr = (int32_t)value;
2264 else if (type.
size() == 8)
2265 *(int64_t*)ptr = (int64_t)value;
2269 if (type.
size() == 1)
2270 *(uint8_t*)ptr = (uint8_t)value;
2271 else if (type.
size() == 2)
2272 *(uint16_t*)ptr = (uint16_t)value;
2273 else if (type.
size() == 4)
2274 *(uint32_t*)ptr = (uint32_t)value;
2275 else if (type.
size() == 8)
2276 *(uint64_t*)ptr = (uint64_t)value;
2280 m_isModified =
true;
2295 if (!
object)
return;
2296 if (!
object.type().isReal())
2297 throw Exception(
"Not a real data type");
2298 Object* pObject = &object;
2299 if (
object.type().isPointer()) {
2300 Object& obj = objectByUID(
object.uid(1));
2305 pObject->m_data.resize(type.
size());
2306 void* ptr = &pObject->m_data[0];
2307 if (type.
size() ==
sizeof(float))
2308 *(
float*)ptr = (
float)value;
2309 else if (type.
size() ==
sizeof(double))
2310 *(
double*)ptr = (
double)value;
2313 m_isModified =
true;
2325 if (!
object)
return;
2326 if (!
object.type().isBool())
2327 throw Exception(
"Not a bool data type");
2328 Object* pObject = &object;
2329 if (
object.type().isPointer()) {
2330 Object& obj = objectByUID(
object.uid(1));
2335 pObject->m_data.resize(type.
size());
2336 bool* ptr = (
bool*)&pObject->m_data[0];
2338 m_isModified =
true;
2350 if (!
object)
return;
2351 if (!
object.type().isString())
2352 throw Exception(
"Not a String data type");
2353 Object* pObject = &object;
2354 if (
object.type().isPointer()) {
2355 Object& obj = objectByUID(
object.uid(1));
2359 pObject->m_data.resize(value.length() + 1);
2360 char* ptr = (
char*) &pObject->m_data[0];
2361 strcpy(ptr, &value[0]);
2362 m_isModified =
true;
2379 if (!
object)
return;
2380 const DataType& type =
object.type();
2382 setIntValue(
object, atoll(value.c_str()));
2384 setRealValue(
object, atof(value.c_str()));
2385 else if (type.
isBool()) {
2386 String val = toLowerCase(value);
2387 if (val ==
"true" || val ==
"yes" || val ==
"1")
2388 setBoolValue(
object,
true);
2389 else if (val ==
"false" || val ==
"no" || val ==
"0")
2390 setBoolValue(
object,
false);
2392 setBoolValue(
object, atof(value.c_str()));
2394 setStringValue(
object, value);
2396 setEnumValue(
object, atoll(value.c_str()));
2398 throw Exception(
"Not a primitive data type");
2413 if (
object.type().isClass())
2414 throw Exception(
"Object is class type");
2415 const Object* pObject = &object;
2416 if (
object.type().isPointer()) {
2417 const Object& obj = objectByUID(
object.uid(1));
2418 if (!obj)
return "";
2421 return _primitiveObjectValueToString(*pObject);
2436 if (!
object.type().isInteger() && !
object.type().isEnum())
2437 throw Exception(
"Object is neither an integer nor an enum");
2438 const Object* pObject = &object;
2439 if (
object.type().isPointer()) {
2440 const Object& obj = objectByUID(
object.uid(1));
2444 return _primitiveObjectValueToNumber<int64_t>(*pObject);
2459 if (!
object.type().isReal())
2460 throw Exception(
"Object is not an real type");
2461 const Object* pObject = &object;
2462 if (
object.type().isPointer()) {
2463 const Object& obj = objectByUID(
object.uid(1));
2467 return _primitiveObjectValueToNumber<double>(*pObject);
2481 if (!
object.type().isBool())
2482 throw Exception(
"Object is not a bool");
2483 const Object* pObject = &object;
2484 if (
object.type().isPointer()) {
2485 const Object& obj = objectByUID(
object.uid(1));
2489 return _primitiveObjectValueToNumber<bool>(*pObject);
2500 : m_dst(dst), m_src(src)
2505 throw Exception(
"No source root object!");
2507 throw Exception(
"Expected destination root object not found!");
2508 syncObject(dstRootObj, srcRootObj);
2511 void Archive::Syncer::syncPrimitive(
const Object& dstObj,
const Object& srcObj) {
2513 void* pDst = (
void*)dstObj.
uid().
id;
2517 void Archive::Syncer::syncString(
const Object& dstObj,
const Object& srcObj) {
2519 assert(dstObj.
type() == srcObj.
type());
2524 void Archive::Syncer::syncArray(
const Object& dstObj,
const Object& srcObj) {
2526 assert(dstObj.
type() == srcObj.
type());
2527 dstObj.m_sync(const_cast<Object&>(dstObj), srcObj,
this);
2530 void Archive::Syncer::syncSet(
const Object& dstObj,
const Object& srcObj) {
2532 assert(dstObj.
type() == srcObj.
type());
2533 dstObj.m_sync(const_cast<Object&>(dstObj), srcObj,
this);
2536 void Archive::Syncer::syncMap(
const Object& dstObj,
const Object& srcObj) {
2538 assert(dstObj.
type() == srcObj.
type());
2539 dstObj.m_sync(const_cast<Object&>(dstObj), srcObj,
this);
2542 void Archive::Syncer::syncPointer(
const Object& dstObj,
const Object& srcObj) {
2544 assert(dstObj.
type() == srcObj.
type());
2545 const Object& pointedDstObject = m_dst.m_allObjects[dstObj.
uid(1)];
2546 const Object& pointedSrcObject = m_src.m_allObjects[srcObj.
uid(1)];
2547 syncObject(pointedDstObject, pointedSrcObject);
2550 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2551 if (!dstObj || !srcObj)
return;
2553 throw Exception(
"Version incompatible (destination version " +
2554 ToString(dstObj.
version()) +
" [min. version " +
2555 ToString(dstObj.
minVersion()) +
"], source version " +
2556 ToString(srcObj.
version()) +
" [min. version " +
2558 if (dstObj.
type() != srcObj.
type())
2559 throw Exception(
"Incompatible data structure type (destination type " +
2565 m_dst.m_allObjects.erase(dstObj.
uid());
2569 syncString(dstObj, srcObj);
2571 syncPrimitive(dstObj, srcObj);
2576 syncArray(dstObj, srcObj);
2581 syncSet(dstObj, srcObj);
2586 syncMap(dstObj, srcObj);
2591 syncPointer(dstObj, srcObj);
2596 for (
int iMember = 0; iMember < srcObj.
members().size(); ++iMember) {
2598 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2600 throw Exception(
"Expected member missing in destination object");
2601 syncMember(dstMember, srcMember);
2608 return (dstMember.
type() == srcMember.
type()) ? dstMember :
Member();
2610 if (members.size() <= 0)
2612 if (members.size() == 1)
2614 for (
int i = 0; i < members.size(); ++i)
2615 if (members[i].offset() == srcMember.
offset())
2618 assert(srcSeqNr >= 0);
2619 for (
int i = 0; i < members.size(); ++i) {
2621 if (dstSeqNr == srcSeqNr)
2627 void Archive::Syncer::syncMember(
const Member& dstMember,
const Member& srcMember) {
2628 assert(dstMember && srcMember);
2629 assert(dstMember.
type() == srcMember.
type());
2630 const Object dstObj = m_dst.m_allObjects[dstMember.
uid()];
2631 const Object srcObj = m_src.m_allObjects[srcMember.
uid()];
2632 syncObject(dstObj, srcObj);
2638 Exception::Exception() {
2641 Exception::Exception(
String format, ...) {
2643 va_start(arg, format);
2644 Message = assemble(format, arg);
2648 Exception::Exception(
String format, va_list arg) {
2649 Message = assemble(format, arg);
2658 std::cout <<
"Serialization::Exception: " << Message << std::endl;
2661 String Exception::assemble(
String format, va_list arg) {
2663 vasprintf(&buf, format.c_str(), arg);
String customTypeName(bool demangle=false) const
The 1st user defined C/C++ data type name of this data type.
String customTypeName2(bool demangle=false) const
The 2nd user defined C/C++ data type name of this data type.
bool isClass() const
Whether this is reflecting a C/C++ struct or class type.
bool isString() const
Whether this is a C++ String data type.
String baseTypeName() const
The base type name of this data type.
Abstract reflection of some native serialized C/C++ data.
std::vector< Member > membersOfType(const DataType &type) const
Get all members of this Object with given data type.
bool isPointer() const
Whether this is reflecting a C/C++ pointer type.
void setName(String name)
Assign a name to this archive.
Destination container for serialization, and source container for deserialization.
std::vector< UID > UIDChain
Chain of UIDs.
bool operator==(const Member &other) const
Comparison for equalness.
void clear()
Clear content of this archive.
Object & objectByUID(const UID &uid)
Access object by its unique identifier.
bool isVersionCompatibleTo(const Object &other) const
Check version compatibility between Object instances.
void * ID
Abstract identifier for serialized C++ objects.
String name() const
Optional name of this archive.
virtual String rawDataFormat() const
Name of the encoding format used by this Archive class.
int64_t valueAsInt(const Object &object)
Get integer value of object.
bool valueAsBool(const Object &object)
Get boolean value of object.
void setAutoValue(Object &object, String value)
Automatically cast and assign appropriate value to object.
Abstract reflection of a native C++ data type.
const UIDChain & uidChain() const
Unique identifier chain of this Object.
void setMinVersion(const T_classType &nativeObject, Version v)
Set a minimum version number for your C++ class.
const RawData & rawData()
Raw data stream of this archive content.
time_t timeStampCreated() const
Date and time when this archive was initially created.
std::string String
Textual string.
bool isSigned() const
Whether this is a signed integer C/C++ data type.
void setIntValue(Object &object, int64_t value)
Set new integer value for given integer object.
void setNativeValueFromString(const String &s)
Cast from string to object's data type and assign value natively.
uint32_t Version
Version number data type.
bool operator<(const DataType &other) const
Smaller than comparison.
bool isValid() const
Check if this is a valid DataType object.
void setRealValue(Object &object, double value)
Set new floating point value for given floating point object.
time_base_t
To which time zone a certain timing information relates to.
bool operator==(const Object &other) const
Comparison for equalness.
bool isValid() const
Check whether this is a valid unique identifier.
void setVersion(const T_classType &nativeObject, Version v)
Set current version number for your C++ class.
Unique identifier referring to one specific native C++ object, member, fundamental variable...
bool isValid() const
Check if this is a valid Object instance.
std::vector< Member > & members()
All members of the original native C/C++ struct or class instance.
const DataType & type() const
C/C++ data type this Object is reflecting.
bool isBool() const
Whether this is a boolean C/C++ data type.
virtual void decode(const RawData &data)
Fill this archive with the given serialized raw data.
Object & rootObject()
Root C++ object of this archive.
ID id
Abstract non-unique ID of the object or member in question.
String comment() const
Optional comments for this archive.
bool operator<(const Object &other) const
Smaller than comparison.
std::vector< uint8_t > RawData
Raw data stream of serialized C++ objects.
The time stamp relates to the machine's local time zone. Request a time stamp in local time if you wa...
The time stamp relates to "Greenwhich Mean Time" zone, also known as "Coordinated Universal Time"...
Will be thrown whenever an error occurs during an serialization or deserialization process...
Version minVersion() const
Minimum version of original user defined C/C++ struct or class.
String valueAsString(const Object &object)
Get value of object as string.
Version version() const
Version of original user defined C/C++ struct or class.
int sequenceIndexOf(const Member &member) const
Serialization/deserialization sequence number of the requested member.
tm dateTimeCreated(time_base_t base=LOCAL_TIME) const
Date and time when this archive was initially created.
const DataType & type() const
C/C++ Data type of this member.
bool operator>(const DataType &other) const
Greater than comparison.
bool operator!=(const Object &other) const
Comparison for inequalness.
bool isEnum() const
Whether this is a C/C++ enum data type.
Archive()
Create an "empty" archive.
bool isInteger() const
Whether this is an integer C/C++ data type.
bool operator==(const DataType &other) const
Comparison for equalness.
bool isPrimitive() const
Whether this is reflecting a fundamental C/C++ data type.
Object()
Default constructor (for an "invalid" Object).
ssize_t offset() const
Offset of member in its containing parent data structure.
bool isReal() const
Whether this is a floating point based C/C++ data type.
bool isMap() const
Whether this is a C++ Map<> object type.
UID uid() const
Unique identifier of this member instance.
void setBoolValue(Object &object, bool value)
Set new boolean value for given boolean object.
operation_t
Current activity of Archive object.
bool isArray() const
Whether this is a C++ Array<> object type.
Member memberNamed(String name) const
Get the member of this Object with given name.
void PrintMessage()
Print exception message to stdout.
String asLongDescr() const
Human readable long description for this data type.
void setStringValue(Object &object, String value)
Set new textual string for given String object.
void setEnumValue(Object &object, uint64_t value)
Set new value for given enum object.
UID uid(int index=0) const
Unique identifier of this Object.
double valueAsReal(const Object &object)
Get floating point value of object.
size_t size() const
Returns native memory size of the respective C++ object or variable.
tm dateTimeModified(time_base_t base=LOCAL_TIME) const
Date and time when this archive was modified for the last time.
bool isModified() const
Whether this archive was modified.
bool operator!=(const DataType &other) const
Comparison for inequalness.
bool isValid() const
Check if this is a valid Member object.
bool operator>(const Object &other) const
Greater than comparison.
void removeMember(Object &parent, const Member &member)
Remove a member variable from the given object.
bool isSet() const
Whether this is a C++ Set<> object type.
const UID NO_UID
Reflects an invalid UID and behaves similar to NULL as invalid value for pointer types.
void setComment(String comment)
Assign a comment to this archive.
Serialization / deserialization framework.
bool operator<(const Member &other) const
Smaller than comparison.
DataType()
Default constructor (as "invalid" DataType).
bool operator!=(const Member &other) const
Comparison for inequalness.
Member memberByUID(const UID &uid) const
Get the member of this Object with given unique identifier.
size_t size
Memory size of the object or member in question.
Abstract reflection of a native C++ class/struct's member variable.
time_t timeStampModified() const
Date and time when this archive was modified for the last time.
void remove(const Object &obj)
Remove an object from this archive.
const RawData & rawData() const
Raw data of the original native C/C++ data.
bool operator>(const Member &other) const
Greater than comparison.
Member()
Default constructor.
String name() const
Name of the member.