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;
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 &&
271 m_isPointer == other.m_isPointer;
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)))));
334 String s = m_baseTypeName;
335 if (!m_customTypeName.empty())
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;
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)))));
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;
859 return m_uid < other.m_uid ||
860 (m_uid == other.m_uid &&
861 m_type < other.m_type);
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)
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];
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) {
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);
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) {
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);
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) {
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;
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()));
1295 s += _encode(obj.uidChain());
1296 s += _encode(obj.members());
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());
1500 assert(m.uid().isValid());
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) {
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);
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);
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;
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()) {
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()) {
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()) {
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()) {
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();
2117 else if (type.
isBool()) {
2118 String val = toLowerCase(value);
2119 if (val ==
"true" || val ==
"yes" || val ==
"1")
2121 else if (val ==
"false" || val ==
"no" || val ==
"0")
2125 }
else if (type.
isEnum())
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()) {
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()) {
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()) {
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()) {
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) {
2238 assert(srcObj.rawData().size() == dstObj.type().size());
2239 void* pDst = (
void*)dstObj.uid().id;
2240 memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
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);
2251 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2252 if (!dstObj || !srcObj)
return;
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() +
")");
2266 m_dst.m_allObjects.erase(dstObj.uid());
2268 if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2269 syncPrimitive(dstObj, srcObj);
2273 if (dstObj.type().isPointer()) {
2274 syncPointer(dstObj, srcObj);
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);
2283 throw Exception(
"Expected member missing in destination object");
2284 syncMember(dstMember, srcMember);
2288 Member Archive::Syncer::dstMemberMatching(
const Object& dstObj,
const Object& srcObj,
const Member& srcMember) {
2289 Member dstMember = dstObj.memberNamed(srcMember.name());
2291 return (dstMember.type() == srcMember.type()) ? dstMember : Member();
2292 std::vector<Member> members = dstObj.membersOfType(srcMember.type());
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())
2300 const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
2301 assert(srcSeqNr >= 0);
2302 for (
int i = 0; i < members.size(); ++i) {
2303 const int dstSeqNr = dstObj.sequenceIndexOf(members[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);