24 #ifndef LIBGIG_SERIALIZATION_H
25 #define LIBGIG_SERIALIZATION_H
48 #ifndef __has_extension
49 # define __has_extension(x) 0
52 #ifndef HAS_BUILTIN_TYPE_TRAITS
53 # if __cplusplus >= 201103L
54 # define HAS_BUILTIN_TYPE_TRAITS 1
55 # elif ( __has_extension(is_class) && __has_extension(is_enum) )
56 # define HAS_BUILTIN_TYPE_TRAITS 1
57 # elif ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) )
58 # define HAS_BUILTIN_TYPE_TRAITS 1
59 # elif _MSC_VER >= 1400
60 # define HAS_BUILTIN_TYPE_TRAITS 1
61 # elif __INTEL_COMPILER >= 1100
62 # define HAS_BUILTIN_TYPE_TRAITS 1
64 # define HAS_BUILTIN_TYPE_TRAITS 0
68 #if !HAS_BUILTIN_TYPE_TRAITS
69 # include <tr1/type_traits>
70 # define LIBGIG_IS_CLASS(type) std::tr1::__is_union_or_class<type>::value
72 # define LIBGIG_IS_CLASS(type) __is_class(type)
182 template<
class T_key,
class T_value>
183 using Map = std::map<T_key,T_value>;
235 #if !HAS_BUILTIN_TYPE_TRAITS
236 return std::tr1::is_enum<T>::value;
254 #if !HAS_BUILTIN_TYPE_TRAITS
257 return __is_union(T);
272 #if !HAS_BUILTIN_TYPE_TRAITS
273 return std::tr1::__is_union_or_class<T>::value;
275 return __is_class(T);
300 template<
typename T>
inline
301 String toString(
const T& value) {
303 std::stringstream ss;
304 ss.imbue(std::locale::classic());
311 String toString(
const double& value) {
313 std::stringstream ss;
314 ss.imbue(std::locale::classic());
316 ss.precision(std::numeric_limits<double>::max_digits10);
321 template<
typename T>
inline
322 String toString(T* ptr) {
323 std::stringstream ss;
324 ss.imbue(std::locale::classic());
325 ss <<
"0x" << std::hex << size_t(ptr);
330 String toString(
const String& value) {
357 bool operator==(
const UID& other)
const {
return id == other.
id &&
size == other.
size; }
358 bool operator!=(
const UID& other)
const {
return id != other.id ||
size != other.size; }
359 bool operator<(
const UID& other)
const {
return id < other.id || (
id == other.id &&
size < other.size); }
360 bool operator>(
const UID& other)
const {
return id > other.id || (
id == other.id &&
size > other.size); }
371 return Resolver<T>::resolve(obj);
378 static UID resolve(
const T& obj);
383 struct Resolver<T*> {
384 static UID resolve(
const T*
const & obj);
428 #if LIBGIG_SERIALIZATION_INTERNAL
431 static DataType _popDataTypeBlob(
const char*& p,
const char* end);
432 static Member _popMemberBlob(
const char*& p,
const char* end);
433 static Object _popObjectBlob(
const char*& p,
const char* end);
434 static void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
435 static String _primitiveObjectValueToString(
const Object& obj);
438 static T _primitiveObjectValueToNumber(
const Object& obj);
460 size_t size()
const {
return m_size; }
502 const DataType type = Resolver<T>::resolve(data);
524 const DataType type = Resolver<T>::resolve(unused);
542 const auto itNativeType = m_nativeTypes.find(type.
internalID());
543 return (itNativeType != m_nativeTypes.end()) ?
544 itNativeType->second.size :
sizeof(data);
618 DataType::registerNativeDataType<T>();
629 template<typename T, typename std::enable_if<std::is_default_constructible<T>::value,
bool>::type =
true>
632 template<typename T, typename std::enable_if<!std::is_default_constructible<T>::value,
bool>::type =
true>
635 template<
typename T,
bool T_isPo
inter>
636 struct ResolverBase {
637 static DataType resolve(
const T& data) {
641 const std::type_info& type = (T_isPointer) ?
typeid(T) :
typeid(data);
642 const int sz =
sizeof(data);
647 if (type ==
typeid(int8_t))
return DataType(T_isPointer, sz,
"int8");
648 if (type ==
typeid(uint8_t))
return DataType(T_isPointer, sz,
"uint8");
649 if (type ==
typeid(int16_t))
return DataType(T_isPointer, sz,
"int16");
650 if (type ==
typeid(uint16_t))
return DataType(T_isPointer, sz,
"uint16");
651 if (type ==
typeid(int32_t))
return DataType(T_isPointer, sz,
"int32");
652 if (type ==
typeid(uint32_t))
return DataType(T_isPointer, sz,
"uint32");
653 if (type ==
typeid(int64_t))
return DataType(T_isPointer, sz,
"int64");
654 if (type ==
typeid(uint64_t))
return DataType(T_isPointer, sz,
"uint64");
655 if (type ==
typeid(
size_t)) {
656 if (sz == 1)
return DataType(T_isPointer, sz,
"uint8");
657 if (sz == 2)
return DataType(T_isPointer, sz,
"uint16");
658 if (sz == 4)
return DataType(T_isPointer, sz,
"uint32");
659 if (sz == 8)
return DataType(T_isPointer, sz,
"uint64");
662 if (type ==
typeid(ssize_t)) {
663 if (sz == 1)
return DataType(T_isPointer, sz,
"int8");
664 if (sz == 2)
return DataType(T_isPointer, sz,
"int16");
665 if (sz == 4)
return DataType(T_isPointer, sz,
"int32");
666 if (sz == 8)
return DataType(T_isPointer, sz,
"int64");
669 if (type ==
typeid(
bool))
return DataType(T_isPointer, sz,
"bool");
670 if (type ==
typeid(
float))
return DataType(T_isPointer, sz,
"real32");
671 if (type ==
typeid(
double))
return DataType(T_isPointer, sz,
"real64");
672 if (type ==
typeid(String))
return DataType(T_isPointer, sz,
"String");
681 const String rawCppName =
682 (T_isPointer) ? rawCppTypeName<T>()
683 : rawCppTypeNameOf(data);
685 if (
IsEnum(data))
return DataType(T_isPointer, sz,
"enum", rawCppName);
686 if (
IsUnion(data))
return DataType(T_isPointer, sz,
"union", rawCppName);
687 if (
IsClass(data))
return DataType(T_isPointer, sz,
"class", rawCppName);
695 struct Resolver : ResolverBase<T,false> {
696 static DataType resolve(
const T& data) {
697 return ResolverBase<T,false>::resolve(data);
703 struct Resolver<T*> : ResolverBase<T,true> {
704 static DataType resolve(
const T*
const & data) {
705 return ResolverBase<T,true>::resolve(*data);
711 struct Resolver<
Array<T>> {
712 static DataType resolve(
const Array<T>& data) {
713 const int sz =
sizeof(data);
715 return DataType(
false, sz,
"Array", rawCppTypeNameOf(unused));
721 struct Resolver<
Array<T>*> {
722 static DataType resolve(
const Array<T>*& data) {
723 const int sz =
sizeof(*data);
725 return DataType(
true, sz,
"Array", rawCppTypeNameOf(unused));
731 struct Resolver<
Set<T>> {
732 static DataType resolve(
const Set<T>& data) {
733 const int sz =
sizeof(data);
735 return DataType(
false, sz,
"Set", rawCppTypeNameOf(unused));
741 struct Resolver<
Set<T>*> {
742 static DataType resolve(
const Set<T>*& data) {
743 const int sz =
sizeof(*data);
745 return DataType(
true, sz,
"Set", rawCppTypeNameOf(unused));
750 template<
typename T_key,
typename T_value>
751 struct Resolver<
Map<T_key,T_value>> {
752 static DataType resolve(
const Map<T_key,T_value>& data) {
753 const int sz =
sizeof(data);
754 T_key unused1 = T_key();
755 T_value unused2 = T_value();
756 return DataType(
false, sz,
"Map", rawCppTypeNameOf(unused1),
757 rawCppTypeNameOf(unused2));
762 template<
typename T_key,
typename T_value>
763 struct Resolver<
Map<T_key,T_value>*> {
764 static DataType resolve(
const Map<T_key,T_value>*& data) {
765 const int sz =
sizeof(*data);
766 T_key unused1 = T_key();
767 T_value unused2 = T_value();
768 return DataType(
true, sz,
"Map", rawCppTypeNameOf(unused1),
769 rawCppTypeNameOf(unused2));
775 static String rawCppTypeName() {
776 const std::type_info& type =
typeid(T);
778 String name = type.raw_name();
780 String name = type.name();
789 static String rawCppTypeNameOf(
const T*
const & data) {
790 return rawCppTypeName<T*>();
795 static String rawCppTypeNameOf(
const T& data) {
796 const std::type_info& type =
typeid(data);
798 String name = type.raw_name();
800 String name = type.name();
810 std::function<Object(Archive*)> allocFn;
813 String m_baseTypeName;
814 String m_customTypeName;
815 String m_customTypeName2;
818 static std::map<String,NativeType> m_nativeTypes;
820 #if LIBGIG_SERIALIZATION_INTERNAL
821 friend DataType _popDataTypeBlob(
const char*& p,
const char* end);
823 friend class Archive;
874 #if LIBGIG_SERIALIZATION_INTERNAL
875 friend Member _popMemberBlob(
const char*& p,
const char* end);
908 UID uid(
int index = 0)
const;
916 std::vector<Member>&
members();
917 const std::vector<Member>&
members()
const;
932 void remove(
const Member& member);
943 std::vector<Member> m_members;
944 std::function<void(
Object& dstObj,
const Object& srcObj,
void* syncer)> m_sync;
946 #if LIBGIG_SERIALIZATION_INTERNAL
948 friend Object _popObjectBlob(
const char*& p,
const char* end);
949 friend void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
950 friend String _primitiveObjectValueToString(
const Object& obj);
953 friend T _primitiveObjectValueToNumber(
const Object& obj);
1108 Archive(
const uint8_t* data,
size_t size);
1136 template<
typename T>
1139 m_allObjects.clear();
1171 template<
typename T>
1195 template<
typename T>
1218 template<
typename T>
1282 template<
typename T_
classType,
typename T_memberType>
1283 void serializeMember(
const T_classType& nativeObject,
const T_memberType& nativeMember,
const char* memberName) {
1284 const ssize_t offset =
1285 ((
const uint8_t*)(
const void*)&nativeMember) -
1286 ((
const uint8_t*)(
const void*)&nativeObject);
1287 const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
1290 Object& parent = m_allObjects[parentUID];
1292 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1296 const Member member(memberName, uids[0], offset, type, parent);
1297 std::vector<Member>& members = parent.
members();
1298 for (
const Member& m : members)
1299 assert(m.name() != memberName);
1300 parent.
members().push_back(member);
1301 const Object obj(uids, type, parent);
1302 const bool bExistsAlready = m_allObjects.count(uids[0]);
1303 const bool isValidObject = obj;
1304 const Object& existingObj = m_allObjects[uids[0]];
1305 const bool bExistingObjectIsInvalid = !existingObj;
1306 if (isValidObject && (
1307 !bExistsAlready || bExistingObjectIsInvalid || (
1312 m_allObjects[uids[0]] = obj;
1315 SerializationRecursion<T_memberType>::serializeObject(
this, nativeMember);
1349 template<
typename T_
classType,
typename T_memberType>
1350 void serializeHeapMember(
const T_classType& nativeObject,
const T_memberType& heapMember,
const char* memberName) {
1351 const ssize_t offset = -1;
1352 const UIDChain uids = UIDChainResolver<T_memberType>(heapMember);
1355 Object& parent = m_allObjects[parentUID];
1357 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1361 const Member member(memberName, uids[0], offset, type, parent);
1362 parent.
members().push_back(member);
1363 const Object obj(uids, type, parent);
1364 const bool bExistsAlready = m_allObjects.count(uids[0]);
1365 const bool isValidObject = obj;
1366 const Object& existingObj = m_allObjects[uids[0]];
1367 const bool bExistingObjectIsInvalid = !existingObj;
1368 if (isValidObject && (
1369 !bExistsAlready || bExistingObjectIsInvalid || (
1374 m_allObjects[uids[0]] = obj;
1377 SerializationRecursion<T_memberType>::serializeObject(
this, heapMember);
1401 template<
typename T_
objectType>
1403 const UIDChain uids = UIDChainResolver<T_objectType>(heapObject);
1406 const bool bExistsAlready = m_allObjects.count(uids[0]);
1407 const bool isValidObject = obj;
1408 const Object& existingObj = m_allObjects[uids[0]];
1409 const bool bExistingObjectIsInvalid = !existingObj;
1410 if (isValidObject && (
1411 !bExistsAlready || bExistingObjectIsInvalid || (
1416 m_allObjects[uids[0]] = obj;
1419 SerializationRecursion<T_objectType>::serializeObject(
this, heapObject);
1502 template<
typename T_
classType>
1505 Object& obj = m_allObjects[uid];
1507 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1543 template<
typename T_
classType>
1546 Object& obj = m_allObjects[uid];
1548 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1556 virtual void decode(
const uint8_t* data,
size_t size);
1591 template<
typename T>
1592 class UIDChainResolver {
1594 UIDChainResolver(
const T& data) {
1598 operator UIDChain()
const {
return m_uid; }
1599 UIDChain operator()()
const {
return m_uid; }
1605 template<
typename T>
1606 class UIDChainResolver<T*> {
1608 UIDChainResolver(
const T*
const & data) {
1609 m_uid.push_back({ (
ID) &data,
sizeof(data) });
1613 m_uid.push_back({ (
ID) data,
sizeof(*data) });
1616 operator UIDChain()
const {
return m_uid; }
1617 UIDChain operator()()
const {
return m_uid; }
1623 template<
typename T,
bool T_isRecursive>
1624 struct SerializationRecursionImpl {
1625 static void serializeObject(
Archive* archive,
const T& obj) {
1631 template<
typename T,
bool T_isRecursive>
1632 struct SerializationRecursionImpl<T*,T_isRecursive> {
1633 static void serializeObject(
Archive* archive,
const T*& obj) {
1635 const_cast<T*&
>(obj)->
serialize(archive);
1640 template<
typename T>
1641 struct SerializationRecursionImpl<T,false> {
1642 static void serializeObject(
Archive* ,
const T& ) {}
1646 template<
typename T>
1647 struct SerializationRecursionImpl<T*,
false> {
1648 static void serializeObject(
Archive* archive,
const T*
const & obj) {
1650 archive->serializeAnonymousObject(*obj);
1655 template<
bool T_isRecursive>
1656 struct SerializationRecursionImpl<String,T_isRecursive> {
1657 static void serializeObject(
Archive* archive,
const String& obj) {}
1661 template<
bool T_isRecursive>
1662 struct SerializationRecursionImpl<String*,T_isRecursive> {
1663 static void serializeObject(
Archive* archive,
const String*& obj) {
1665 archive->serializeAnonymousObject(*obj);
1670 template<
typename T,
bool T_isRecursive>
1671 struct SerializationRecursionImpl<
Array<T>,T_isRecursive> {
1672 static void serializeObject(
Archive* archive,
const Array<T>& obj) {
1673 const UIDChain uids = UIDChainResolver<Array<T>>(obj);
1674 const Object&
object = archive->objectByUID(uids[0]);
1676 for (
size_t i = 0; i < obj.size(); ++i) {
1677 archive->serializeHeapMember(
1678 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1682 const_cast<Object&
>(object).m_sync =
1683 [&obj,archive](Object& dstObj,
const Object& srcObj,
1686 const size_t n = srcObj.members().size();
1687 const_cast<Array<T>&
>(obj).resize(n);
1688 for (
size_t i = 0; i < n; ++i) {
1689 archive->serializeHeapMember(
1690 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1695 dstObj = archive->objectByUID(dstObj.uid());
1696 for (
size_t i = 0; i < n; ++i) {
1697 String
name =
"[" + toString(i) +
"]";
1698 Member srcMember = srcObj.memberNamed(
name);
1699 Member dstMember = dstObj.memberNamed(
name);
1700 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1708 template<
typename T,
bool T_isRecursive>
1709 struct SerializationRecursionImpl<
Array<T>*,T_isRecursive> {
1710 static void serializeObject(
Archive* archive,
const Array<T>*& obj) {
1712 SerializationRecursionImpl<Array<T>,T_isRecursive>::serializeObject(
1719 template<
typename T,
bool T_isRecursive>
1720 struct SerializationRecursionImpl<
Set<T>,T_isRecursive> {
1721 static void serializeObject(
Archive* archive,
const Set<T>& obj) {
1722 const UIDChain uids = UIDChainResolver<Set<T>>(obj);
1723 const Object&
object = archive->objectByUID(uids[0]);
1725 for (
const T& key : obj) {
1726 archive->serializeHeapMember(
1727 obj, key, (
"[" + toString(key) +
"]").c_str()
1731 const_cast<Object&
>(object).m_sync =
1732 [&obj,archive](Object& dstObj,
const Object& srcObj,
1735 const size_t n = srcObj.members().size();
1736 const_cast<Set<T>&
>(obj).
clear();
1737 for (
size_t i = 0; i < n; ++i) {
1738 const Member& member = srcObj.members()[i];
1739 String
name = member.name();
1741 if (
name.length() < 2 ||
name[0] !=
'[' ||
1742 *
name.rbegin() !=
']')
continue;
1745 const UIDChain uids = UIDChainResolver<T>(key);
1747 Object tmpObj(uids, type, Object());
1749 tmpObj.setNativeValueFromString(
name);
1753 ((Syncer*)syncer)->translateKey(key);
1755 const_cast<Set<T>&
>(obj).insert(key);
1758 for (
const T& key : obj) {
1759 archive->serializeHeapMember(
1760 obj, key, (
"[" + toString(key) +
"]").c_str()
1765 dstObj = archive->objectByUID(dstObj.uid());
1772 template<
typename T,
bool T_isRecursive>
1773 struct SerializationRecursionImpl<
Set<T>*,T_isRecursive> {
1774 static void serializeObject(
Archive* archive,
const Set<T>*& obj) {
1776 SerializationRecursionImpl<Set<T>,T_isRecursive>::serializeObject(
1783 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1784 struct SerializationRecursionImpl<
Map<T_key,T_value>,T_isRecursive> {
1785 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>& obj) {
1786 const UIDChain uids = UIDChainResolver<Map<T_key,T_value>>(obj);
1787 const Object&
object = archive->objectByUID(uids[0]);
1789 for (
const auto& it : obj) {
1791 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1793 archive->serializeHeapMember(
1794 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1798 const_cast<Object&
>(object).m_sync =
1799 [&obj,archive](Object& dstObj,
const Object& srcObj,
1802 const size_t n = srcObj.members().size();
1803 const_cast<Map<T_key,T_value>&
>(obj).
clear();
1805 std::map<String,String> memberNameTranslation;
1806 for (
size_t i = 0; i < n; ++i) {
1807 const Member& member = srcObj.members()[i];
1808 String
name = member.name();
1810 if (
name.length() < 2 ||
name[0] !=
'[' ||
1811 *
name.rbegin() !=
']')
continue;
1813 T_key srcKey = T_key();
1814 const UIDChain uids = UIDChainResolver<T_key>(srcKey);
1816 Object tmpObj(uids, type, Object());
1818 tmpObj.setNativeValueFromString(
name);
1819 T_key dstKey = srcKey;
1823 ((Syncer*)syncer)->translateKey(dstKey);
1824 memberNameTranslation[member.name()] =
"[" + toString(dstKey) +
"]";
1826 const_cast<Map<T_key,T_value>&
>(obj)[dstKey] = T_value();
1829 for (
const auto& it : obj) {
1831 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1833 archive->serializeHeapMember(
1834 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1839 dstObj = archive->objectByUID(dstObj.uid());
1841 for (
size_t i = 0; i < n; ++i) {
1842 Member srcMember = srcObj.members()[i];
1843 Member dstMember = dstObj.memberNamed(
1844 memberNameTranslation[srcMember.name()]
1846 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1854 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1855 struct SerializationRecursionImpl<
Map<T_key,T_value>*,T_isRecursive> {
1856 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>*& obj) {
1858 SerializationRecursionImpl<Map<T_key,T_value>,T_isRecursive>::serializeObject(
1865 template<
typename T>
1866 struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
1869 class ObjectPool :
public std::map<UID,Object> {
1872 Object& operator[](
const UID& k) {
1874 return invalidObject();
1875 return std::map<UID,Object>::operator[](k);
1878 static Object& invalidObject() {
1879 static Object invalid;
1885 friend String _encode(
const ObjectPool& objects);
1888 String _encodeRootBlob();
1889 void _popRootBlob(
const char*& p,
const char* end);
1890 void _popObjectsBlob(
const char*& p,
const char* end);
1936 void syncPrimitive(
const Object& dst,
const Object& src);
1941 void syncPointer(
const Object& dst,
const Object& src);
1942 void syncMember(
const Member& dstMember,
const Member& srcMember);
1949 template<
typename T>
1950 void translateKey(T*& key) {
1957 UID uid = { (
ID) key,
sizeof(*key) };
1960 assert(pointedSrcObject);
1961 std::map<UID,UID>::iterator uidRelation = m_counterparts.find(uid);
1962 if (pointedSrcObject.
parentUID() || uidRelation != m_counterparts.end()) {
1963 assert(uidRelation != m_counterparts.end());
1964 key = (T*) uidRelation->second.id;
1966 assert(pointedSrcObject.
type());
1968 assert(pointedDstObject);
1969 m_dst.m_allObjects[pointedDstObject.
uid()] = pointedDstObject;
1970 key = (T*) pointedDstObject.
uid().
id;
1972 syncObject(pointedDstObject, pointedSrcObject);
1977 template<
typename T>
1978 void translateKey(T& key) {}
1984 std::map<UID,UID> m_counterparts;
1987 virtual void encode();
1989 ObjectPool m_allObjects;
1996 time_t m_timeCreated;
1997 time_t m_timeModified;
2003 template<
typename T>
2004 UID UID::Resolver<T>::resolve(
const T& obj) {
2006 const UID uid = { (
ID) &obj, size };
2011 template<
typename T>
2012 UID UID::Resolver<T*>::resolve(
const T*
const & obj) {
2014 const UID uid = { (
ID) obj, size };
2019 template<
typename T>
2022 std::is_default_constructible<T>::value,
2023 "missing default constructor for type: registration of data "
2024 "types is only needed for creating instances of that type at "
2025 "runtime by this framework's reflection API; which in turn "
2026 "requires the type to provide a default constructor."
2028 const DataType staticType = DataType::dataType<T>(
false);
2030 const auto itType = m_nativeTypes.find(staticType.
internalID());
2031 if (itType != m_nativeTypes.end()) {
2032 assert(itType->second.size >=
sizeof(T));
2040 T* instance =
new T;
2041 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
2042 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
2044 if (obj)
return obj;
2053 template<typename T, typename std::enable_if<std::is_default_constructible<T>::value,
bool>::type>
2055 if (!rttiType)
return;
2056 if (m_nativeTypes.find(rttiType.
internalID()) != m_nativeTypes.end())
2075 const DataType staticType = DataType::dataType<T>(
false);
2076 if (staticType != rttiType) {
2077 fprintf(stderr,
"Serialization Failure: run-time data type '%s' does not match compile-time data type '%s'!\n",
2080 assert(
false &&
"You may need to explicitly register this run-time "
2081 "data type by either calling "
2082 "DataType::registerNativeType<T>() or using class "
2083 "NativeDataTypeRegistry");
2089 [](Archive* archive) -> Object {
2090 T* instance =
new T;
2091 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
2092 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
2093 Object& obj = archive->objectByUID(uids[0]);
2094 if (obj)
return obj;
2096 return Object(uids, type, Object());
2103 template<typename T, typename std::enable_if<!std::is_default_constructible<T>::value,
bool>::type>
2106 if (m_nativeTypes.find(type.internalID()) != m_nativeTypes.end())
2108 m_nativeTypes[type.internalID()] = {
2110 [](Archive*) -> Object {
2111 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.
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.
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 dataTypeOf(const T &data, bool registerType=true)
Construct a DataType object for the given native C++ data.
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.
static size_t sizeOf(const T &data)
True size of passed native data in bytes.
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 dataType(bool registerType=true)
Construct a DataType object for the given native C++ type.
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...