24 #include "Serialization.h" 34 #define LIBGIG_EPOCH_TIME ((time_t)0) 41 static UID _createNullUID() {
42 const UID uid = { NULL, 0 };
60 return id != NULL &&
id != (
void*)-1 &&
size;
83 m_baseTypeName = baseType;
84 m_customTypeName = customType;
131 return m_baseTypeName ==
"class";
173 return m_baseTypeName.substr(0, 3) ==
"int" ||
174 m_baseTypeName.substr(0, 4) ==
"uint";
190 return m_baseTypeName.substr(0, 4) ==
"real";
205 return m_baseTypeName ==
"bool";
220 return m_baseTypeName ==
"enum";
237 return m_baseTypeName.substr(0, 3) ==
"int" ||
260 return m_baseTypeName == other.m_baseTypeName &&
261 m_customTypeName == other.m_customTypeName &&
263 m_isPointer == other.m_isPointer;
287 return m_baseTypeName < other.m_baseTypeName ||
288 (m_baseTypeName == other.m_baseTypeName &&
289 m_customTypeName < other.m_customTypeName ||
290 (m_customTypeName == other.m_customTypeName &&
291 m_size < other.m_size ||
292 (m_size == other.m_size &&
293 m_isPointer < other.m_isPointer)));
326 String s = m_baseTypeName;
327 if (!m_customTypeName.empty())
364 return m_baseTypeName;
401 if (!demangle)
return m_customTypeName;
404 abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
405 return (status == 0) ? result : m_customTypeName;
534 return m_uid && !m_name.empty() && m_type;
546 return m_uid == other.m_uid &&
547 m_offset == other.m_offset &&
548 m_name == other.m_name &&
549 m_type == other.m_type;
574 return m_uid < other.m_uid ||
575 (m_uid == other.m_uid &&
576 m_offset < other.m_offset ||
577 (m_offset == other.m_offset &&
578 m_name < other.m_name ||
579 (m_name == other.m_name &&
580 m_type < other.m_type)));
654 return m_type && !m_uid.empty();
669 return (index < m_uid.size()) ? m_uid[index] :
NO_UID;
804 return m_uid == other.m_uid &&
805 m_type == other.m_type;
832 return m_uid < other.m_uid ||
833 (m_uid == other.m_uid &&
834 m_type < other.m_type);
880 void Object::setVersion(
Version v) {
884 void Object::setMinVersion(
Version v) {
918 for (
int i = 0; i < m_members.size(); ++i)
919 if (m_members[i].name() == name)
940 for (
int i = 0; i < m_members.size(); ++i)
941 if (m_members[i].
uid() ==
uid)
946 void Object::remove(
const Member& member) {
947 for (
int i = 0; i < m_members.size(); ++i) {
948 if (m_members[i] == member) {
949 m_members.erase(m_members.begin() + i);
971 std::vector<Member> v;
972 for (
int i = 0; i < m_members.size(); ++i) {
973 const Member& member = m_members[i];
1012 for (
int i = 0; i < m_members.size(); ++i)
1013 if (m_members[i] == member)
1040 m_operation = OPERATION_NONE;
1042 m_isModified =
false;
1043 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1062 m_operation = OPERATION_NONE;
1064 m_isModified =
false;
1065 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1090 m_operation = OPERATION_NONE;
1092 m_isModified =
false;
1093 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1097 Archive::~Archive() {
1111 return m_allObjects[m_root];
1114 static String _encodeBlob(String data) {
1115 return ToString(data.length()) +
":" + data;
1118 static String _encode(
const UID& uid) {
1120 s += _encodeBlob(ToString(
size_t(uid.id)));
1121 s += _encodeBlob(ToString(
size_t(uid.size)));
1122 return _encodeBlob(s);
1125 static String _encode(
const time_t& time) {
1126 return _encodeBlob(ToString(time));
1129 static String _encode(
const DataType& type) {
1131 s += _encodeBlob(type.baseTypeName());
1132 s += _encodeBlob(type.customTypeName());
1133 s += _encodeBlob(ToString(type.size()));
1134 s += _encodeBlob(ToString(type.isPointer()));
1135 return _encodeBlob(s);
1138 static String _encode(
const UIDChain& chain) {
1140 for (
int i = 0; i < chain.size(); ++i)
1141 s += _encode(chain[i]);
1142 return _encodeBlob(s);
1145 static String _encode(
const Member& member) {
1147 s += _encode(member.uid());
1148 s += _encodeBlob(ToString(member.offset()));
1149 s += _encodeBlob(member.name());
1150 s += _encode(member.type());
1151 return _encodeBlob(s);
1154 static String _encode(
const std::vector<Member>& members) {
1156 for (
int i = 0; i < members.size(); ++i)
1157 s += _encode(members[i]);
1158 return _encodeBlob(s);
1161 static String _primitiveObjectValueToString(
const Object& obj) {
1163 const DataType& type = obj.type();
1164 const ID&
id = obj.uid().id;
1165 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1166 if (!obj.m_data.empty())
1167 assert(type.size() == obj.m_data.size());
1168 if (type.isPrimitive() && !type.isPointer()) {
1169 if (type.isInteger() || type.isEnum()) {
1170 if (type.isSigned()) {
1171 if (type.size() == 1)
1172 s = ToString((int16_t)*(int8_t*)ptr);
1173 else if (type.size() == 2)
1174 s = ToString(*(int16_t*)ptr);
1175 else if (type.size() == 4)
1176 s = ToString(*(int32_t*)ptr);
1177 else if (type.size() == 8)
1178 s = ToString(*(int64_t*)ptr);
1182 if (type.size() == 1)
1183 s = ToString((uint16_t)*(uint8_t*)ptr);
1184 else if (type.size() == 2)
1185 s = ToString(*(uint16_t*)ptr);
1186 else if (type.size() == 4)
1187 s = ToString(*(uint32_t*)ptr);
1188 else if (type.size() == 8)
1189 s = ToString(*(uint64_t*)ptr);
1193 }
else if (type.isReal()) {
1194 if (type.size() ==
sizeof(float))
1195 s = ToString(*(
float*)ptr);
1196 else if (type.size() ==
sizeof(double))
1197 s = ToString(*(
double*)ptr);
1200 }
else if (type.isBool()) {
1201 s = ToString(*(
bool*)ptr);
1210 template<
typename T>
1211 static T _primitiveObjectValueToNumber(
const Object& obj) {
1213 const DataType& type = obj.type();
1214 const ID&
id = obj.uid().id;
1215 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1216 if (!obj.m_data.empty())
1217 assert(type.size() == obj.m_data.size());
1218 if (type.isPrimitive() && !type.isPointer()) {
1219 if (type.isInteger() || type.isEnum()) {
1220 if (type.isSigned()) {
1221 if (type.size() == 1)
1222 value = (T)*(int8_t*)ptr;
1223 else if (type.size() == 2)
1224 value = (T)*(int16_t*)ptr;
1225 else if (type.size() == 4)
1226 value = (T)*(int32_t*)ptr;
1227 else if (type.size() == 8)
1228 value = (T)*(int64_t*)ptr;
1232 if (type.size() == 1)
1233 value = (T)*(uint8_t*)ptr;
1234 else if (type.size() == 2)
1235 value = (T)*(uint16_t*)ptr;
1236 else if (type.size() == 4)
1237 value = (T)*(uint32_t*)ptr;
1238 else if (type.size() == 8)
1239 value = (T)*(uint64_t*)ptr;
1243 }
else if (type.isReal()) {
1244 if (type.size() ==
sizeof(float))
1245 value = (T)*(
float*)ptr;
1246 else if (type.size() ==
sizeof(double))
1247 value = (T)*(
double*)ptr;
1250 }
else if (type.isBool()) {
1251 value = (T)*(
bool*)ptr;
1259 static String _encodePrimitiveValue(
const Object& obj) {
1260 return _encodeBlob( _primitiveObjectValueToString(obj) );
1263 static String _encode(
const Object& obj) {
1265 s += _encode(obj.type());
1266 s += _encodeBlob(ToString(obj.version()));
1267 s += _encodeBlob(ToString(obj.minVersion()));
1268 s += _encode(obj.uidChain());
1269 s += _encode(obj.members());
1270 s += _encodePrimitiveValue(obj);
1271 return _encodeBlob(s);
1274 String _encode(
const Archive::ObjectPool& objects) {
1276 for (Archive::ObjectPool::const_iterator itObject = objects.begin();
1277 itObject != objects.end(); ++itObject)
1279 const Object& obj = itObject->second;
1282 return _encodeBlob(s);
1285 #define MAGIC_START "Srx1v" 1286 #define ENCODING_FORMAT_MINOR_VERSION 0 1288 String Archive::_encodeRootBlob() {
1290 s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
1291 s += _encode(m_root);
1292 s += _encode(m_allObjects);
1293 s += _encodeBlob(m_name);
1294 s += _encodeBlob(m_comment);
1295 s += _encode(m_timeCreated);
1296 s += _encode(m_timeModified);
1297 return _encodeBlob(s);
1300 void Archive::encode() {
1302 String s = MAGIC_START;
1303 m_timeModified = time(NULL);
1304 if (m_timeCreated == LIBGIG_EPOCH_TIME)
1305 m_timeCreated = m_timeModified;
1306 s += _encodeRootBlob();
1307 m_rawData.resize(s.length() + 1);
1308 memcpy(&m_rawData[0], &s[0], s.length() + 1);
1309 m_isModified =
false;
1317 static _Blob _decodeBlob(
const char* p,
const char* end,
bool bThrow =
true) {
1318 if (!bThrow && p >= end) {
1319 const _Blob blob = { p, end };
1325 throw Exception(
"Decode Error: Missing blob");
1327 if (c ==
':')
break;
1328 if (c < '0' || c >
'9')
1329 throw Exception(
"Decode Error: Missing blob size");
1331 sz += size_t(c -
'0');
1335 throw Exception(
"Decode Error: Premature end of blob");
1336 const _Blob blob = { p, p + sz };
1340 template<
typename T_
int>
1341 static T_int _popIntBlob(
const char*& p,
const char* end) {
1342 _Blob blob = _decodeBlob(p, end);
1349 throw Exception(
"Decode Error: premature end of int blob");
1354 for (; p < end; ++p) {
1356 if (c < '0' || c >
'9')
1357 throw Exception(
"Decode Error: Invalid int blob format");
1359 i += size_t(c -
'0');
1364 template<
typename T_
int>
1365 static void _popIntBlob(
const char*& p,
const char* end,
RawData& rawData) {
1366 const T_int i = _popIntBlob<T_int>(p, end);
1367 *(T_int*)&rawData[0] = i;
1370 template<
typename T_real>
1371 static T_real _popRealBlob(
const char*& p,
const char* end) {
1372 _Blob blob = _decodeBlob(p, end);
1376 if (p >= end || (end - p) < 1)
1377 throw Exception(
"Decode Error: premature end of real blob");
1379 String s(p,
size_t(end - p));
1382 if (
sizeof(T_real) <=
sizeof(
double))
1383 r = atof(s.c_str());
1392 template<
typename T_real>
1393 static void _popRealBlob(
const char*& p,
const char* end,
RawData& rawData) {
1394 const T_real r = _popRealBlob<T_real>(p, end);
1395 *(T_real*)&rawData[0] = r;
1398 static String _popStringBlob(
const char*& p,
const char* end) {
1399 _Blob blob = _decodeBlob(p, end);
1403 throw Exception(
"Decode Error: missing String blob");
1405 const size_t sz = end - p;
1407 memcpy(&s[0], p, sz);
1412 static time_t _popTimeBlob(
const char*& p,
const char* end) {
1413 const uint64_t i = _popIntBlob<uint64_t>(p, end);
1417 DataType _popDataTypeBlob(
const char*& p,
const char* end) {
1418 _Blob blob = _decodeBlob(p, end);
1423 type.m_baseTypeName = _popStringBlob(p, end);
1424 type.m_customTypeName = _popStringBlob(p, end);
1425 type.m_size = _popIntBlob<int>(p, end);
1426 type.m_isPointer = _popIntBlob<bool>(p, end);
1430 static UID _popUIDBlob(
const char*& p,
const char* end) {
1431 _Blob blob = _decodeBlob(p, end);
1436 throw Exception(
"Decode Error: premature end of UID blob");
1438 const ID id = (
ID) _popIntBlob<size_t>(p, end);
1439 const size_t size = _popIntBlob<size_t>(p, end);
1441 const UID uid = { id, size };
1445 static UIDChain _popUIDChainBlob(
const char*& p,
const char* end) {
1446 _Blob blob = _decodeBlob(p, end);
1452 const UID uid = _popUIDBlob(p, end);
1453 chain.push_back(uid);
1455 assert(!chain.empty());
1459 static Member _popMemberBlob(
const char*& p,
const char* end) {
1460 _Blob blob = _decodeBlob(p, end,
false);
1465 if (p >= end)
return m;
1467 m.m_uid = _popUIDBlob(p, end);
1468 m.m_offset = _popIntBlob<size_t>(p, end);
1469 m.m_name = _popStringBlob(p, end);
1470 m.m_type = _popDataTypeBlob(p, end);
1472 assert(!m.name().empty());
1473 assert(m.uid().isValid());
1477 static std::vector<Member> _popMembersBlob(
const char*& p,
const char* end) {
1478 _Blob blob = _decodeBlob(p, end,
false);
1482 std::vector<Member> members;
1484 const Member member = _popMemberBlob(p, end);
1486 members.push_back(member);
1493 static void _popPrimitiveValue(
const char*& p,
const char* end, Object& obj) {
1494 const DataType& type = obj.type();
1495 if (type.isPrimitive() && !type.isPointer()) {
1496 obj.m_data.resize(type.size());
1497 if (type.isInteger() || type.isEnum()) {
1498 if (type.isSigned()) {
1499 if (type.size() == 1)
1500 _popIntBlob<int8_t>(p, end, obj.m_data);
1501 else if (type.size() == 2)
1502 _popIntBlob<int16_t>(p, end, obj.m_data);
1503 else if (type.size() == 4)
1504 _popIntBlob<int32_t>(p, end, obj.m_data);
1505 else if (type.size() == 8)
1506 _popIntBlob<int64_t>(p, end, obj.m_data);
1510 if (type.size() == 1)
1511 _popIntBlob<uint8_t>(p, end, obj.m_data);
1512 else if (type.size() == 2)
1513 _popIntBlob<uint16_t>(p, end, obj.m_data);
1514 else if (type.size() == 4)
1515 _popIntBlob<uint32_t>(p, end, obj.m_data);
1516 else if (type.size() == 8)
1517 _popIntBlob<uint64_t>(p, end, obj.m_data);
1521 }
else if (type.isReal()) {
1522 if (type.size() ==
sizeof(float))
1523 _popRealBlob<float>(p, end, obj.m_data);
1524 else if (type.size() ==
sizeof(double))
1525 _popRealBlob<double>(p, end, obj.m_data);
1528 }
else if (type.isBool()) {
1529 _popIntBlob<uint8_t>(p, end, obj.m_data);
1536 _Blob blob = _decodeBlob(p, end,
false);
1542 static Object _popObjectBlob(
const char*& p,
const char* end) {
1543 _Blob blob = _decodeBlob(p, end,
false);
1548 if (p >= end)
return obj;
1550 obj.m_type = _popDataTypeBlob(p, end);
1551 obj.m_version = _popIntBlob<Version>(p, end);
1552 obj.m_minVersion = _popIntBlob<Version>(p, end);
1553 obj.m_uid = _popUIDChainBlob(p, end);
1554 obj.m_members = _popMembersBlob(p, end);
1555 _popPrimitiveValue(p, end, obj);
1560 void Archive::_popObjectsBlob(
const char*& p,
const char* end) {
1561 _Blob blob = _decodeBlob(p, end,
false);
1566 throw Exception(
"Decode Error: Premature end of objects blob");
1569 const Object obj = _popObjectBlob(p, end);
1571 m_allObjects[obj.uid()] = obj;
1575 void Archive::_popRootBlob(
const char*& p,
const char* end) {
1576 _Blob blob = _decodeBlob(p, end,
false);
1581 throw Exception(
"Decode Error: Premature end of root blob");
1585 const int formatMinorVersion = _popIntBlob<int>(p, end);
1587 m_root = _popUIDBlob(p, end);
1589 throw Exception(
"Decode Error: No root object");
1591 _popObjectsBlob(p, end);
1592 if (!m_allObjects[m_root])
1593 throw Exception(
"Decode Error: Missing declared root object");
1595 m_name = _popStringBlob(p, end);
1596 m_comment = _popStringBlob(p, end);
1597 m_timeCreated = _popTimeBlob(p, end);
1598 m_timeModified = _popTimeBlob(p, end);
1618 m_allObjects.clear();
1619 m_isModified =
false;
1620 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1621 const char* p = (
const char*) &data[0];
1622 const char* end = p + data.size();
1623 if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
1624 throw Exception(
"Decode Error: Magic start missing!");
1625 p += strlen(MAGIC_START);
1626 _popRootBlob(p, end);
1652 memcpy(&
rawData[0], data, size);
1672 if (m_isModified) encode();
1700 return m_isModified;
1709 m_allObjects.clear();
1710 m_operation = OPERATION_NONE;
1713 m_isModified =
false;
1714 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1738 if (m_name ==
name)
return;
1740 m_isModified =
true;
1764 if (m_comment ==
comment)
return;
1766 m_isModified =
true;
1769 static tm _convertTimeStamp(
const time_t& time,
time_base_t base) {
1773 pTm = localtime(&time);
1776 pTm = gmtime(&time);
1779 throw Exception(
"Time stamp with unknown time base (" + ToString((int64_t)base) +
") requested");
1782 throw Exception(
"Failed assembling time stamp structure");
1792 return m_timeCreated;
1801 return m_timeModified;
1815 return _convertTimeStamp(m_timeCreated, base);
1829 return _convertTimeStamp(m_timeModified, base);
1850 parent.remove(member);
1851 m_isModified =
true;
1871 if (!obj.
uid())
return;
1872 m_allObjects.erase(obj.
uid());
1873 m_isModified =
true;
1888 return m_allObjects[uid];
1902 if (!
object)
return;
1903 object.setVersion(v);
1904 m_isModified =
true;
1918 if (!
object)
return;
1919 object.setMinVersion(v);
1920 m_isModified =
true;
1932 if (!
object)
return;
1933 if (!
object.type().isEnum())
1934 throw Exception(
"Not an enum data type");
1935 Object* pObject = &object;
1936 if (
object.type().isPointer()) {
1941 const int nativeEnumSize =
sizeof(
enum operation_t);
1942 DataType& type = const_cast<DataType&>( pObject->
type() );
1945 if (type.
size() != nativeEnumSize) {
1946 type.m_size = nativeEnumSize;
1948 pObject->m_data.resize(type.
size());
1949 void* ptr = &pObject->m_data[0];
1950 if (type.
size() == 1)
1951 *(uint8_t*)ptr = (uint8_t)value;
1952 else if (type.
size() == 2)
1953 *(uint16_t*)ptr = (uint16_t)value;
1954 else if (type.
size() == 4)
1955 *(uint32_t*)ptr = (uint32_t)value;
1956 else if (type.
size() == 8)
1957 *(uint64_t*)ptr = (uint64_t)value;
1960 m_isModified =
true;
1974 if (!
object)
return;
1975 if (!
object.type().isInteger())
1976 throw Exception(
"Not an integer data type");
1977 Object* pObject = &object;
1978 if (
object.type().isPointer()) {
1984 pObject->m_data.resize(type.
size());
1985 void* ptr = &pObject->m_data[0];
1987 if (type.
size() == 1)
1988 *(int8_t*)ptr = (int8_t)value;
1989 else if (type.
size() == 2)
1990 *(int16_t*)ptr = (int16_t)value;
1991 else if (type.
size() == 4)
1992 *(int32_t*)ptr = (int32_t)value;
1993 else if (type.
size() == 8)
1994 *(int64_t*)ptr = (int64_t)value;
1998 if (type.
size() == 1)
1999 *(uint8_t*)ptr = (uint8_t)value;
2000 else if (type.
size() == 2)
2001 *(uint16_t*)ptr = (uint16_t)value;
2002 else if (type.
size() == 4)
2003 *(uint32_t*)ptr = (uint32_t)value;
2004 else if (type.
size() == 8)
2005 *(uint64_t*)ptr = (uint64_t)value;
2009 m_isModified =
true;
2024 if (!
object)
return;
2025 if (!
object.type().isReal())
2026 throw Exception(
"Not a real data type");
2027 Object* pObject = &object;
2028 if (
object.type().isPointer()) {
2034 pObject->m_data.resize(type.
size());
2035 void* ptr = &pObject->m_data[0];
2036 if (type.
size() ==
sizeof(float))
2037 *(
float*)ptr = (
float)value;
2038 else if (type.
size() ==
sizeof(double))
2039 *(
double*)ptr = (
double)value;
2042 m_isModified =
true;
2054 if (!
object)
return;
2055 if (!
object.type().isBool())
2056 throw Exception(
"Not a bool data type");
2057 Object* pObject = &object;
2058 if (
object.type().isPointer()) {
2064 pObject->m_data.resize(type.
size());
2065 bool* ptr = (
bool*)&pObject->m_data[0];
2067 m_isModified =
true;
2084 if (!
object)
return;
2085 const DataType& type =
object.type();
2090 else if (type.
isBool()) {
2091 String val = toLowerCase(value);
2092 if (val ==
"true" || val ==
"yes" || val ==
"1")
2094 else if (val ==
"false" || val ==
"no" || val ==
"0")
2098 }
else if (type.
isEnum())
2101 throw Exception(
"Not a primitive data type");
2116 if (
object.type().isClass())
2117 throw Exception(
"Object is class type");
2118 const Object* pObject = &object;
2119 if (
object.type().isPointer()) {
2121 if (!obj)
return "";
2124 return _primitiveObjectValueToString(*pObject);
2139 if (!
object.type().isInteger() && !
object.type().isEnum())
2140 throw Exception(
"Object is neither an integer nor an enum");
2141 const Object* pObject = &object;
2142 if (
object.type().isPointer()) {
2147 return _primitiveObjectValueToNumber<int64_t>(*pObject);
2162 if (!
object.type().isReal())
2163 throw Exception(
"Object is not an real type");
2164 const Object* pObject = &object;
2165 if (
object.type().isPointer()) {
2170 return _primitiveObjectValueToNumber<double>(*pObject);
2184 if (!
object.type().isBool())
2185 throw Exception(
"Object is not a bool");
2186 const Object* pObject = &object;
2187 if (
object.type().isPointer()) {
2192 return _primitiveObjectValueToNumber<bool>(*pObject);
2199 : m_dst(dst), m_src(src)
2204 throw Exception(
"No source root object!");
2206 throw Exception(
"Expected destination root object not found!");
2207 syncObject(dstRootObj, srcRootObj);
2210 void Archive::Syncer::syncPrimitive(
const Object& dstObj,
const Object& srcObj) {
2211 assert(srcObj.rawData().size() == dstObj.type().size());
2212 void* pDst = (
void*)dstObj.uid().id;
2213 memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
2216 void Archive::Syncer::syncPointer(
const Object& dstObj,
const Object& srcObj) {
2217 assert(dstObj.type().isPointer());
2218 assert(dstObj.type() == srcObj.type());
2219 const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
2220 const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
2221 syncObject(pointedDstObject, pointedSrcObject);
2224 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2225 if (!dstObj || !srcObj)
return;
2226 if (!dstObj.isVersionCompatibleTo(srcObj))
2227 throw Exception(
"Version incompatible (destination version " +
2228 ToString(dstObj.version()) +
" [min. version " +
2229 ToString(dstObj.minVersion()) +
"], source version " +
2230 ToString(srcObj.version()) +
" [min. version " +
2231 ToString(srcObj.minVersion()) +
"])");
2232 if (dstObj.type() != srcObj.type())
2233 throw Exception(
"Incompatible data structure type (destination type " +
2234 dstObj.type().asLongDescr() +
" vs. source type " +
2235 srcObj.type().asLongDescr() +
")");
2239 m_dst.m_allObjects.erase(dstObj.uid());
2241 if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2242 syncPrimitive(dstObj, srcObj);
2246 if (dstObj.type().isPointer()) {
2247 syncPointer(dstObj, srcObj);
2251 assert(dstObj.type().isClass());
2252 for (
int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
2253 const Member& srcMember = srcObj.members()[iMember];
2254 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2256 throw Exception(
"Expected member missing in destination object");
2257 syncMember(dstMember, srcMember);
2261 Member Archive::Syncer::dstMemberMatching(
const Object& dstObj,
const Object& srcObj,
const Member& srcMember) {
2262 Member dstMember = dstObj.memberNamed(srcMember.name());
2264 return (dstMember.type() == srcMember.type()) ? dstMember : Member();
2265 std::vector<Member> members = dstObj.membersOfType(srcMember.type());
2266 if (members.size() <= 0)
2268 if (members.size() == 1)
2270 for (
int i = 0; i < members.size(); ++i)
2271 if (members[i].offset() == srcMember.offset())
2273 const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
2274 assert(srcSeqNr >= 0);
2275 for (
int i = 0; i < members.size(); ++i) {
2276 const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
2277 if (dstSeqNr == srcSeqNr)
2283 void Archive::Syncer::syncMember(
const Member& dstMember,
const Member& srcMember) {
2284 assert(dstMember && srcMember);
2285 assert(dstMember.type() == srcMember.type());
2286 const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
2287 const Object srcObj = m_src.m_allObjects[srcMember.uid()];
2288 syncObject(dstObj, srcObj);
2294 Exception::Exception() {
2297 Exception::Exception(String format, ...) {
2299 va_start(arg, format);
2300 Message = assemble(format, arg);
2304 Exception::Exception(String format, va_list arg) {
2305 Message = assemble(format, arg);
2314 std::cout <<
"Serialization::Exception: " << Message << std::endl;
2317 String Exception::assemble(String format, va_list arg) {
2319 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.
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.