24 #ifndef LIBGIG_SERIALIZATION_H
25 #define LIBGIG_SERIALIZATION_H
46 #ifndef __has_extension
47 # define __has_extension(x) 0
50 #ifndef HAS_BUILTIN_TYPE_TRAITS
51 # if __cplusplus >= 201103L
52 # define HAS_BUILTIN_TYPE_TRAITS 1
53 # elif ( __has_extension(is_class) && __has_extension(is_enum) )
54 # define HAS_BUILTIN_TYPE_TRAITS 1
55 # elif ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) )
56 # define HAS_BUILTIN_TYPE_TRAITS 1
57 # elif _MSC_VER >= 1400
58 # define HAS_BUILTIN_TYPE_TRAITS 1
59 # elif __INTEL_COMPILER >= 1100
60 # define HAS_BUILTIN_TYPE_TRAITS 1
62 # define HAS_BUILTIN_TYPE_TRAITS 0
66 #if !HAS_BUILTIN_TYPE_TRAITS
67 # include <tr1/type_traits>
68 # define LIBGIG_IS_CLASS(type) std::tr1::__is_union_or_class<type>::value
70 # define LIBGIG_IS_CLASS(type) __is_class(type)
180 template<
class T_key,
class T_value>
181 using Map = std::map<T_key,T_value>;
233 #if !HAS_BUILTIN_TYPE_TRAITS
234 return std::tr1::is_enum<T>::value;
252 #if !HAS_BUILTIN_TYPE_TRAITS
255 return __is_union(T);
270 #if !HAS_BUILTIN_TYPE_TRAITS
271 return std::tr1::__is_union_or_class<T>::value;
273 return __is_class(T);
297 template<
typename T>
inline
298 String toString(
const T& value) {
299 return std::to_string(value);
302 template<
typename T>
inline
303 String toString(T* ptr) {
304 std::stringstream ss;
305 ss <<
"0x" << std::hex << size_t(ptr);
310 String toString(
const String& value) {
337 bool operator==(
const UID& other)
const {
return id == other.
id &&
size == other.
size; }
338 bool operator!=(
const UID& other)
const {
return id != other.id ||
size != other.size; }
339 bool operator<(
const UID& other)
const {
return id < other.id || (
id == other.id &&
size < other.size); }
340 bool operator>(
const UID& other)
const {
return id > other.id || (
id == other.id &&
size > other.size); }
351 return Resolver<T>::resolve(obj);
358 static UID resolve(
const T& obj) {
359 const UID uid = { (
ID) &obj,
sizeof(obj) };
366 struct Resolver<T*> {
367 static UID resolve(
const T*
const & obj) {
368 const UID uid = { (
ID) obj,
sizeof(*obj) };
414 #if LIBGIG_SERIALIZATION_INTERNAL
417 static DataType _popDataTypeBlob(
const char*& p,
const char* end);
418 static Member _popMemberBlob(
const char*& p,
const char* end);
419 static Object _popObjectBlob(
const char*& p,
const char* end);
420 static void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
421 static String _primitiveObjectValueToString(
const Object& obj);
424 static T _primitiveObjectValueToNumber(
const Object& obj);
446 size_t size()
const {
return m_size; }
485 const DataType type = Resolver<T>::resolve(data);
503 const DataType type = Resolver<T>::resolve(unused);
580 DataType::registerNativeDataType<T>();
591 template<typename T, typename std::enable_if<std::is_default_constructible<T>::value,
bool>::type =
true>
594 template<typename T, typename std::enable_if<!std::is_default_constructible<T>::value,
bool>::type =
true>
597 template<
typename T,
bool T_isPo
inter>
598 struct ResolverBase {
599 static DataType resolve(
const T& data) {
603 const std::type_info& type = (T_isPointer) ?
typeid(T) :
typeid(data);
604 const int sz =
sizeof(data);
609 if (type ==
typeid(int8_t))
return DataType(T_isPointer, sz,
"int8");
610 if (type ==
typeid(uint8_t))
return DataType(T_isPointer, sz,
"uint8");
611 if (type ==
typeid(int16_t))
return DataType(T_isPointer, sz,
"int16");
612 if (type ==
typeid(uint16_t))
return DataType(T_isPointer, sz,
"uint16");
613 if (type ==
typeid(int32_t))
return DataType(T_isPointer, sz,
"int32");
614 if (type ==
typeid(uint32_t))
return DataType(T_isPointer, sz,
"uint32");
615 if (type ==
typeid(int64_t))
return DataType(T_isPointer, sz,
"int64");
616 if (type ==
typeid(uint64_t))
return DataType(T_isPointer, sz,
"uint64");
617 if (type ==
typeid(
size_t)) {
618 if (sz == 1)
return DataType(T_isPointer, sz,
"uint8");
619 if (sz == 2)
return DataType(T_isPointer, sz,
"uint16");
620 if (sz == 4)
return DataType(T_isPointer, sz,
"uint32");
621 if (sz == 8)
return DataType(T_isPointer, sz,
"uint64");
624 if (type ==
typeid(ssize_t)) {
625 if (sz == 1)
return DataType(T_isPointer, sz,
"int8");
626 if (sz == 2)
return DataType(T_isPointer, sz,
"int16");
627 if (sz == 4)
return DataType(T_isPointer, sz,
"int32");
628 if (sz == 8)
return DataType(T_isPointer, sz,
"int64");
631 if (type ==
typeid(
bool))
return DataType(T_isPointer, sz,
"bool");
632 if (type ==
typeid(
float))
return DataType(T_isPointer, sz,
"real32");
633 if (type ==
typeid(
double))
return DataType(T_isPointer, sz,
"real64");
634 if (type ==
typeid(String))
return DataType(T_isPointer, sz,
"String");
643 const String rawCppName =
644 (T_isPointer) ? rawCppTypeName<T>()
645 : rawCppTypeNameOf(data);
647 if (
IsEnum(data))
return DataType(T_isPointer, sz,
"enum", rawCppName);
648 if (
IsUnion(data))
return DataType(T_isPointer, sz,
"union", rawCppName);
649 if (
IsClass(data))
return DataType(T_isPointer, sz,
"class", rawCppName);
657 struct Resolver : ResolverBase<T,false> {
658 static DataType resolve(
const T& data) {
659 return ResolverBase<T,false>::resolve(data);
665 struct Resolver<T*> : ResolverBase<T,true> {
666 static DataType resolve(
const T*
const & data) {
667 return ResolverBase<T,true>::resolve(*data);
673 struct Resolver<
Array<T>> {
674 static DataType resolve(
const Array<T>& data) {
675 const int sz =
sizeof(data);
677 return DataType(
false, sz,
"Array", rawCppTypeNameOf(unused));
683 struct Resolver<
Array<T>*> {
684 static DataType resolve(
const Array<T>*& data) {
685 const int sz =
sizeof(*data);
687 return DataType(
true, sz,
"Array", rawCppTypeNameOf(unused));
693 struct Resolver<
Set<T>> {
694 static DataType resolve(
const Set<T>& data) {
695 const int sz =
sizeof(data);
697 return DataType(
false, sz,
"Set", rawCppTypeNameOf(unused));
703 struct Resolver<
Set<T>*> {
704 static DataType resolve(
const Set<T>*& data) {
705 const int sz =
sizeof(*data);
707 return DataType(
true, sz,
"Set", rawCppTypeNameOf(unused));
712 template<
typename T_key,
typename T_value>
713 struct Resolver<
Map<T_key,T_value>> {
714 static DataType resolve(
const Map<T_key,T_value>& data) {
715 const int sz =
sizeof(data);
716 T_key unused1 = T_key();
717 T_value unused2 = T_value();
718 return DataType(
false, sz,
"Map", rawCppTypeNameOf(unused1),
719 rawCppTypeNameOf(unused2));
724 template<
typename T_key,
typename T_value>
725 struct Resolver<
Map<T_key,T_value>*> {
726 static DataType resolve(
const Map<T_key,T_value>*& data) {
727 const int sz =
sizeof(*data);
728 T_key unused1 = T_key();
729 T_value unused2 = T_value();
730 return DataType(
true, sz,
"Map", rawCppTypeNameOf(unused1),
731 rawCppTypeNameOf(unused2));
737 static String rawCppTypeName() {
738 const std::type_info& type =
typeid(T);
740 String name = type.raw_name();
742 String name = type.name();
751 static String rawCppTypeNameOf(
const T*
const & data) {
752 return rawCppTypeName<T*>();
757 static String rawCppTypeNameOf(
const T& data) {
758 const std::type_info& type =
typeid(data);
760 String name = type.raw_name();
762 String name = type.name();
770 String m_baseTypeName;
771 String m_customTypeName;
772 String m_customTypeName2;
775 static std::map<
String,std::function<Object(Archive*)>> m_allocFns;
777 #if LIBGIG_SERIALIZATION_INTERNAL
778 friend DataType _popDataTypeBlob(
const char*& p,
const char* end);
780 friend class Archive;
831 #if LIBGIG_SERIALIZATION_INTERNAL
832 friend Member _popMemberBlob(
const char*& p,
const char* end);
865 UID uid(
int index = 0)
const;
873 std::vector<Member>&
members();
874 const std::vector<Member>&
members()
const;
889 void remove(
const Member& member);
900 std::vector<Member> m_members;
901 std::function<void(
Object& dstObj,
const Object& srcObj,
void* syncer)> m_sync;
903 #if LIBGIG_SERIALIZATION_INTERNAL
905 friend Object _popObjectBlob(
const char*& p,
const char* end);
906 friend void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
907 friend String _primitiveObjectValueToString(
const Object& obj);
910 friend T _primitiveObjectValueToNumber(
const Object& obj);
1065 Archive(
const uint8_t* data,
size_t size);
1093 template<
typename T>
1096 m_allObjects.clear();
1128 template<
typename T>
1152 template<
typename T>
1175 template<
typename T>
1239 template<
typename T_
classType,
typename T_memberType>
1240 void serializeMember(
const T_classType& nativeObject,
const T_memberType& nativeMember,
const char* memberName) {
1241 const ssize_t offset =
1242 ((
const uint8_t*)(
const void*)&nativeMember) -
1243 ((
const uint8_t*)(
const void*)&nativeObject);
1244 const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
1247 Object& parent = m_allObjects[parentUID];
1249 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1253 const Member member(memberName, uids[0], offset, type, parent);
1254 parent.
members().push_back(member);
1255 const Object obj(uids, type, parent);
1256 const bool bExistsAlready = m_allObjects.count(uids[0]);
1257 const bool isValidObject = obj;
1258 const Object& existingObj = m_allObjects[uids[0]];
1259 const bool bExistingObjectIsInvalid = !existingObj;
1260 if (isValidObject && (
1261 !bExistsAlready || bExistingObjectIsInvalid || (
1266 m_allObjects[uids[0]] = obj;
1269 SerializationRecursion<T_memberType>::serializeObject(
this, nativeMember);
1303 template<
typename T_
classType,
typename T_memberType>
1304 void serializeHeapMember(
const T_classType& nativeObject,
const T_memberType& heapMember,
const char* memberName) {
1305 const ssize_t offset = -1;
1306 const UIDChain uids = UIDChainResolver<T_memberType>(heapMember);
1309 Object& parent = m_allObjects[parentUID];
1311 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1315 const Member member(memberName, uids[0], offset, type, parent);
1316 parent.
members().push_back(member);
1317 const Object obj(uids, type, parent);
1318 const bool bExistsAlready = m_allObjects.count(uids[0]);
1319 const bool isValidObject = obj;
1320 const Object& existingObj = m_allObjects[uids[0]];
1321 const bool bExistingObjectIsInvalid = !existingObj;
1322 if (isValidObject && (
1323 !bExistsAlready || bExistingObjectIsInvalid || (
1328 m_allObjects[uids[0]] = obj;
1331 SerializationRecursion<T_memberType>::serializeObject(
this, heapMember);
1355 template<
typename T_
objectType>
1357 const UIDChain uids = UIDChainResolver<T_objectType>(heapObject);
1360 const bool bExistsAlready = m_allObjects.count(uids[0]);
1361 const bool isValidObject = obj;
1362 const Object& existingObj = m_allObjects[uids[0]];
1363 const bool bExistingObjectIsInvalid = !existingObj;
1364 if (isValidObject && (
1365 !bExistsAlready || bExistingObjectIsInvalid || (
1370 m_allObjects[uids[0]] = obj;
1373 SerializationRecursion<T_objectType>::serializeObject(
this, heapObject);
1456 template<
typename T_
classType>
1459 Object& obj = m_allObjects[uid];
1461 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1497 template<
typename T_
classType>
1500 Object& obj = m_allObjects[uid];
1502 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1510 virtual void decode(
const uint8_t* data,
size_t size);
1543 template<
typename T>
1544 class UIDChainResolver {
1546 UIDChainResolver(
const T& data) {
1550 operator UIDChain()
const {
return m_uid; }
1551 UIDChain operator()()
const {
return m_uid; }
1557 template<
typename T>
1558 class UIDChainResolver<T*> {
1560 UIDChainResolver(
const T*
const & data) {
1561 const UID uids[2] = {
1562 { (
ID) &data,
sizeof(data) },
1563 { (
ID) data,
sizeof(*data) }
1565 m_uid.push_back(uids[0]);
1566 m_uid.push_back(uids[1]);
1569 operator UIDChain()
const {
return m_uid; }
1570 UIDChain operator()()
const {
return m_uid; }
1576 template<
typename T,
bool T_isRecursive>
1577 struct SerializationRecursionImpl {
1578 static void serializeObject(
Archive* archive,
const T& obj) {
1584 template<
typename T,
bool T_isRecursive>
1585 struct SerializationRecursionImpl<T*,T_isRecursive> {
1586 static void serializeObject(
Archive* archive,
const T*& obj) {
1588 const_cast<T*&
>(obj)->
serialize(archive);
1593 template<
typename T>
1594 struct SerializationRecursionImpl<T,false> {
1595 static void serializeObject(
Archive* ,
const T& ) {}
1599 template<
typename T>
1600 struct SerializationRecursionImpl<T*,
false> {
1601 static void serializeObject(
Archive* archive,
const T*
const & obj) {
1603 archive->serializeAnonymousObject(*obj);
1608 template<
bool T_isRecursive>
1609 struct SerializationRecursionImpl<String,T_isRecursive> {
1610 static void serializeObject(
Archive* archive,
const String& obj) {}
1614 template<
bool T_isRecursive>
1615 struct SerializationRecursionImpl<String*,T_isRecursive> {
1616 static void serializeObject(
Archive* archive,
const String*& obj) {
1618 archive->serializeAnonymousObject(*obj);
1623 template<
typename T,
bool T_isRecursive>
1624 struct SerializationRecursionImpl<
Array<T>,T_isRecursive> {
1625 static void serializeObject(
Archive* archive,
const Array<T>& obj) {
1626 const UIDChain uids = UIDChainResolver<Array<T>>(obj);
1627 const Object&
object = archive->objectByUID(uids[0]);
1629 for (
size_t i = 0; i < obj.size(); ++i) {
1630 archive->serializeHeapMember(
1631 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1635 const_cast<Object&
>(object).m_sync =
1636 [&obj,archive](Object& dstObj,
const Object& srcObj,
1639 const size_t n = srcObj.members().size();
1640 const_cast<Array<T>&
>(obj).resize(n);
1641 for (
size_t i = 0; i < n; ++i) {
1642 archive->serializeHeapMember(
1643 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1648 dstObj = archive->objectByUID(dstObj.uid());
1649 for (
size_t i = 0; i < n; ++i) {
1650 String
name =
"[" + toString(i) +
"]";
1651 Member srcMember = srcObj.memberNamed(
name);
1652 Member dstMember = dstObj.memberNamed(
name);
1653 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1661 template<
typename T,
bool T_isRecursive>
1662 struct SerializationRecursionImpl<
Array<T>*,T_isRecursive> {
1663 static void serializeObject(
Archive* archive,
const Array<T>*& obj) {
1665 SerializationRecursionImpl<Array<T>,T_isRecursive>::serializeObject(
1672 template<
typename T,
bool T_isRecursive>
1673 struct SerializationRecursionImpl<
Set<T>,T_isRecursive> {
1674 static void serializeObject(
Archive* archive,
const Set<T>& obj) {
1675 const UIDChain uids = UIDChainResolver<Set<T>>(obj);
1676 const Object&
object = archive->objectByUID(uids[0]);
1678 for (
const T& key : obj) {
1679 archive->serializeHeapMember(
1680 obj, key, (
"[" + toString(key) +
"]").c_str()
1684 const_cast<Object&
>(object).m_sync =
1685 [&obj,archive](Object& dstObj,
const Object& srcObj,
1688 const size_t n = srcObj.members().size();
1689 const_cast<Set<T>&
>(obj).
clear();
1690 for (
size_t i = 0; i < n; ++i) {
1691 const Member& member = srcObj.members()[i];
1692 String
name = member.name();
1694 if (
name.length() < 2 ||
name[0] !=
'[' ||
1695 *
name.rbegin() !=
']')
continue;
1698 const UIDChain uids = UIDChainResolver<T>(key);
1700 Object tmpObj(uids, type, Object());
1702 tmpObj.setNativeValueFromString(
name);
1706 ((Syncer*)syncer)->translateKey(key);
1708 const_cast<Set<T>&
>(obj).insert(key);
1711 for (
const T& key : obj) {
1712 archive->serializeHeapMember(
1713 obj, key, (
"[" + toString(key) +
"]").c_str()
1718 dstObj = archive->objectByUID(dstObj.uid());
1725 template<
typename T,
bool T_isRecursive>
1726 struct SerializationRecursionImpl<
Set<T>*,T_isRecursive> {
1727 static void serializeObject(
Archive* archive,
const Set<T>*& obj) {
1729 SerializationRecursionImpl<Set<T>,T_isRecursive>::serializeObject(
1736 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1737 struct SerializationRecursionImpl<
Map<T_key,T_value>,T_isRecursive> {
1738 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>& obj) {
1739 const UIDChain uids = UIDChainResolver<Map<T_key,T_value>>(obj);
1740 const Object&
object = archive->objectByUID(uids[0]);
1742 for (
const auto& it : obj) {
1744 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1746 archive->serializeHeapMember(
1747 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1751 const_cast<Object&
>(object).m_sync =
1752 [&obj,archive](Object& dstObj,
const Object& srcObj,
1755 const size_t n = srcObj.members().size();
1756 const_cast<Map<T_key,T_value>&
>(obj).
clear();
1758 std::map<String,String> memberNameTranslation;
1759 for (
size_t i = 0; i < n; ++i) {
1760 const Member& member = srcObj.members()[i];
1761 String
name = member.name();
1763 if (
name.length() < 2 ||
name[0] !=
'[' ||
1764 *
name.rbegin() !=
']')
continue;
1767 const UIDChain uids = UIDChainResolver<T_key>(srcKey);
1769 Object tmpObj(uids, type, Object());
1771 tmpObj.setNativeValueFromString(
name);
1772 T_key dstKey = srcKey;
1776 ((Syncer*)syncer)->translateKey(dstKey);
1777 memberNameTranslation[member.name()] =
"[" + toString(dstKey) +
"]";
1779 const_cast<Map<T_key,T_value>&
>(obj)[dstKey] = T_value();
1782 for (
const auto& it : obj) {
1784 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1786 archive->serializeHeapMember(
1787 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1792 dstObj = archive->objectByUID(dstObj.uid());
1794 for (
size_t i = 0; i < n; ++i) {
1795 Member srcMember = srcObj.members()[i];
1796 Member dstMember = dstObj.memberNamed(
1797 memberNameTranslation[srcMember.name()]
1799 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1807 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1808 struct SerializationRecursionImpl<
Map<T_key,T_value>*,T_isRecursive> {
1809 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>*& obj) {
1811 SerializationRecursionImpl<Map<T_key,T_value>,T_isRecursive>::serializeObject(
1818 template<
typename T>
1819 struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
1822 class ObjectPool :
public std::map<UID,Object> {
1825 Object& operator[](
const UID& k) {
1826 static Object invalid;
1831 return std::map<UID,Object>::operator[](k);
1835 friend String _encode(
const ObjectPool& objects);
1838 String _encodeRootBlob();
1839 void _popRootBlob(
const char*& p,
const char* end);
1840 void _popObjectsBlob(
const char*& p,
const char* end);
1886 void syncPrimitive(
const Object& dst,
const Object& src);
1891 void syncPointer(
const Object& dst,
const Object& src);
1892 void syncMember(
const Member& dstMember,
const Member& srcMember);
1899 template<
typename T>
1900 void translateKey(T*& key) {
1901 const UIDChain uids = UIDChainResolver<T*>(key);
1902 assert(uids.size() == 2);
1905 const Object& pointedSrcObject = m_src.m_allObjects[uids[1]];
1906 assert(pointedSrcObject);
1907 std::map<UID,UID>::iterator uidRelation = m_counterparts.find(uids[1]);
1908 if (pointedSrcObject.
parentUID() || uidRelation != m_counterparts.end()) {
1909 assert(uidRelation != m_counterparts.end());
1910 key = (T*) uidRelation->second.id;
1912 assert(pointedSrcObject.
type());
1914 assert(pointedDstObject);
1915 m_dst.m_allObjects[pointedDstObject.
uid()] = pointedDstObject;
1916 key = (T*) pointedDstObject.
uid().
id;
1918 syncObject(pointedDstObject, pointedSrcObject);
1923 template<
typename T>
1924 void translateKey(T& key) {}
1930 std::map<UID,UID> m_counterparts;
1933 virtual void encode();
1935 ObjectPool m_allObjects;
1942 time_t m_timeCreated;
1943 time_t m_timeModified;
1949 template<
typename T>
1952 std::is_default_constructible<T>::value,
1953 "missing default constructor for type: registration of data "
1954 "types is only needed for creating instances of that type at "
1955 "runtime by this framework's reflection API; which in turn "
1956 "requires the type to provide a default constructor."
1958 const DataType staticType = DataType::dataType<T>();
1960 if (m_allocFns.find(staticType.
internalID()) != m_allocFns.end())
return;
1964 T* instance =
new T;
1965 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
1966 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
1967 Object& obj = archive->objectByUID(uids[0]);
1968 if (obj)
return obj;
1976 template<typename T, typename std::enable_if<std::is_default_constructible<T>::value,
bool>::type>
1978 if (!rttiType)
return;
1979 if (m_allocFns.find(rttiType.
internalID()) != m_allocFns.end())
return;
1997 const DataType staticType = DataType::dataType<T>();
1998 if (staticType != rttiType) {
1999 fprintf(stderr,
"Serialization Failure: run-time data type '%s' does not match compile-time data type '%s'!\n",
2002 assert(
false &&
"You may need to explicitly register this run-time "
2003 "data type by either calling "
2004 "DataType::registerNativeType<T>() or using class "
2005 "NativeDataTypeRegistry");
2009 m_allocFns[rttiType.
internalID()] = [](Archive* archive) -> Object {
2010 T* instance =
new T;
2011 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
2012 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
2013 Object& obj = archive->objectByUID(uids[0]);
2014 if (obj)
return obj;
2016 return Object(uids, type, Object());
2022 template<typename T, typename std::enable_if<!std::is_default_constructible<T>::value,
bool>::type>
2025 if (m_allocFns.find(type.internalID()) != m_allocFns.end())
return;
2026 m_allocFns[type.internalID()] = [](Archive*) -> Object {
2027 assert(
false &&
"instance not possible: native data type does not have default constructor");
Synchronizes 2 archives with each other.
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 serializeMember(const T_classType &nativeObject, const T_memberType &nativeMember, const char *memberName)
Serialize a native C/C++ member variable.
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.
void serialize(const T *obj)
Initiate serialization.
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.
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_DESERIALIZE
Archive is currently deserializing.
@ OPERATION_NONE
Archive is currently neither serializing, nor deserializing.
@ OPERATION_SERIALIZE
Archive is currently serializing.
const RawData & rawData()
Raw data stream of this archive content.
bool isModified() const
Whether this archive was modified.
void deserialize(T *obj)
Initiate deserialization.
virtual void decode(const RawData &data)
Fill this archive with the given serialized raw data.
void serializeAnonymousObject(const T_objectType &heapObject)
Serialize anonymous C/C++ 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.
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.
void serializeHeapMember(const T_classType &nativeObject, const T_memberType &heapMember, const char *memberName)
Serialize a C/C++ member variable allocated on the heap.
Object & parentObjectOf(const Object &obj)
Access parent of supplied object.
void operator<<(const T &obj)
Initiate serialization of your C++ objects.
void setComment(String comment)
Assign a comment to this archive.
Archive()
Create an "empty" archive.
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.
void operator>>(T &obj)
Initiate deserialization of your C++ objects.
tm dateTimeModified(time_base_t base=LOCAL_TIME) const
Date and time when this archive was modified for the last time.
Registrator for native data types.
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.
static DataType dataType()
Construct a DataType object for the given native C++ 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).
static void registerNativeDataType()
Manual registration of native C++ data types.
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.
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.
static DataType dataTypeOf(const T &data)
Construct a DataType object for the given native C++ data.
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,...
static UID from(const T &obj)
Create an unique indentifier for a native C++ object/member/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.
Serialization / deserialization framework.
bool IsUnion(const T &)
Check whether data is a C++ union type.
void * ID
Abstract identifier for serialized C++ objects.
bool IsClass(const T &)
Check whether data is a C/C++ struct or C++ class type.
const UID NO_UID
Reflects an invalid UID and behaves similar to NULL as invalid value for pointer types.
std::set< T > Set
Set<> template.
std::string String
Textual string.
std::map< T_key, T_value > Map
Map<> template.
bool IsEnum(const T &)
Check whether data is a C/C++ enum type.
uint32_t Version
Version number data type.
std::vector< UID > UIDChain
Chain of UIDs.
std::vector< T > Array
Array<> template.
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...