26 #define LIBGIG_SERIALIZATION_INTERNAL 1 28 #include "Serialization.h" 38 #define LIBGIG_EPOCH_TIME ((time_t)0) 45 static UID _createNullUID() {
46 const UID uid = { NULL, 0 };
64 return id != NULL &&
id != (
void*)-1 &&
size;
87 m_baseTypeName = baseType;
88 m_customTypeName = customType;
135 return m_baseTypeName ==
"class";
177 return m_baseTypeName.substr(0, 3) ==
"int" ||
178 m_baseTypeName.substr(0, 4) ==
"uint";
194 return m_baseTypeName.substr(0, 4) ==
"real";
209 return m_baseTypeName ==
"bool";
224 return m_baseTypeName ==
"enum";
241 return m_baseTypeName.substr(0, 3) ==
"int" ||
264 return m_baseTypeName == other.m_baseTypeName &&
265 m_customTypeName == other.m_customTypeName &&
267 m_isPointer == other.m_isPointer;
291 return m_baseTypeName < other.m_baseTypeName ||
292 (m_baseTypeName == other.m_baseTypeName &&
293 (m_customTypeName < other.m_customTypeName ||
294 (m_customTypeName == other.m_customTypeName &&
295 (m_size < other.m_size ||
296 (m_size == other.m_size &&
297 m_isPointer < other.m_isPointer)))));
330 String s = m_baseTypeName;
331 if (!m_customTypeName.empty())
368 return m_baseTypeName;
405 if (!demangle)
return m_customTypeName;
408 abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
409 return (status == 0) ? result : m_customTypeName;
538 return m_uid && !m_name.empty() && m_type;
550 return m_uid == other.m_uid &&
551 m_offset == other.m_offset &&
552 m_name == other.m_name &&
553 m_type == other.m_type;
578 return m_uid < other.m_uid ||
579 (m_uid == other.m_uid &&
580 (m_offset < other.m_offset ||
581 (m_offset == other.m_offset &&
582 (m_name < other.m_name ||
583 (m_name == other.m_name &&
584 m_type < other.m_type)))));
658 return m_type && !m_uid.empty();
673 return (index < m_uid.size()) ? m_uid[index] :
NO_UID;
808 return m_uid == other.m_uid &&
809 m_type == other.m_type;
836 return m_uid < other.m_uid ||
837 (m_uid == other.m_uid &&
838 m_type < other.m_type);
884 void Object::setVersion(
Version v) {
888 void Object::setMinVersion(
Version v) {
922 for (
int i = 0; i < m_members.size(); ++i)
923 if (m_members[i].name() == name)
944 for (
int i = 0; i < m_members.size(); ++i)
945 if (m_members[i].
uid() ==
uid)
950 void Object::remove(
const Member& member) {
951 for (
int i = 0; i < m_members.size(); ++i) {
952 if (m_members[i] == member) {
953 m_members.erase(m_members.begin() + i);
975 std::vector<Member> v;
976 for (
int i = 0; i < m_members.size(); ++i) {
977 const Member& member = m_members[i];
1016 for (
int i = 0; i < m_members.size(); ++i)
1017 if (m_members[i] == member)
1044 m_operation = OPERATION_NONE;
1046 m_isModified =
false;
1047 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1066 m_operation = OPERATION_NONE;
1068 m_isModified =
false;
1069 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1094 m_operation = OPERATION_NONE;
1096 m_isModified =
false;
1097 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1101 Archive::~Archive() {
1115 return m_allObjects[m_root];
1118 static String _encodeBlob(String data) {
1119 return ToString(data.length()) +
":" + data;
1122 static String _encode(
const UID& uid) {
1124 s += _encodeBlob(ToString(
size_t(uid.id)));
1125 s += _encodeBlob(ToString(
size_t(uid.size)));
1126 return _encodeBlob(s);
1129 static String _encode(
const time_t& time) {
1130 return _encodeBlob(ToString(time));
1133 static String _encode(
const DataType& type) {
1135 s += _encodeBlob(type.baseTypeName());
1136 s += _encodeBlob(type.customTypeName());
1137 s += _encodeBlob(ToString(type.size()));
1138 s += _encodeBlob(ToString(type.isPointer()));
1139 return _encodeBlob(s);
1142 static String _encode(
const UIDChain& chain) {
1144 for (
int i = 0; i < chain.size(); ++i)
1145 s += _encode(chain[i]);
1146 return _encodeBlob(s);
1149 static String _encode(
const Member& member) {
1151 s += _encode(member.uid());
1152 s += _encodeBlob(ToString(member.offset()));
1153 s += _encodeBlob(member.name());
1154 s += _encode(member.type());
1155 return _encodeBlob(s);
1158 static String _encode(
const std::vector<Member>& members) {
1160 for (
int i = 0; i < members.size(); ++i)
1161 s += _encode(members[i]);
1162 return _encodeBlob(s);
1165 static String _primitiveObjectValueToString(
const Object& obj) {
1167 const DataType& type = obj.type();
1168 const ID&
id = obj.uid().id;
1169 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1170 if (!obj.m_data.empty())
1171 assert(type.size() == obj.m_data.size());
1172 if (type.isPrimitive() && !type.isPointer()) {
1173 if (type.isInteger() || type.isEnum()) {
1174 if (type.isSigned()) {
1175 if (type.size() == 1)
1176 s = ToString((int16_t)*(int8_t*)ptr);
1177 else if (type.size() == 2)
1178 s = ToString(*(int16_t*)ptr);
1179 else if (type.size() == 4)
1180 s = ToString(*(int32_t*)ptr);
1181 else if (type.size() == 8)
1182 s = ToString(*(int64_t*)ptr);
1186 if (type.size() == 1)
1187 s = ToString((uint16_t)*(uint8_t*)ptr);
1188 else if (type.size() == 2)
1189 s = ToString(*(uint16_t*)ptr);
1190 else if (type.size() == 4)
1191 s = ToString(*(uint32_t*)ptr);
1192 else if (type.size() == 8)
1193 s = ToString(*(uint64_t*)ptr);
1197 }
else if (type.isReal()) {
1198 if (type.size() ==
sizeof(float))
1199 s = ToString(*(
float*)ptr);
1200 else if (type.size() ==
sizeof(double))
1201 s = ToString(*(
double*)ptr);
1204 }
else if (type.isBool()) {
1205 s = ToString(*(
bool*)ptr);
1214 template<
typename T>
1215 static T _primitiveObjectValueToNumber(
const Object& obj) {
1217 const DataType& type = obj.type();
1218 const ID&
id = obj.uid().id;
1219 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1220 if (!obj.m_data.empty())
1221 assert(type.size() == obj.m_data.size());
1222 if (type.isPrimitive() && !type.isPointer()) {
1223 if (type.isInteger() || type.isEnum()) {
1224 if (type.isSigned()) {
1225 if (type.size() == 1)
1226 value = (T)*(int8_t*)ptr;
1227 else if (type.size() == 2)
1228 value = (T)*(int16_t*)ptr;
1229 else if (type.size() == 4)
1230 value = (T)*(int32_t*)ptr;
1231 else if (type.size() == 8)
1232 value = (T)*(int64_t*)ptr;
1236 if (type.size() == 1)
1237 value = (T)*(uint8_t*)ptr;
1238 else if (type.size() == 2)
1239 value = (T)*(uint16_t*)ptr;
1240 else if (type.size() == 4)
1241 value = (T)*(uint32_t*)ptr;
1242 else if (type.size() == 8)
1243 value = (T)*(uint64_t*)ptr;
1247 }
else if (type.isReal()) {
1248 if (type.size() ==
sizeof(float))
1249 value = (T)*(
float*)ptr;
1250 else if (type.size() ==
sizeof(double))
1251 value = (T)*(
double*)ptr;
1254 }
else if (type.isBool()) {
1255 value = (T)*(
bool*)ptr;
1263 static String _encodePrimitiveValue(
const Object& obj) {
1264 return _encodeBlob( _primitiveObjectValueToString(obj) );
1267 static String _encode(
const Object& obj) {
1269 s += _encode(obj.type());
1270 s += _encodeBlob(ToString(obj.version()));
1271 s += _encodeBlob(ToString(obj.minVersion()));
1272 s += _encode(obj.uidChain());
1273 s += _encode(obj.members());
1274 s += _encodePrimitiveValue(obj);
1275 return _encodeBlob(s);
1278 String _encode(
const Archive::ObjectPool& objects) {
1280 for (Archive::ObjectPool::const_iterator itObject = objects.begin();
1281 itObject != objects.end(); ++itObject)
1283 const Object& obj = itObject->second;
1286 return _encodeBlob(s);
1289 #define MAGIC_START "Srx1v" 1290 #define ENCODING_FORMAT_MINOR_VERSION 0 1292 String Archive::_encodeRootBlob() {
1294 s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
1295 s += _encode(m_root);
1296 s += _encode(m_allObjects);
1297 s += _encodeBlob(m_name);
1298 s += _encodeBlob(m_comment);
1299 s += _encode(m_timeCreated);
1300 s += _encode(m_timeModified);
1301 return _encodeBlob(s);
1304 void Archive::encode() {
1306 String s = MAGIC_START;
1307 m_timeModified = time(NULL);
1308 if (m_timeCreated == LIBGIG_EPOCH_TIME)
1309 m_timeCreated = m_timeModified;
1310 s += _encodeRootBlob();
1311 m_rawData.resize(s.length() + 1);
1312 memcpy(&m_rawData[0], &s[0], s.length() + 1);
1313 m_isModified =
false;
1321 static _Blob _decodeBlob(
const char* p,
const char* end,
bool bThrow =
true) {
1322 if (!bThrow && p >= end) {
1323 const _Blob blob = { p, end };
1329 throw Exception(
"Decode Error: Missing blob");
1331 if (c ==
':')
break;
1332 if (c < '0' || c >
'9')
1333 throw Exception(
"Decode Error: Missing blob size");
1335 sz += size_t(c -
'0');
1339 throw Exception(
"Decode Error: Premature end of blob");
1340 const _Blob blob = { p, p + sz };
1344 template<
typename T_
int>
1345 static T_int _popIntBlob(
const char*& p,
const char* end) {
1346 _Blob blob = _decodeBlob(p, end);
1353 throw Exception(
"Decode Error: premature end of int blob");
1358 for (; p < end; ++p) {
1360 if (c < '0' || c >
'9')
1361 throw Exception(
"Decode Error: Invalid int blob format");
1363 i += size_t(c -
'0');
1368 template<
typename T_
int>
1369 static void _popIntBlob(
const char*& p,
const char* end,
RawData& rawData) {
1370 const T_int i = _popIntBlob<T_int>(p, end);
1371 *(T_int*)&rawData[0] = i;
1374 template<
typename T_real>
1375 static T_real _popRealBlob(
const char*& p,
const char* end) {
1376 _Blob blob = _decodeBlob(p, end);
1380 if (p >= end || (end - p) < 1)
1381 throw Exception(
"Decode Error: premature end of real blob");
1383 String s(p,
size_t(end - p));
1386 if (
sizeof(T_real) <=
sizeof(
double))
1387 r = atof(s.c_str());
1396 template<
typename T_real>
1397 static void _popRealBlob(
const char*& p,
const char* end,
RawData& rawData) {
1398 const T_real r = _popRealBlob<T_real>(p, end);
1399 *(T_real*)&rawData[0] = r;
1402 static String _popStringBlob(
const char*& p,
const char* end) {
1403 _Blob blob = _decodeBlob(p, end);
1407 throw Exception(
"Decode Error: missing String blob");
1409 const size_t sz = end - p;
1411 memcpy(&s[0], p, sz);
1416 static time_t _popTimeBlob(
const char*& p,
const char* end) {
1417 const uint64_t i = _popIntBlob<uint64_t>(p, end);
1421 static DataType _popDataTypeBlob(
const char*& p,
const char* end) {
1422 _Blob blob = _decodeBlob(p, end);
1427 type.m_baseTypeName = _popStringBlob(p, end);
1428 type.m_customTypeName = _popStringBlob(p, end);
1429 type.m_size = _popIntBlob<int>(p, end);
1430 type.m_isPointer = _popIntBlob<bool>(p, end);
1434 static UID _popUIDBlob(
const char*& p,
const char* end) {
1435 _Blob blob = _decodeBlob(p, end);
1440 throw Exception(
"Decode Error: premature end of UID blob");
1442 const ID id = (
ID) _popIntBlob<size_t>(p, end);
1443 const size_t size = _popIntBlob<size_t>(p, end);
1445 const UID uid = { id, size };
1449 static UIDChain _popUIDChainBlob(
const char*& p,
const char* end) {
1450 _Blob blob = _decodeBlob(p, end);
1456 const UID uid = _popUIDBlob(p, end);
1457 chain.push_back(uid);
1459 assert(!chain.empty());
1463 static Member _popMemberBlob(
const char*& p,
const char* end) {
1464 _Blob blob = _decodeBlob(p, end,
false);
1469 if (p >= end)
return m;
1471 m.m_uid = _popUIDBlob(p, end);
1472 m.m_offset = _popIntBlob<size_t>(p, end);
1473 m.m_name = _popStringBlob(p, end);
1474 m.m_type = _popDataTypeBlob(p, end);
1476 assert(!m.name().empty());
1477 assert(m.uid().isValid());
1481 static std::vector<Member> _popMembersBlob(
const char*& p,
const char* end) {
1482 _Blob blob = _decodeBlob(p, end,
false);
1486 std::vector<Member> members;
1488 const Member member = _popMemberBlob(p, end);
1490 members.push_back(member);
1497 static void _popPrimitiveValue(
const char*& p,
const char* end, Object& obj) {
1498 const DataType& type = obj.type();
1499 if (type.isPrimitive() && !type.isPointer()) {
1500 obj.m_data.resize(type.size());
1501 if (type.isInteger() || type.isEnum()) {
1502 if (type.isSigned()) {
1503 if (type.size() == 1)
1504 _popIntBlob<int8_t>(p, end, obj.m_data);
1505 else if (type.size() == 2)
1506 _popIntBlob<int16_t>(p, end, obj.m_data);
1507 else if (type.size() == 4)
1508 _popIntBlob<int32_t>(p, end, obj.m_data);
1509 else if (type.size() == 8)
1510 _popIntBlob<int64_t>(p, end, obj.m_data);
1514 if (type.size() == 1)
1515 _popIntBlob<uint8_t>(p, end, obj.m_data);
1516 else if (type.size() == 2)
1517 _popIntBlob<uint16_t>(p, end, obj.m_data);
1518 else if (type.size() == 4)
1519 _popIntBlob<uint32_t>(p, end, obj.m_data);
1520 else if (type.size() == 8)
1521 _popIntBlob<uint64_t>(p, end, obj.m_data);
1525 }
else if (type.isReal()) {
1526 if (type.size() ==
sizeof(float))
1527 _popRealBlob<float>(p, end, obj.m_data);
1528 else if (type.size() ==
sizeof(double))
1529 _popRealBlob<double>(p, end, obj.m_data);
1532 }
else if (type.isBool()) {
1533 _popIntBlob<uint8_t>(p, end, obj.m_data);
1540 _Blob blob = _decodeBlob(p, end,
false);
1546 static Object _popObjectBlob(
const char*& p,
const char* end) {
1547 _Blob blob = _decodeBlob(p, end,
false);
1552 if (p >= end)
return obj;
1554 obj.m_type = _popDataTypeBlob(p, end);
1555 obj.m_version = _popIntBlob<Version>(p, end);
1556 obj.m_minVersion = _popIntBlob<Version>(p, end);
1557 obj.m_uid = _popUIDChainBlob(p, end);
1558 obj.m_members = _popMembersBlob(p, end);
1559 _popPrimitiveValue(p, end, obj);
1564 void Archive::_popObjectsBlob(
const char*& p,
const char* end) {
1565 _Blob blob = _decodeBlob(p, end,
false);
1570 throw Exception(
"Decode Error: Premature end of objects blob");
1573 const Object obj = _popObjectBlob(p, end);
1575 m_allObjects[obj.uid()] = obj;
1579 void Archive::_popRootBlob(
const char*& p,
const char* end) {
1580 _Blob blob = _decodeBlob(p, end,
false);
1585 throw Exception(
"Decode Error: Premature end of root blob");
1589 const int formatMinorVersion = _popIntBlob<int>(p, end);
1591 m_root = _popUIDBlob(p, end);
1593 throw Exception(
"Decode Error: No root object");
1595 _popObjectsBlob(p, end);
1596 if (!m_allObjects[m_root])
1597 throw Exception(
"Decode Error: Missing declared root object");
1599 m_name = _popStringBlob(p, end);
1600 m_comment = _popStringBlob(p, end);
1601 m_timeCreated = _popTimeBlob(p, end);
1602 m_timeModified = _popTimeBlob(p, end);
1622 m_allObjects.clear();
1623 m_isModified =
false;
1624 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1625 const char* p = (
const char*) &data[0];
1626 const char* end = p + data.size();
1627 if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
1628 throw Exception(
"Decode Error: Magic start missing!");
1629 p += strlen(MAGIC_START);
1630 _popRootBlob(p, end);
1656 memcpy(&
rawData[0], data, size);
1676 if (m_isModified) encode();
1704 return m_isModified;
1713 m_allObjects.clear();
1714 m_operation = OPERATION_NONE;
1717 m_isModified =
false;
1718 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1742 if (m_name ==
name)
return;
1744 m_isModified =
true;
1768 if (m_comment ==
comment)
return;
1770 m_isModified =
true;
1773 static tm _convertTimeStamp(
const time_t& time,
time_base_t base) {
1777 pTm = localtime(&time);
1780 pTm = gmtime(&time);
1783 throw Exception(
"Time stamp with unknown time base (" + ToString((int64_t)base) +
") requested");
1786 throw Exception(
"Failed assembling time stamp structure");
1796 return m_timeCreated;
1805 return m_timeModified;
1819 return _convertTimeStamp(m_timeCreated, base);
1833 return _convertTimeStamp(m_timeModified, base);
1854 parent.remove(member);
1855 m_isModified =
true;
1875 if (!obj.
uid())
return;
1876 m_allObjects.erase(obj.
uid());
1877 m_isModified =
true;
1892 return m_allObjects[uid];
1906 if (!
object)
return;
1907 object.setVersion(v);
1908 m_isModified =
true;
1922 if (!
object)
return;
1923 object.setMinVersion(v);
1924 m_isModified =
true;
1936 if (!
object)
return;
1937 if (!
object.type().isEnum())
1938 throw Exception(
"Not an enum data type");
1939 Object* pObject = &object;
1940 if (
object.type().isPointer()) {
1945 const int nativeEnumSize =
sizeof(
enum operation_t);
1946 DataType& type = const_cast<DataType&>( pObject->
type() );
1949 if (type.
size() != nativeEnumSize) {
1950 type.m_size = nativeEnumSize;
1952 pObject->m_data.resize(type.
size());
1953 void* ptr = &pObject->m_data[0];
1954 if (type.
size() == 1)
1955 *(uint8_t*)ptr = (uint8_t)value;
1956 else if (type.
size() == 2)
1957 *(uint16_t*)ptr = (uint16_t)value;
1958 else if (type.
size() == 4)
1959 *(uint32_t*)ptr = (uint32_t)value;
1960 else if (type.
size() == 8)
1961 *(uint64_t*)ptr = (uint64_t)value;
1964 m_isModified =
true;
1978 if (!
object)
return;
1979 if (!
object.type().isInteger())
1980 throw Exception(
"Not an integer data type");
1981 Object* pObject = &object;
1982 if (
object.type().isPointer()) {
1988 pObject->m_data.resize(type.
size());
1989 void* ptr = &pObject->m_data[0];
1991 if (type.
size() == 1)
1992 *(int8_t*)ptr = (int8_t)value;
1993 else if (type.
size() == 2)
1994 *(int16_t*)ptr = (int16_t)value;
1995 else if (type.
size() == 4)
1996 *(int32_t*)ptr = (int32_t)value;
1997 else if (type.
size() == 8)
1998 *(int64_t*)ptr = (int64_t)value;
2002 if (type.
size() == 1)
2003 *(uint8_t*)ptr = (uint8_t)value;
2004 else if (type.
size() == 2)
2005 *(uint16_t*)ptr = (uint16_t)value;
2006 else if (type.
size() == 4)
2007 *(uint32_t*)ptr = (uint32_t)value;
2008 else if (type.
size() == 8)
2009 *(uint64_t*)ptr = (uint64_t)value;
2013 m_isModified =
true;
2028 if (!
object)
return;
2029 if (!
object.type().isReal())
2030 throw Exception(
"Not a real data type");
2031 Object* pObject = &object;
2032 if (
object.type().isPointer()) {
2038 pObject->m_data.resize(type.
size());
2039 void* ptr = &pObject->m_data[0];
2040 if (type.
size() ==
sizeof(float))
2041 *(
float*)ptr = (
float)value;
2042 else if (type.
size() ==
sizeof(double))
2043 *(
double*)ptr = (
double)value;
2046 m_isModified =
true;
2058 if (!
object)
return;
2059 if (!
object.type().isBool())
2060 throw Exception(
"Not a bool data type");
2061 Object* pObject = &object;
2062 if (
object.type().isPointer()) {
2068 pObject->m_data.resize(type.
size());
2069 bool* ptr = (
bool*)&pObject->m_data[0];
2071 m_isModified =
true;
2088 if (!
object)
return;
2089 const DataType& type =
object.type();
2094 else if (type.
isBool()) {
2095 String val = toLowerCase(value);
2096 if (val ==
"true" || val ==
"yes" || val ==
"1")
2098 else if (val ==
"false" || val ==
"no" || val ==
"0")
2102 }
else if (type.
isEnum())
2105 throw Exception(
"Not a primitive data type");
2120 if (
object.type().isClass())
2121 throw Exception(
"Object is class type");
2122 const Object* pObject = &object;
2123 if (
object.type().isPointer()) {
2125 if (!obj)
return "";
2128 return _primitiveObjectValueToString(*pObject);
2143 if (!
object.type().isInteger() && !
object.type().isEnum())
2144 throw Exception(
"Object is neither an integer nor an enum");
2145 const Object* pObject = &object;
2146 if (
object.type().isPointer()) {
2151 return _primitiveObjectValueToNumber<int64_t>(*pObject);
2166 if (!
object.type().isReal())
2167 throw Exception(
"Object is not an real type");
2168 const Object* pObject = &object;
2169 if (
object.type().isPointer()) {
2174 return _primitiveObjectValueToNumber<double>(*pObject);
2188 if (!
object.type().isBool())
2189 throw Exception(
"Object is not a bool");
2190 const Object* pObject = &object;
2191 if (
object.type().isPointer()) {
2196 return _primitiveObjectValueToNumber<bool>(*pObject);
2203 : m_dst(dst), m_src(src)
2208 throw Exception(
"No source root object!");
2210 throw Exception(
"Expected destination root object not found!");
2211 syncObject(dstRootObj, srcRootObj);
2214 void Archive::Syncer::syncPrimitive(
const Object& dstObj,
const Object& srcObj) {
2215 assert(srcObj.rawData().size() == dstObj.type().size());
2216 void* pDst = (
void*)dstObj.uid().id;
2217 memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
2220 void Archive::Syncer::syncPointer(
const Object& dstObj,
const Object& srcObj) {
2221 assert(dstObj.type().isPointer());
2222 assert(dstObj.type() == srcObj.type());
2223 const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
2224 const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
2225 syncObject(pointedDstObject, pointedSrcObject);
2228 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2229 if (!dstObj || !srcObj)
return;
2230 if (!dstObj.isVersionCompatibleTo(srcObj))
2231 throw Exception(
"Version incompatible (destination version " +
2232 ToString(dstObj.version()) +
" [min. version " +
2233 ToString(dstObj.minVersion()) +
"], source version " +
2234 ToString(srcObj.version()) +
" [min. version " +
2235 ToString(srcObj.minVersion()) +
"])");
2236 if (dstObj.type() != srcObj.type())
2237 throw Exception(
"Incompatible data structure type (destination type " +
2238 dstObj.type().asLongDescr() +
" vs. source type " +
2239 srcObj.type().asLongDescr() +
")");
2243 m_dst.m_allObjects.erase(dstObj.uid());
2245 if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2246 syncPrimitive(dstObj, srcObj);
2250 if (dstObj.type().isPointer()) {
2251 syncPointer(dstObj, srcObj);
2255 assert(dstObj.type().isClass());
2256 for (
int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
2257 const Member& srcMember = srcObj.members()[iMember];
2258 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2260 throw Exception(
"Expected member missing in destination object");
2261 syncMember(dstMember, srcMember);
2265 Member Archive::Syncer::dstMemberMatching(
const Object& dstObj,
const Object& srcObj,
const Member& srcMember) {
2266 Member dstMember = dstObj.memberNamed(srcMember.name());
2268 return (dstMember.type() == srcMember.type()) ? dstMember : Member();
2269 std::vector<Member> members = dstObj.membersOfType(srcMember.type());
2270 if (members.size() <= 0)
2272 if (members.size() == 1)
2274 for (
int i = 0; i < members.size(); ++i)
2275 if (members[i].offset() == srcMember.offset())
2277 const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
2278 assert(srcSeqNr >= 0);
2279 for (
int i = 0; i < members.size(); ++i) {
2280 const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
2281 if (dstSeqNr == srcSeqNr)
2287 void Archive::Syncer::syncMember(
const Member& dstMember,
const Member& srcMember) {
2288 assert(dstMember && srcMember);
2289 assert(dstMember.type() == srcMember.type());
2290 const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
2291 const Object srcObj = m_src.m_allObjects[srcMember.uid()];
2292 syncObject(dstObj, srcObj);
2298 Exception::Exception() {
2301 Exception::Exception(String format, ...) {
2303 va_start(arg, format);
2304 Message = assemble(format, arg);
2308 Exception::Exception(String format, va_list arg) {
2309 Message = assemble(format, arg);
2318 std::cout <<
"Serialization::Exception: " << Message << std::endl;
2321 String Exception::assemble(String format, va_list arg) {
2323 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.