26 #define LIBGIG_SERIALIZATION_INTERNAL 1
28 #include "Serialization.h"
40 #include "srx/SrxFormat.h"
41 #include "srx/SrxJSONFormat.h"
43 #define LIBGIG_EPOCH_TIME ((time_t)0)
50 static UID _createNullUID() {
51 const UID uid = { NULL, 0 };
69 return id != NULL &&
id != (
void*)-1 &&
size;
86 std::map<String,DataType::NativeType> DataType::m_nativeTypes;
134 m_baseTypeName = baseType;
135 m_customTypeName = customType1;
136 m_customTypeName2 = customType2;
188 return m_baseTypeName ==
"class";
226 return m_baseTypeName ==
"String";
245 return m_baseTypeName.substr(0, 4) ==
"char";
268 return m_baseTypeName.substr(0, 3) ==
"int" ||
269 m_baseTypeName.substr(0, 4) ==
"uint";
285 return m_baseTypeName.substr(0, 4) ==
"real";
318 return m_baseTypeName ==
"bool";
333 return m_baseTypeName ==
"enum";
349 return m_baseTypeName ==
"Array";
365 return m_baseTypeName ==
"Set";
381 return m_baseTypeName ==
"Map";
400 return m_baseTypeName.substr(0, 3) ==
"int" ||
423 return m_baseTypeName == other.m_baseTypeName &&
424 m_customTypeName == other.m_customTypeName &&
425 m_customTypeName2 == other.m_customTypeName2 &&
427 m_isPointer == other.m_isPointer;
443 return m_baseTypeName +
"," +
444 m_customTypeName +
"," +
445 m_customTypeName2 +
"," +
447 ToString(m_isPointer);
471 return m_baseTypeName < other.m_baseTypeName ||
472 (m_baseTypeName == other.m_baseTypeName &&
473 (m_customTypeName < other.m_customTypeName ||
474 (m_customTypeName == other.m_customTypeName &&
475 (m_customTypeName2 < other.m_customTypeName2 ||
476 (m_customTypeName2 == other.m_customTypeName2 &&
477 (m_size < other.m_size ||
478 (m_size == other.m_size &&
479 m_isPointer < other.m_isPointer)))))));
512 String s = m_baseTypeName;
513 if (!m_customTypeName.empty())
515 if (!m_customTypeName2.empty())
552 return m_baseTypeName;
555 static String _demangleTypeName(
const char* name) {
557 const size_t MAXLENGTH = 1024;
558 char result[MAXLENGTH];
562 size_t size = UnDecorateSymbolName(name + 1, result, MAXLENGTH, UNDNAME_32_BIT_DECODE | UNDNAME_NO_ARGUMENTS);
571 abi::__cxa_demangle(name, 0, 0, &status);
572 String sResult = result;
574 return (status == 0) ? sResult : name;
615 if (!demangle)
return m_customTypeName;
616 return _demangleTypeName(m_customTypeName.c_str());
627 if (!demangle)
return m_customTypeName2;
628 return _demangleTypeName(m_customTypeName2.c_str());
646 auto itNativeType = m_nativeTypes.find(
id);
647 if (itNativeType == m_nativeTypes.end()) {
649 "(De)serialization Failure: cannot create new instance of "
650 "unknown data type '%s' !\n",
652 assert(
false &&
"You may need to explicitly register this data "
653 "type by either calling "
654 "DataType::registerNativeType<T>() or using class "
655 "NativeDataTypeRegistry");
657 const std::function<
Object(
Archive*)>& allocFn = itNativeType->second.allocFn;
658 return allocFn(archive);
687 m_parentUID = parent.
uid();
807 return m_uid && !m_name.empty() && m_type;
819 return m_uid == other.m_uid &&
820 m_offset == other.m_offset &&
821 m_name == other.m_name &&
822 m_type == other.m_type;
847 return m_uid < other.m_uid ||
848 (m_uid == other.m_uid &&
849 (m_offset < other.m_offset ||
850 (m_offset == other.m_offset &&
851 (m_name < other.m_name ||
852 (m_name == other.m_name &&
853 m_type < other.m_type)))));
912 m_parentUID = parent.
uid();
929 return m_type && !m_uid.empty();
944 return (index < m_uid.size()) ? m_uid[index] :
NO_UID;
963 static void _setNativeValueFromString(
void* ptr,
const DataType& type,
const char* s) {
966 uintptr_t addr = std::stoull(s, NULL, 16);
967 *(
void**)ptr =
reinterpret_cast<void*
>(addr);
971 if (type.
size() == 1)
972 *(int8_t*)ptr = strTo<int8_t>(s);
973 else if (type.
size() == 2)
974 *(int16_t*)ptr = strTo<int16_t>(s);
975 else if (type.
size() == 4)
976 *(int32_t*)ptr = strTo<int32_t>(s);
977 else if (type.
size() == 8)
978 *(int64_t*)ptr = strTo<int64_t>(s);
982 if (type.
size() == 1)
983 *(uint8_t*)ptr = strTo<uint8_t>(s);
984 else if (type.
size() == 2)
985 *(uint16_t*)ptr = strTo<uint16_t>(s);
986 else if (type.
size() == 4)
987 *(uint32_t*)ptr = strTo<uint32_t>(s);
988 else if (type.
size() == 8)
989 *(uint64_t*)ptr = strTo<uint64_t>(s);
993 }
else if (type.
isReal()) {
994 if (type.
size() ==
sizeof(
float))
995 *(
float*)ptr = strTo<float>(s);
996 else if (type.
size() ==
sizeof(double))
997 *(
double*)ptr = strTo<double>(s);
1000 }
else if (type.
isChar()) {
1002 }
else if (type.
isBool()) {
1003 String lower = toLowerCase(s);
1004 const bool b = lower !=
"0" && lower !=
"false" && lower !=
"no";
1031 void* ptr = (
void*)
id;
1032 _setNativeValueFromString(ptr, m_type, s.c_str());
1106 return m_minVersion;
1168 return m_uid == other.m_uid &&
1169 m_type == other.m_type;
1196 return m_uid < other.m_uid ||
1197 (m_uid == other.m_uid &&
1198 m_type < other.m_type);
1244 void Object::setVersion(
Version v) {
1248 void Object::setMinVersion(
Version v) {
1282 for (
int i = 0; i < m_members.size(); ++i)
1283 if (m_members[i].name() == name)
1284 return m_members[i];
1304 for (
int i = 0; i < m_members.size(); ++i)
1305 if (m_members[i].
uid() ==
uid)
1306 return m_members[i];
1310 void Object::remove(
const Member& member) {
1311 for (
int i = 0; i < m_members.size(); ++i) {
1312 if (m_members[i] == member) {
1313 m_members.erase(m_members.begin() + i);
1335 std::vector<Member> v;
1336 for (
int i = 0; i < m_members.size(); ++i) {
1337 const Member& member = m_members[i];
1339 v.push_back(member);
1376 for (
int i = 0; i < m_members.size(); ++i)
1377 if (m_members[i] == member)
1386 if (SrxFormat::checkMagicStart(data))
1388 if (SrxJSONFormat::checkMagicStart(data))
1418 m_isModified =
false;
1419 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1443 m_isModified =
false;
1444 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1474 m_isModified =
false;
1475 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1479 Archive::~Archive() {
1493 return m_allObjects[m_root];
1496 String Archive::primitiveObjectValueToString(
const Object& obj) {
1500 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1501 if (!obj.m_data.empty())
1502 assert(type.
size() == obj.m_data.size());
1506 if (type.
size() == 1)
1507 s = ToString((int16_t)*(int8_t*)ptr);
1508 else if (type.
size() == 2)
1509 s = ToString(*(int16_t*)ptr);
1510 else if (type.
size() == 4)
1511 s = ToString(*(int32_t*)ptr);
1512 else if (type.
size() == 8)
1513 s = ToString(*(int64_t*)ptr);
1517 if (type.
size() == 1)
1518 s = ToString((uint16_t)*(uint8_t*)ptr);
1519 else if (type.
size() == 2)
1520 s = ToString(*(uint16_t*)ptr);
1521 else if (type.
size() == 4)
1522 s = ToString(*(uint32_t*)ptr);
1523 else if (type.
size() == 8)
1524 s = ToString(*(uint64_t*)ptr);
1528 }
else if (type.
isReal()) {
1529 if (type.
size() ==
sizeof(
float))
1530 s = ToString(*(
float*)ptr);
1531 else if (type.
size() ==
sizeof(
double))
1532 s = ToString(*(
double*)ptr);
1535 }
else if (type.
isChar()) {
1538 }
else if (type.
isBool()) {
1539 s = ToString(*(
bool*)ptr);
1541 s = obj.m_data.empty() ? *(String*)ptr :
String((
const char*)ptr);
1549 template<
typename T>
1550 inline T _stringToNumber(
const String& s) {
1555 inline int64_t _stringToNumber(
const String& s) {
1556 return strTo<int64_t>(s);
1560 inline double _stringToNumber(
const String& s) {
1561 return strTo<double>(s);
1565 inline bool _stringToNumber(
const String& s) {
1566 return strTo<bool>(s);
1569 template<
typename T>
1570 static T _primitiveObjectValueToNumber(
const Object& obj) {
1572 const DataType& type = obj.type();
1573 const ID&
id = obj.uid().id;
1574 void* ptr = obj.m_data.empty() ? (
void*)
id : (
void*)&obj.m_data[0];
1575 if (!obj.m_data.empty())
1576 assert(type.size() == obj.m_data.size());
1577 if (type.isPrimitive() && !type.isPointer()) {
1578 if (type.isInteger() || type.isEnum()) {
1579 if (type.isSigned()) {
1580 if (type.size() == 1)
1581 value = (T)*(int8_t*)ptr;
1582 else if (type.size() == 2)
1583 value = (T)*(int16_t*)ptr;
1584 else if (type.size() == 4)
1585 value = (T)*(int32_t*)ptr;
1586 else if (type.size() == 8)
1587 value = (T)*(int64_t*)ptr;
1591 if (type.size() == 1)
1592 value = (T)*(uint8_t*)ptr;
1593 else if (type.size() == 2)
1594 value = (T)*(uint16_t*)ptr;
1595 else if (type.size() == 4)
1596 value = (T)*(uint32_t*)ptr;
1597 else if (type.size() == 8)
1598 value = (T)*(uint64_t*)ptr;
1602 }
else if (type.isReal()) {
1603 if (type.size() ==
sizeof(
float))
1604 value = (T)*(
float*)ptr;
1605 else if (type.size() ==
sizeof(double))
1606 value = (T)*(
double*)ptr;
1609 }
else if (type.isChar()) {
1610 value = (T)*(
char*)ptr;
1611 }
else if (type.isBool()) {
1612 value = (T)*(
bool*)ptr;
1613 }
else if (type.isString()) {
1614 value = _stringToNumber<T>(
1615 obj.m_data.empty() ? *(String*)ptr : String((
const char*)ptr)
1624 void Archive::encode() {
1628 void Archive::encode(format_t format) {
1630 m_timeModified = time(NULL);
1631 if (m_timeCreated == LIBGIG_EPOCH_TIME)
1632 m_timeCreated = m_timeModified;
1639 m_rawData = SrxFormat::encode(*
this);
1643 SrxJSONEncoder jsonEncoder;
1644 m_rawData = jsonEncoder.encode(*
this);
1649 throw Exception(
"Requested encoding format unknown: %d", format);
1651 m_isModified =
false;
1692 m_allObjects.clear();
1693 m_isModified =
false;
1694 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1698 format = _autoDetectEncodingFormat(data);
1700 throw Exception(
"Unknown encoding format");
1703 SrxFormat::decode(*
this, data);
1707 SrxJSONDecoder::decode(*
this, data);
1712 throw Exception(
"Requested encoding format unknown: %d", format);
1736 decode(data, size, m_format);
1764 memcpy(&
rawData[0], data, size);
1784 if (m_isModified) encode();
1797 return SrxFormat::name();
1799 return SrxJSONFormat::name();
1819 return m_isModified;
1828 m_allObjects.clear();
1832 m_isModified =
false;
1833 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
1857 if (m_name ==
name)
return;
1859 m_isModified =
true;
1883 if (m_comment ==
comment)
return;
1885 m_isModified =
true;
1888 static tm _convertTimeStamp(
const time_t& time,
time_base_t base) {
1892 pTm = localtime(&time);
1895 pTm = gmtime(&time);
1898 throw Exception(
"Time stamp with unknown time base (" + ToString((int64_t)base) +
") requested");
1901 throw Exception(
"Failed assembling time stamp structure");
1911 return m_timeCreated;
1920 return m_timeModified;
1934 return _convertTimeStamp(m_timeCreated, base);
1948 return _convertTimeStamp(m_timeModified, base);
1969 parent.remove(member);
1970 m_isModified =
true;
1990 if (!obj.
uid())
return;
1991 m_allObjects.erase(obj.
uid());
1992 m_isModified =
true;
2008 return m_allObjects[uid];
2026 ObjectPool::iterator it = m_allObjects.find(uid);
2027 if (it != m_allObjects.end())
2032 std::map<size_t,UID> matches;
2033 for (
const auto& it : m_allObjects)
2034 if (it.first.id == uid.
id && it.first.size > uid.
size)
2035 matches[it.first.size] = it.first;
2037 if (matches.empty())
2038 return ObjectPool::invalidObject();
2041 return m_allObjects[matches.begin()->second];
2062 return m_allObjects[member.
parentUID()];
2076 if (!
object)
return;
2077 object.setVersion(v);
2078 m_isModified =
true;
2092 if (!
object)
return;
2093 object.setMinVersion(v);
2094 m_isModified =
true;
2106 if (!
object)
return;
2107 if (!
object.type().isEnum())
2108 throw Exception(
"Not an enum data type");
2109 Object* pObject = &object;
2110 if (
object.type().isPointer()) {
2115 const int nativeEnumSize =
sizeof(
enum operation_t);
2119 if (type.
size() != nativeEnumSize) {
2120 type.m_size = nativeEnumSize;
2122 pObject->m_data.resize(type.
size());
2123 void* ptr = &pObject->m_data[0];
2124 if (type.
size() == 1)
2125 *(uint8_t*)ptr = (uint8_t)value;
2126 else if (type.
size() == 2)
2127 *(uint16_t*)ptr = (uint16_t)value;
2128 else if (type.
size() == 4)
2129 *(uint32_t*)ptr = (uint32_t)value;
2130 else if (type.
size() == 8)
2131 *(uint64_t*)ptr = (uint64_t)value;
2134 m_isModified =
true;
2148 if (!
object)
return;
2149 if (!
object.type().isInteger())
2150 throw Exception(
"Not an integer data type");
2151 Object* pObject = &object;
2152 if (
object.type().isPointer()) {
2158 pObject->m_data.resize(type.
size());
2159 void* ptr = &pObject->m_data[0];
2161 if (type.
size() == 1)
2162 *(int8_t*)ptr = (int8_t)value;
2163 else if (type.
size() == 2)
2164 *(int16_t*)ptr = (int16_t)value;
2165 else if (type.
size() == 4)
2166 *(int32_t*)ptr = (int32_t)value;
2167 else if (type.
size() == 8)
2168 *(int64_t*)ptr = (int64_t)value;
2172 if (type.
size() == 1)
2173 *(uint8_t*)ptr = (uint8_t)value;
2174 else if (type.
size() == 2)
2175 *(uint16_t*)ptr = (uint16_t)value;
2176 else if (type.
size() == 4)
2177 *(uint32_t*)ptr = (uint32_t)value;
2178 else if (type.
size() == 8)
2179 *(uint64_t*)ptr = (uint64_t)value;
2183 m_isModified =
true;
2198 if (!
object)
return;
2199 if (!
object.type().isReal())
2200 throw Exception(
"Not a real data type");
2201 Object* pObject = &object;
2202 if (
object.type().isPointer()) {
2208 pObject->m_data.resize(type.
size());
2209 void* ptr = &pObject->m_data[0];
2210 if (type.
size() ==
sizeof(
float))
2211 *(
float*)ptr = (
float)value;
2212 else if (type.
size() ==
sizeof(double))
2213 *(
double*)ptr = (
double)value;
2216 m_isModified =
true;
2228 if (!
object)
return;
2229 if (!
object.type().isChar())
2230 throw Exception(
"Not a char data type");
2231 Object* pObject = &object;
2232 if (
object.type().isPointer()) {
2238 pObject->m_data.resize(type.
size());
2239 char* ptr = (
char*)&pObject->m_data[0];
2241 m_isModified =
true;
2253 if (!
object)
return;
2254 if (!
object.type().isBool())
2255 throw Exception(
"Not a bool data type");
2256 Object* pObject = &object;
2257 if (
object.type().isPointer()) {
2263 pObject->m_data.resize(type.
size());
2264 bool* ptr = (
bool*)&pObject->m_data[0];
2266 m_isModified =
true;
2278 if (!
object)
return;
2279 if (!
object.type().isString())
2280 throw Exception(
"Not a String data type");
2281 Object* pObject = &object;
2282 if (
object.type().isPointer()) {
2287 pObject->m_data.resize(value.length() + 1);
2288 char* ptr = (
char*) &pObject->m_data[0];
2289 strcpy(ptr, &value[0]);
2290 m_isModified =
true;
2307 if (!
object)
return;
2308 const DataType& type =
object.type();
2313 else if (type.
isChar()) {
2315 throw Exception(
"Empty string provided for char type");
2317 }
else if (type.
isBool()) {
2318 String val = toLowerCase(value);
2319 if (val ==
"true" || val ==
"yes" || val ==
"1")
2321 else if (val ==
"false" || val ==
"no" || val ==
"0")
2330 throw Exception(
"Not a primitive data type");
2345 if (
object.type().isClass())
2346 throw Exception(
"Object is class type");
2347 const Object* pObject = &object;
2348 if (
object.type().isPointer()) {
2350 if (!obj)
return "";
2353 return primitiveObjectValueToString(*pObject);
2368 if (!
object.type().isInteger() && !
object.type().isEnum())
2369 throw Exception(
"Object is neither an integer nor an enum");
2370 const Object* pObject = &object;
2371 if (
object.type().isPointer()) {
2376 return _primitiveObjectValueToNumber<int64_t>(*pObject);
2391 if (!
object.type().isReal())
2392 throw Exception(
"Object is not an real type");
2393 const Object* pObject = &object;
2394 if (
object.type().isPointer()) {
2399 return _primitiveObjectValueToNumber<double>(*pObject);
2413 if (!
object.type().isChar())
2414 throw Exception(
"Object is not a char type");
2415 const Object* pObject = &object;
2416 if (
object.type().isPointer()) {
2421 return _primitiveObjectValueToNumber<char>(*pObject);
2435 if (!
object.type().isBool())
2436 throw Exception(
"Object is not a bool type");
2437 const Object* pObject = &object;
2438 if (
object.type().isPointer()) {
2443 return _primitiveObjectValueToNumber<bool>(*pObject);
2453 Archive::Syncer::Syncer(Archive& dst, Archive& src)
2454 : m_dst(dst), m_src(src)
2456 const Object srcRootObj = src.rootObject();
2457 const Object dstRootObj = dst.rootObject();
2459 throw Exception(
"No source root object!");
2461 throw Exception(
"Expected destination root object not found!");
2462 syncObject(dstRootObj, srcRootObj);
2465 void Archive::Syncer::syncPrimitive(
const Object& dstObj,
const Object& srcObj) {
2466 assert(srcObj.rawData().size() == dstObj.type().size());
2467 void* pDst = (
void*)dstObj.uid().id;
2468 memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
2471 void Archive::Syncer::syncString(
const Object& dstObj,
const Object& srcObj) {
2472 assert(dstObj.type().isString());
2473 assert(dstObj.type() == srcObj.type());
2474 String* pDst = (String*)(
void*)dstObj.uid().id;
2475 *pDst = (
String) (
const char*) &srcObj.rawData()[0];
2478 void Archive::Syncer::syncArray(
const Object& dstObj,
const Object& srcObj) {
2479 assert(dstObj.type().isArray());
2480 assert(dstObj.type() == srcObj.type());
2481 dstObj.m_sync(
const_cast<Object&
>(dstObj), srcObj,
this);
2484 void Archive::Syncer::syncSet(
const Object& dstObj,
const Object& srcObj) {
2485 assert(dstObj.type().isSet());
2486 assert(dstObj.type() == srcObj.type());
2487 dstObj.m_sync(
const_cast<Object&
>(dstObj), srcObj,
this);
2490 void Archive::Syncer::syncMap(
const Object& dstObj,
const Object& srcObj) {
2491 assert(dstObj.type().isMap());
2492 assert(dstObj.type() == srcObj.type());
2493 dstObj.m_sync(
const_cast<Object&
>(dstObj), srcObj,
this);
2496 void Archive::Syncer::syncPointer(
const Object& dstObj,
const Object& srcObj) {
2497 assert(dstObj.type().isPointer());
2498 assert(dstObj.type() == srcObj.type());
2499 void** ppDst = (
void**)dstObj.uid().id;
2500 if (!srcObj.uid(1)) {
2504 const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
2505 assert(pointedSrcObject);
2506 std::map<UID,UID>::iterator uidRelation = m_counterparts.find(srcObj.uid(1));
2507 if (pointedSrcObject.parentUID() || uidRelation != m_counterparts.end()) {
2508 assert(uidRelation != m_counterparts.end());
2509 const Object& pointedDstObject = m_dst.m_allObjects[uidRelation->second];
2510 assert(pointedDstObject);
2511 *ppDst = (
void*)pointedDstObject.uid().id;
2513 assert(pointedSrcObject.type());
2514 Object pointedDstObject = pointedSrcObject.type().newInstance(&m_dst);
2515 assert(pointedDstObject);
2517 m_dst.m_allObjects[pointedDstObject.uid()] = pointedDstObject;
2518 *ppDst = (
void*)pointedDstObject.uid().id;
2519 syncObject(pointedDstObject, pointedSrcObject);
2523 void Archive::Syncer::syncObject(
const Object& dstObj,
const Object& srcObj) {
2524 assert(dstObj && srcObj);
2534 const bool alreadySynced =
2535 !m_counterparts.insert({srcObj.uid(), dstObj.uid()}).second;
2542 if (!dstObj.isVersionCompatibleTo(srcObj))
2543 throw Exception(
"Version incompatible (destination version " +
2544 ToString(dstObj.version()) +
" [min. version " +
2545 ToString(dstObj.minVersion()) +
"], source version " +
2546 ToString(srcObj.version()) +
" [min. version " +
2547 ToString(srcObj.minVersion()) +
"])");
2548 if (dstObj.type() != srcObj.type())
2549 throw Exception(
"Incompatible data structure type (destination type " +
2550 dstObj.type().asLongDescr() +
" vs. source type " +
2551 srcObj.type().asLongDescr() +
")");
2553 if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
2554 if (dstObj.type().isString())
2555 syncString(dstObj, srcObj);
2557 syncPrimitive(dstObj, srcObj);
2561 if (dstObj.type().isArray()) {
2562 syncArray(dstObj, srcObj);
2566 if (dstObj.type().isSet()) {
2567 syncSet(dstObj, srcObj);
2571 if (dstObj.type().isMap()) {
2572 syncMap(dstObj, srcObj);
2576 if (dstObj.type().isPointer()) {
2577 syncPointer(dstObj, srcObj);
2581 assert(dstObj.type().isClass());
2582 for (
int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
2583 const Member& srcMember = srcObj.members()[iMember];
2584 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
2586 throw Exception(
"Expected member missing in destination object");
2587 syncMember(dstMember, srcMember);
2591 Member Archive::Syncer::dstMemberMatching(
const Object& dstObj,
const Object& srcObj,
const Member& srcMember) {
2592 Member dstMember = dstObj.memberNamed(srcMember.name());
2594 return (dstMember.type() == srcMember.type()) ? dstMember : Member();
2595 std::vector<Member> members = dstObj.membersOfType(srcMember.type());
2596 if (members.size() <= 0)
2598 if (members.size() == 1)
2600 for (
int i = 0; i < members.size(); ++i)
2601 if (members[i].offset() == srcMember.offset())
2603 const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
2604 assert(srcSeqNr >= 0);
2605 for (
int i = 0; i < members.size(); ++i) {
2606 const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
2607 if (dstSeqNr == srcSeqNr)
2613 void Archive::Syncer::syncMember(
const Member& dstMember,
const Member& srcMember) {
2614 assert(dstMember && srcMember);
2615 assert(dstMember.type() == srcMember.type());
2616 const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
2617 const Object srcObj = m_src.m_allObjects[srcMember.uid()];
2618 syncObject(dstObj, srcObj);
2624 Exception::Exception() {
2627 Exception::Exception(String format, ...) {
2629 va_start(arg, format);
2630 Message = assemble(format, arg);
2634 Exception::Exception(String format, va_list arg) {
2635 Message = assemble(format, arg);
2644 std::cout <<
"Serialization::Exception: " << Message << std::endl;
2647 String Exception::assemble(
String format, va_list arg) {
2649 vasprintf(&buf, format.c_str(), arg);
Destination container for serialization, and source container for deserialization.
void setStringValue(Object &object, String value)
Set new textual string for given String object.
void setRealValue(Object &object, double value)
Set new floating point value for given floating point object.
void setCharValue(Object &object, char value)
Set new char value for given character object.
char valueAsChar(const Object &object)
Get char value of object.
void setMinVersion(const T_classType &nativeObject, Version v)
Set a minimum version number for your C++ class.
void setName(String name)
Assign a name to this archive.
time_t timeStampCreated() const
Date and time when this archive was initially created.
void setBoolValue(Object &object, bool value)
Set new boolean value for given boolean object.
void clear()
Clear content of this archive.
double valueAsReal(const Object &object)
Get floating point value of object.
Archive(format_t format=FORMAT_AUTO)
Create an "empty" archive.
time_t timeStampModified() const
Date and time when this archive was modified for the last time.
virtual String rawDataFormat() const
Name of the encoding format used by this Archive class.
void setIntValue(Object &object, int64_t value)
Set new integer value for given integer object.
operation_t
Current activity of Archive object.
@ OPERATION_NONE
Archive is currently neither serializing, nor deserializing.
const RawData & rawData()
Raw data stream of this archive content.
bool isModified() const
Whether this archive was modified.
virtual void decode(const RawData &data)
Fill this archive with the given serialized raw data.
tm dateTimeCreated(time_base_t base=LOCAL_TIME) const
Date and time when this archive was initially created.
Object & rootObject()
Root C++ object of this archive.
Object & objectByUID(const UID &uid)
Access object by its unique identifier.
String valueAsString(const Object &object)
Get value of object as string.
int64_t valueAsInt(const Object &object)
Get integer value of object.
void setVersion(const T_classType &nativeObject, Version v)
Set current version number for your C++ class.
Object & objectByBaseUID(const UID &uid)
Find true object for a base pointer.
void removeMember(Object &parent, const Member &member)
Remove a member variable from the given object.
void remove(const Object &obj)
Remove an object from this archive.
bool valueAsBool(const Object &object)
Get boolean value of object.
void setEnumValue(Object &object, uint64_t value)
Set new value for given enum object.
Object & parentObjectOf(const Object &obj)
Access parent of supplied object.
void setComment(String comment)
Assign a comment to this archive.
format_t
Encoding format of serialized data stream.
@ FORMAT_AUTO
Automatically handle the encoding format:
@ FORMAT_SRX_JSON
Use and expect "Srx-JSON" encoding format (user-friendly to read and modify).
@ FORMAT_SRX
Use and expect "Srx" encoding format (simple, reliable, fast).
String name() const
Optional name of this archive.
void setAutoValue(Object &object, String value)
Automatically cast and assign appropriate value to object.
String comment() const
Optional comments for this archive.
tm dateTimeModified(time_base_t base=LOCAL_TIME) const
Date and time when this archive was modified for the last time.
Abstract reflection of a native C++ data type.
bool isPrimitive() const
Whether this is reflecting a fundamental C/C++ data type.
bool isSet() const
Whether this is a C++ Set<> object type.
bool isNumber() const
Whether this is a numeric C/C++ data type.
bool isPointer() const
Whether this is reflecting a C/C++ pointer type.
bool isSigned() const
Whether this is a signed integer C/C++ data type.
String baseTypeName() const
The base type name of this data type.
bool operator!=(const DataType &other) const
Comparison for inequalness.
bool isReal() const
Whether this is a floating point based C/C++ data type.
DataType()
Default constructor (as "invalid" DataType).
String asLongDescr() const
Human readable long description for this data type.
bool isBool() const
Whether this is a boolean C/C++ data type.
bool isMap() const
Whether this is a C++ Map<> object type.
bool isValid() const
Check if this is a valid DataType object.
bool isArray() const
Whether this is a C++ Array<> object type.
bool operator>(const DataType &other) const
Greater than comparison.
bool isEnum() const
Whether this is a C/C++ enum data type.
bool operator<(const DataType &other) const
Smaller than comparison.
bool isChar() const
Whether this is a character C/C++ data type.
String customTypeName2(bool demangle=false) const
The 2nd user defined C/C++ data type name of this data type.
bool isClass() const
Whether this is reflecting a C/C++ struct or class type.
bool isInteger() const
Whether this is an integer C/C++ data type.
bool operator==(const DataType &other) const
Comparison for equalness.
String internalID() const
Unique key for native data type, for internal purposes only.
bool isString() const
Whether this is a C++ String data type.
String customTypeName(bool demangle=false) const
The 1st user defined C/C++ data type name of this data type.
size_t size() const
Returns native memory size of the respective C++ object or variable.
Object newInstance(Archive *archive) const
Allocate and initialize a native instance of data type.
Will be thrown whenever an error occurs during an serialization or deserialization process.
void PrintMessage() const
Print exception message to stdout.
Abstract reflection of a native C++ class/struct's member variable.
UID parentUID() const
Unique identifier of parent object.
Member()
Default constructor.
bool operator!=(const Member &other) const
Comparison for inequalness.
bool operator<(const Member &other) const
Smaller than comparison.
bool operator>(const Member &other) const
Greater than comparison.
ssize_t offset() const
Offset of member in its containing parent data structure.
String name() const
Name of the member.
bool operator==(const Member &other) const
Comparison for equalness.
const DataType & type() const
C/C++ Data type of this member.
bool isValid() const
Check if this is a valid Member object.
UID uid() const
Unique identifier of this member instance.
Abstract reflection of some native serialized C/C++ data.
bool isValid() const
Check if this is a valid Object instance.
Member memberNamed(String name) const
Get the member of this Object with given name.
Version version() const
Version of original user defined C/C++ struct or class.
UID uid(int index=0) const
Unique identifier of this Object.
const UIDChain & uidChain() const
Unique identifier chain of this Object.
const RawData & rawData() const
Raw data of the original native C/C++ data.
bool operator<(const Object &other) const
Smaller than comparison.
Object()
Default constructor (for an "invalid" Object).
Member memberByUID(const UID &uid) const
Get the member of this Object with given unique identifier.
std::vector< Member > membersOfType(const DataType &type) const
Get all members of this Object with given data type.
int sequenceIndexOf(const Member &member) const
Serialization/deserialization sequence number of the requested member.
void setNativeValueFromString(const String &s)
Cast from string to object's data type and assign value natively.
bool operator!=(const Object &other) const
Comparison for inequalness.
bool operator>(const Object &other) const
Greater than comparison.
UID parentUID() const
Unique identifier of parent object.
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 isVersionCompatibleTo(const Object &other) const
Check version compatibility between Object instances.
Version minVersion() const
Minimum version of original user defined C/C++ struct or class.
bool operator==(const Object &other) const
Comparison for equalness.
Unique identifier referring to one specific native C++ object, member, fundamental variable,...
bool isValid() const
Check whether this is a valid unique identifier.
size_t size
Memory size of the object or member in question.
ID id
Abstract non-unique ID of the object or member in question.
C++ Serialization / Deserialization Framework.
void * ID
Abstract identifier for serialized C++ objects.
const UID NO_UID
Reflects an invalid UID and behaves similar to NULL as invalid value for pointer types.
std::string String
Textual string.
uint32_t Version
Version number data type.
std::vector< UID > UIDChain
Chain of UIDs.
std::vector< uint8_t > RawData
Raw data stream of serialized C++ objects.
time_base_t
To which time zone a certain timing information relates to.
@ UTC_TIME
The time stamp relates to "Greenwhich Mean Time" zone, also known as "Coordinated Universal Time"....
@ LOCAL_TIME
The time stamp relates to the machine's local time zone. Request a time stamp in local time if you wa...