26 #define LIBGIG_SERIALIZATION_INTERNAL 1 28 #include "Serialization.h" 42 #define LIBGIG_EPOCH_TIME ((time_t)0) 49 static UID _createNullUID() {
50 const UID uid = { NULL, 0 };
68 return id != NULL &&
id != (
void*)-1 &&
size;
90 m_isPointer = isPointer;
91 m_baseTypeName = baseType;
92 m_customTypeName = customType;
139 return m_baseTypeName ==
"class";
181 return m_baseTypeName.substr(0, 3) ==
"int" ||
182 m_baseTypeName.substr(0, 4) ==
"uint";
198 return m_baseTypeName.substr(0, 4) ==
"real";
213 return m_baseTypeName ==
"bool";
228 return m_baseTypeName ==
"enum";
245 return m_baseTypeName.substr(0, 3) ==
"int" ||
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;
280 return !operator==(other);
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)))));
316 return !(operator==(other) || operator<(other));
334 String s = m_baseTypeName;
335 if (!m_customTypeName.empty())
336 s +=
" " + customTypeName(
true);
372 return m_baseTypeName;
412 if (!demangle)
return m_customTypeName;
414 const size_t MAXLENGTH = 1024;
415 char result[MAXLENGTH];
419 size_t size = UnDecorateSymbolName(m_customTypeName.c_str() +1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
424 return m_customTypeName;
428 abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
429 String sResult = result;
431 return (status == 0) ? sResult : m_customTypeName;
561 return m_uid && !m_name.empty() && m_type;
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;
585 return !operator==(other);
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)))));
623 return !(operator==(other) || operator<(other));
681 return m_type && !m_uid.empty();
696 return (index < m_uid.size()) ? m_uid[index] : NO_UID;
831 return m_uid == other.m_uid &&
832 m_type == other.m_type;
841 return !operator==(other);
859 return m_uid < other.m_uid ||
860 (m_uid == other.m_uid &&
861 m_type < other.m_type);
877 return !(operator==(other) || operator<(other));
899 if (this->version() == other.
version())
901 if (this->version() > other.
version())
902 return this->minVersion() <= other.
version();
907 void Object::setVersion(
Version v) {
911 void Object::setMinVersion(
Version v) {
945 for (
int i = 0; i < m_members.size(); ++i)
946 if (m_members[i].name() == name)
966 if (!uid)
return Member();
967 for (
int i = 0; i < m_members.size(); ++i)
968 if (m_members[i].uid() == uid)
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);
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);
1039 for (
int i = 0; i < m_members.size(); ++i)
1040 if (m_members[i] == member)
1067 m_operation = OPERATION_NONE;
1069 m_isModified =
false;
1070 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1089 m_operation = OPERATION_NONE;
1091 m_isModified =
false;
1092 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1117 m_operation = OPERATION_NONE;
1119 m_isModified =
false;
1120 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1124 Archive::~Archive() {
1138 return m_allObjects[m_root];
1141 static String _encodeBlob(String data) {
1142 return ToString(data.length()) +
":" + data;
1145 static String _encode(
const UID& uid) {
1147 s += _encodeBlob(ToString(
size_t(uid.
id)));
1148 s += _encodeBlob(ToString(
size_t(uid.
size)));
1149 return _encodeBlob(s);
1152 static String _encode(
const time_t& time) {
1153 return _encodeBlob(ToString(time));
1156 static String _encode(
const DataType& type) {
1160 s += _encodeBlob(ToString(type.
size()));
1161 s += _encodeBlob(ToString(type.
isPointer()));
1162 return _encodeBlob(s);
1165 static String _encode(
const UIDChain& chain) {
1167 for (
int i = 0; i < chain.size(); ++i)
1168 s += _encode(chain[i]);
1169 return _encodeBlob(s);
1172 static String _encode(
const Member& member) {
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);
1181 static String _encode(
const std::vector<Member>& members) {
1183 for (
int i = 0; i < members.size(); ++i)
1184 s += _encode(members[i]);
1185 return _encodeBlob(s);
1188 static String _primitiveObjectValueToString(
const Object& obj) {
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());
1198 if (type.
size() == 1)
1199 s = ToString((int16_t)*(int8_t*)ptr);
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);
1209 if (type.
size() == 1)
1210 s = ToString((uint16_t)*(uint8_t*)ptr);
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);
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);
1227 }
else if (type.
isBool()) {
1228 s = ToString(*(
bool*)ptr);
1237 template<
typename T>
1238 static T _primitiveObjectValueToNumber(
const Object& obj) {
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());
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;
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;
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;
1277 }
else if (type.
isBool()) {
1278 value = (T)*(
bool*)ptr;
1286 static String _encodePrimitiveValue(
const Object& obj) {
1287 return _encodeBlob( _primitiveObjectValueToString(obj) );
1290 static String _encode(
const Object& obj) {
1292 s += _encode(obj.
type());
1293 s += _encodeBlob(ToString(obj.
version()));
1294 s += _encodeBlob(ToString(obj.
minVersion()));
1297 s += _encodePrimitiveValue(obj);
1298 return _encodeBlob(s);
1301 String _encode(
const Archive::ObjectPool& objects) {
1303 for (Archive::ObjectPool::const_iterator itObject = objects.begin();
1304 itObject != objects.end(); ++itObject)
1306 const Object& obj = itObject->second;
1309 return _encodeBlob(s);
1312 #define MAGIC_START "Srx1v" 1313 #define ENCODING_FORMAT_MINOR_VERSION 0 1315 String Archive::_encodeRootBlob() {
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);
1327 void Archive::encode() {
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;
1344 static _Blob _decodeBlob(
const char* p,
const char* end,
bool bThrow =
true) {
1345 if (!bThrow && p >= end) {
1346 const _Blob blob = { p, end };
1352 throw Exception(
"Decode Error: Missing blob");
1354 if (c ==
':')
break;
1355 if (c < '0' || c >
'9')
1356 throw Exception(
"Decode Error: Missing blob size");
1358 sz += size_t(c -
'0');
1362 throw Exception(
"Decode Error: Premature end of blob");
1363 const _Blob blob = { p, p + sz };
1367 template<
typename T_
int>
1368 static T_int _popIntBlob(
const char*& p,
const char* end) {
1369 _Blob blob = _decodeBlob(p, end);
1376 throw Exception(
"Decode Error: premature end of int blob");
1381 for (; p < end; ++p) {
1383 if (c < '0' || c >
'9')
1384 throw Exception(
"Decode Error: Invalid int blob format");
1386 i += size_t(c -
'0');
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;
1397 template<
typename T_real>
1398 static T_real _popRealBlob(
const char*& p,
const char* end) {
1399 _Blob blob = _decodeBlob(p, end);
1403 if (p >= end || (end - p) < 1)
1404 throw Exception(
"Decode Error: premature end of real blob");
1406 String s(p,
size_t(end - p));
1409 if (
sizeof(T_real) <=
sizeof(
double))
1410 r = atof(s.c_str());
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;
1425 static String _popStringBlob(
const char*& p,
const char* end) {
1426 _Blob blob = _decodeBlob(p, end);
1430 throw Exception(
"Decode Error: missing String blob");
1432 const size_t sz = end - p;
1434 memcpy(&s[0], p, sz);
1439 static time_t _popTimeBlob(
const char*& p,
const char* end) {
1440 const uint64_t i = _popIntBlob<uint64_t>(p, end);
1444 static DataType _popDataTypeBlob(
const char*& p,
const char* end) {
1445 _Blob blob = _decodeBlob(p, end);
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);
1457 static UID _popUIDBlob(
const char*& p,
const char* end) {
1458 _Blob blob = _decodeBlob(p, end);
1463 throw Exception(
"Decode Error: premature end of UID blob");
1465 const ID id = (
ID) _popIntBlob<size_t>(p, end);
1466 const size_t size = _popIntBlob<size_t>(p, end);
1468 const UID uid = {
id, size };
1472 static UIDChain _popUIDChainBlob(
const char*& p,
const char* end) {
1473 _Blob blob = _decodeBlob(p, end);
1479 const UID uid = _popUIDBlob(p, end);
1480 chain.push_back(uid);
1482 assert(!chain.empty());
1486 static Member _popMemberBlob(
const char*& p,
const char* end) {
1487 _Blob blob = _decodeBlob(p, end,
false);
1492 if (p >= end)
return m;
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);
1499 assert(!m.
name().empty());
1504 static std::vector<Member> _popMembersBlob(
const char*& p,
const char* end) {
1505 _Blob blob = _decodeBlob(p, end,
false);
1509 std::vector<Member> members;
1511 const Member member = _popMemberBlob(p, end);
1513 members.push_back(member);
1520 static void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj) {
1523 obj.m_data.resize(type.
size());
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);
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);
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);
1555 }
else if (type.
isBool()) {
1556 _popIntBlob<uint8_t>(p, end, obj.m_data);
1563 _Blob blob = _decodeBlob(p, end,
false);
1569 static Object _popObjectBlob(
const char*& p,
const char* end) {
1570 _Blob blob = _decodeBlob(p, end,
false);
1575 if (p >= end)
return obj;
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);
1587 void Archive::_popObjectsBlob(
const char*& p,
const char* end) {
1588 _Blob blob = _decodeBlob(p, end,
false);
1593 throw Exception(
"Decode Error: Premature end of objects blob");
1596 const Object obj = _popObjectBlob(p, end);
1598 m_allObjects[obj.
uid()] = obj;
1602 void Archive::_popRootBlob(
const char*& p,
const char* end) {
1603 _Blob blob = _decodeBlob(p, end,
false);
1608 throw Exception(
"Decode Error: Premature end of root blob");
1612 const int formatMinorVersion = _popIntBlob<int>(p, end);
1614 m_root = _popUIDBlob(p, end);
1616 throw Exception(
"Decode Error: No root object");
1618 _popObjectsBlob(p, end);
1619 if (!m_allObjects[m_root])
1620 throw Exception(
"Decode Error: Missing declared root object");
1622 m_name = _popStringBlob(p, end);
1623 m_comment = _popStringBlob(p, end);
1624 m_timeCreated = _popTimeBlob(p, end);
1625 m_timeModified = _popTimeBlob(p, end);
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);
1678 rawData.resize(size);
1679 memcpy(&rawData[0], data, size);
1699 if (m_isModified) encode();
1727 return m_isModified;
1736 m_allObjects.clear();
1737 m_operation = OPERATION_NONE;
1740 m_isModified =
false;
1741 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1765 if (m_name == name)
return;
1767 m_isModified =
true;
1791 if (m_comment == comment)
return;
1792 m_comment = comment;
1793 m_isModified =
true;
1796 static tm _convertTimeStamp(
const time_t& time,
time_base_t base) {
1800 pTm = localtime(&time);
1803 pTm = gmtime(&time);
1806 throw Exception(
"Time stamp with unknown time base (" + ToString((int64_t)base) +
") requested");
1809 throw Exception(
"Failed assembling time stamp structure");
1819 return m_timeCreated;
1828 return m_timeModified;
1842 return _convertTimeStamp(m_timeCreated, base);
1856 return _convertTimeStamp(m_timeModified, base);
1877 parent.remove(member);
1878 m_isModified =
true;
1898 if (!obj.
uid())
return;
1899 m_allObjects.erase(obj.
uid());
1900 m_isModified =
true;
1915 return m_allObjects[uid];
1929 if (!
object)
return;
1930 object.setVersion(v);
1931 m_isModified =
true;
1945 if (!
object)
return;
1946 object.setMinVersion(v);
1947 m_isModified =
true;
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));
1968 const int nativeEnumSize =
sizeof(
enum operation_t);
1972 if (type.
size() != nativeEnumSize) {
1973 type.m_size = nativeEnumSize;
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;
1987 m_isModified =
true;
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));
2011 pObject->m_data.resize(type.
size());
2012 void* ptr = &pObject->m_data[0];
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;
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;
2036 m_isModified =
true;
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));
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;
2069 m_isModified =
true;
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));
2091 pObject->m_data.resize(type.
size());
2092 bool* ptr = (
bool*)&pObject->m_data[0];
2094 m_isModified =
true;
2111 if (!
object)
return;
2112 const DataType& type =
object.type();
2114 setIntValue(
object, atoll(value.c_str()));
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);
2124 setBoolValue(
object, atof(value.c_str()));
2125 }
else if (type.
isEnum())
2126 setEnumValue(
object, atoll(value.c_str()));
2128 throw Exception(
"Not a primitive data type");
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 "";
2151 return _primitiveObjectValueToString(*pObject);
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));
2174 return _primitiveObjectValueToNumber<int64_t>(*pObject);
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));
2197 return _primitiveObjectValueToNumber<double>(*pObject);
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));
2219 return _primitiveObjectValueToNumber<bool>(*pObject);
2226 : m_dst(dst), m_src(src)
2231 throw Exception(
"No source root object!");
2233 throw Exception(
"Expected destination root object not found!");
2234 syncObject(dstRootObj, srcRootObj);
2237 void Archive::Syncer::syncPrimitive(
const Object& dstObj,
const Object& srcObj) {
2239 void* pDst = (
void*)dstObj.
uid().
id;
2243 void Archive::Syncer::syncPointer(
const Object& dstObj,
const Object& srcObj) {
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);
2251 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2252 if (!dstObj || !srcObj)
return;
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 " +
2259 if (dstObj.
type() != srcObj.
type())
2260 throw Exception(
"Incompatible data structure type (destination type " +
2266 m_dst.m_allObjects.erase(dstObj.
uid());
2269 syncPrimitive(dstObj, srcObj);
2274 syncPointer(dstObj, srcObj);
2279 for (
int iMember = 0; iMember < srcObj.
members().size(); ++iMember) {
2281 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2283 throw Exception(
"Expected member missing in destination object");
2284 syncMember(dstMember, srcMember);
2291 return (dstMember.
type() == srcMember.
type()) ? dstMember :
Member();
2293 if (members.size() <= 0)
2295 if (members.size() == 1)
2297 for (
int i = 0; i < members.size(); ++i)
2298 if (members[i].offset() == srcMember.
offset())
2301 assert(srcSeqNr >= 0);
2302 for (
int i = 0; i < members.size(); ++i) {
2304 if (dstSeqNr == srcSeqNr)
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);
2321 Exception::Exception() {
2324 Exception::Exception(String format, ...) {
2326 va_start(arg, format);
2327 Message = assemble(format, arg);
2331 Exception::Exception(String format, va_list arg) {
2332 Message = assemble(format, arg);
2341 std::cout <<
"Serialization::Exception: " << Message << std::endl;
2344 String Exception::assemble(String format, va_list arg) {
2346 vasprintf(&buf, format.c_str(), arg);
String customTypeName(bool demangle=false) const
The 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.
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.
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.
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).
bool isReal() const
Whether this is a floating point based C/C++ data type.
UID uid() const
Unique identifier of this member instance.
void setBoolValue(Object &object, bool value)
Set new boolean value for given boolean object.
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 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.
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.
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.
size_t offset() const
Offset of member in its containing parent data structure.
String name() const
Name of the member.