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)
229 template<
class T_key,
class T_value>
230 using Map = std::map<T_key,T_value>;
282 #if !HAS_BUILTIN_TYPE_TRAITS
283 return std::tr1::is_enum<T>::value;
301 #if !HAS_BUILTIN_TYPE_TRAITS
304 return __is_union(T);
319 #if !HAS_BUILTIN_TYPE_TRAITS
320 return std::tr1::__is_union_or_class<T>::value;
322 return __is_class(T);
347 template<
typename T>
inline
348 String toString(
const T& value) {
350 std::stringstream ss;
351 ss.imbue(std::locale::classic());
358 String toString(
const double& value) {
360 std::stringstream ss;
361 ss.imbue(std::locale::classic());
363 ss.precision(std::numeric_limits<double>::max_digits10);
368 template<
typename T>
inline
369 String toString(T* ptr) {
370 std::stringstream ss;
371 ss.imbue(std::locale::classic());
372 ss <<
"0x" << std::hex << size_t(ptr);
377 String toString(
const String& value) {
381 #if LIBGIG_SERIALIZATION_INTERNAL
384 static T _primitiveObjectValueToNumber(
const Object& obj);
406 size_t size()
const {
return m_size; }
450 const DataType type = Resolver<T>::resolve(data);
472 const DataType type = Resolver<T>::resolve(unused);
490 const auto itNativeType = m_nativeTypes.find(type.
internalID());
491 return (itNativeType != m_nativeTypes.end()) ?
492 itNativeType->second.size :
sizeof(data);
566 DataType::registerNativeDataType<T>();
577 template<
typename T,
typename std::enable_if<
578 !std::is_pointer<T>::value &&
579 std::is_default_constructible<T>::value,
bool>::type =
true>
582 template<
typename T,
typename std::enable_if<
583 !std::is_pointer<T>::value &&
584 !std::is_default_constructible<T>::value,
bool>::type =
true>
587 template<
typename T,
typename std::enable_if<
588 std::is_default_constructible<T>::value,
bool>::type =
true>
591 template<
typename T,
typename std::enable_if<
592 !std::is_default_constructible<T>::value,
bool>::type =
true>
596 template<
typename T,
bool T_isPo
inter>
597 struct ResolverBase {
598 static DataType resolve(
const T& data);
603 struct Resolver : ResolverBase<T,false> {
604 static DataType resolve(
const T& data) {
605 return ResolverBase<T,false>::resolve(data);
611 struct Resolver<T*> : ResolverBase<T,true> {
612 static DataType resolve(
const T*
const & data) {
613 return ResolverBase<T,true>::resolve(*data);
619 struct Resolver<
Array<T>> {
620 static DataType resolve(
const Array<T>& data) {
621 const int sz =
sizeof(data);
623 return DataType(
false, sz,
"Array", rawCppTypeNameOf(unused));
629 struct Resolver<
Array<T>*> {
630 static DataType resolve(
const Array<T>*& data) {
631 const int sz =
sizeof(*data);
633 return DataType(
true, sz,
"Array", rawCppTypeNameOf(unused));
639 struct Resolver<
Set<T>> {
640 static DataType resolve(
const Set<T>& data) {
641 const int sz =
sizeof(data);
643 return DataType(
false, sz,
"Set", rawCppTypeNameOf(unused));
649 struct Resolver<
Set<T>*> {
650 static DataType resolve(
const Set<T>*& data) {
651 const int sz =
sizeof(*data);
653 return DataType(
true, sz,
"Set", rawCppTypeNameOf(unused));
658 template<
typename T_key,
typename T_value>
659 struct Resolver<
Map<T_key,T_value>> {
660 static DataType resolve(
const Map<T_key,T_value>& data) {
661 const int sz =
sizeof(data);
662 T_key unused1 = T_key();
663 T_value unused2 = T_value();
664 return DataType(
false, sz,
"Map", rawCppTypeNameOf(unused1),
665 rawCppTypeNameOf(unused2));
670 template<
typename T_key,
typename T_value>
671 struct Resolver<
Map<T_key,T_value>*> {
672 static DataType resolve(
const Map<T_key,T_value>*& data) {
673 const int sz =
sizeof(*data);
674 T_key unused1 = T_key();
675 T_value unused2 = T_value();
676 return DataType(
true, sz,
"Map", rawCppTypeNameOf(unused1),
677 rawCppTypeNameOf(unused2));
683 static String rawCppTypeName() {
684 const std::type_info& type =
typeid(T);
686 String name = type.raw_name();
688 String name = type.name();
697 static String rawCppTypeNameOf(
const T*
const & data) {
698 return rawCppTypeName<T*>();
703 static String rawCppTypeNameOf(
const T& data) {
704 const std::type_info& type =
typeid(data);
706 String name = type.raw_name();
708 String name = type.name();
718 std::function<Object(Archive*)> allocFn;
723 String m_baseTypeName;
724 String m_customTypeName;
725 String m_customTypeName2;
727 static std::map<String,NativeType> m_nativeTypes;
729 friend class Archive;
730 friend class SrxFormat;
731 friend class SrxJSONDecoder;
757 bool operator==(
const UID& other)
const {
return id == other.
id &&
size == other.
size; }
758 bool operator!=(
const UID& other)
const {
return id != other.id ||
size != other.size; }
759 bool operator<(
const UID& other)
const {
return id < other.id || (
id == other.id &&
size < other.size); }
760 bool operator>(
const UID& other)
const {
return id > other.id || (
id == other.id &&
size > other.size); }
771 return Resolver<T>::resolve(obj);
778 static UID resolve(
const T& obj);
783 struct Resolver<T*> {
784 static UID resolve(
const T*
const & obj);
876 friend class SrxFormat;
877 friend class SrxJSONDecoder;
909 UID uid(
int index = 0)
const;
917 std::vector<Member>&
members();
918 const std::vector<Member>&
members()
const;
933 void remove(
const Member& member);
944 std::vector<Member> m_members;
945 std::function<void(
Object& dstObj,
const Object& srcObj,
void* syncer)> m_sync;
947 #if LIBGIG_SERIALIZATION_INTERNAL
949 friend T _primitiveObjectValueToNumber(
const Object& obj);
953 friend class SrxFormat;
954 friend class SrxJSONDecoder;
1162 template<
typename T>
1165 m_allObjects.clear();
1167 preregisterNativeObject(*obj);
1198 template<
typename T>
1202 a.preregisterNativeObject(*obj);
1223 template<
typename T>
1246 template<
typename T>
1310 template<
typename T_
classType,
typename T_memberType>
1311 void serializeMember(
const T_classType& nativeObject,
const T_memberType& nativeMember,
const char* memberName) {
1312 Object& parent = preregisterNativeObject(nativeObject);
1313 const ssize_t offset =
1314 ((
const uint8_t*)(
const void*)&nativeMember) -
1315 ((
const uint8_t*)(
const void*)&nativeObject);
1316 const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
1318 const Member member(memberName, uids[0], offset, type, parent);
1319 std::vector<Member>& members = parent.
members();
1320 for (
const Member& m : members)
1321 assert(m.name() != memberName);
1322 parent.
members().push_back(member);
1323 const Object obj(uids, type, parent);
1324 const bool bExistsAlready = m_allObjects.count(uids[0]);
1325 const bool isValidObject = obj;
1326 const Object& existingObj = m_allObjects[uids[0]];
1327 const bool bExistingObjectIsInvalid = !existingObj;
1328 if (isValidObject && (
1329 !bExistsAlready || bExistingObjectIsInvalid || (
1334 m_allObjects[uids[0]] = obj;
1337 SerializationRecursion<T_memberType>::serializeObject(
this, nativeMember);
1371 template<
typename T_
classType,
typename T_memberType>
1372 void serializeHeapMember(
const T_classType& nativeObject,
const T_memberType& heapMember,
const char* memberName) {
1373 Object& parent = preregisterNativeObject(nativeObject);
1374 const ssize_t offset = -1;
1375 const UIDChain uids = UIDChainResolver<T_memberType>(heapMember);
1377 const Member member(memberName, uids[0], offset, type, parent);
1378 parent.
members().push_back(member);
1379 const Object obj(uids, type, parent);
1380 const bool bExistsAlready = m_allObjects.count(uids[0]);
1381 const bool isValidObject = obj;
1382 const Object& existingObj = m_allObjects[uids[0]];
1383 const bool bExistingObjectIsInvalid = !existingObj;
1384 if (isValidObject && (
1385 !bExistsAlready || bExistingObjectIsInvalid || (
1390 m_allObjects[uids[0]] = obj;
1393 SerializationRecursion<T_memberType>::serializeObject(
this, heapMember);
1417 template<
typename T_
objectType>
1419 const UIDChain uids = UIDChainResolver<T_objectType>(heapObject);
1422 const bool bExistsAlready = m_allObjects.count(uids[0]);
1423 const bool isValidObject = obj;
1424 const Object& existingObj = m_allObjects[uids[0]];
1425 const bool bExistingObjectIsInvalid = !existingObj;
1426 if (isValidObject && (
1427 !bExistsAlready || bExistingObjectIsInvalid || (
1432 m_allObjects[uids[0]] = obj;
1435 SerializationRecursion<T_objectType>::serializeObject(
this, heapObject);
1518 template<
typename T_
classType>
1521 Object& obj = m_allObjects[uid];
1523 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1559 template<
typename T_
classType>
1562 Object& obj = m_allObjects[uid];
1564 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1573 virtual void decode(
const uint8_t* data,
size_t size);
1574 virtual void decode(
const uint8_t* data,
size_t size,
format_t format);
1609 static String primitiveObjectValueToString(
const Object& obj);
1611 template<
typename T_
classType>
1612 Object& preregisterNativeObject(
const T_classType& nativeObject) {
1614 Object& obj = m_allObjects[uid];
1616 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1624 template<
typename T>
1625 class UIDChainResolver {
1627 UIDChainResolver(
const T& data) {
1631 operator UIDChain()
const {
return m_uid; }
1632 UIDChain operator()()
const {
return m_uid; }
1638 template<
typename T>
1639 class UIDChainResolver<T*> {
1641 UIDChainResolver(
const T*
const & data) {
1642 m_uid.push_back({ (
ID) &data,
sizeof(data) });
1646 m_uid.push_back({ (
ID) data,
sizeof(*data) });
1649 operator UIDChain()
const {
return m_uid; }
1650 UIDChain operator()()
const {
return m_uid; }
1656 template<
typename T,
bool T_isRecursive>
1657 struct SerializationRecursionImpl {
1658 static void serializeObject(
Archive* archive,
const T& obj) {
1664 template<
typename T,
bool T_isRecursive>
1665 struct SerializationRecursionImpl<T*,T_isRecursive> {
1666 static void serializeObject(
Archive* archive,
const T*& obj) {
1668 const_cast<T*&
>(obj)->
serialize(archive);
1673 template<
typename T>
1674 struct SerializationRecursionImpl<T,false> {
1675 static void serializeObject(
Archive* ,
const T& ) {}
1679 template<
typename T>
1680 struct SerializationRecursionImpl<T*,
false> {
1681 static void serializeObject(
Archive* archive,
const T*
const & obj) {
1683 archive->serializeAnonymousObject(*obj);
1688 template<
bool T_isRecursive>
1689 struct SerializationRecursionImpl<String,T_isRecursive> {
1690 static void serializeObject(
Archive* archive,
const String& obj) {}
1694 template<
bool T_isRecursive>
1695 struct SerializationRecursionImpl<String*,T_isRecursive> {
1696 static void serializeObject(
Archive* archive,
const String*& obj) {
1698 archive->serializeAnonymousObject(*obj);
1703 template<
typename T,
bool T_isRecursive>
1704 struct SerializationRecursionImpl<
Array<T>,T_isRecursive> {
1705 static void serializeObject(
Archive* archive,
const Array<T>& obj) {
1706 const UIDChain uids = UIDChainResolver<Array<T>>(obj);
1707 const Object&
object = archive->objectByUID(uids[0]);
1709 for (
size_t i = 0; i < obj.size(); ++i) {
1710 archive->serializeHeapMember(
1711 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1715 const_cast<Object&
>(object).m_sync =
1716 [&obj,archive](Object& dstObj,
const Object& srcObj,
1719 const size_t n = srcObj.members().size();
1720 const_cast<Array<T>&
>(obj).resize(n);
1721 for (
size_t i = 0; i < n; ++i) {
1722 archive->serializeHeapMember(
1723 obj, obj[i], (
"[" + toString(i) +
"]").c_str()
1728 dstObj = archive->objectByUID(dstObj.uid());
1729 for (
size_t i = 0; i < n; ++i) {
1730 String
name =
"[" + toString(i) +
"]";
1731 Member srcMember = srcObj.memberNamed(
name);
1732 Member dstMember = dstObj.memberNamed(
name);
1733 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1741 template<
typename T,
bool T_isRecursive>
1742 struct SerializationRecursionImpl<
Array<T>*,T_isRecursive> {
1743 static void serializeObject(
Archive* archive,
const Array<T>*& obj) {
1745 SerializationRecursionImpl<Array<T>,T_isRecursive>::serializeObject(
1752 template<
typename T,
bool T_isRecursive>
1753 struct SerializationRecursionImpl<
Set<T>,T_isRecursive> {
1754 static void serializeObject(
Archive* archive,
const Set<T>& obj) {
1755 const UIDChain uids = UIDChainResolver<Set<T>>(obj);
1756 const Object&
object = archive->objectByUID(uids[0]);
1758 for (
const T& key : obj) {
1759 archive->serializeHeapMember(
1760 obj, key, (
"[" + toString(key) +
"]").c_str()
1764 const_cast<Object&
>(object).m_sync =
1765 [&obj,archive](Object& dstObj,
const Object& srcObj,
1768 const size_t n = srcObj.members().size();
1769 const_cast<Set<T>&
>(obj).
clear();
1770 for (
size_t i = 0; i < n; ++i) {
1771 const Member& member = srcObj.members()[i];
1772 String
name = member.name();
1774 if (
name.length() < 2 ||
name[0] !=
'[' ||
1775 *
name.rbegin() !=
']')
continue;
1778 const UIDChain uids = UIDChainResolver<T>(key);
1780 Object tmpObj(uids, type, Object());
1782 tmpObj.setNativeValueFromString(
name);
1786 ((Syncer*)syncer)->translateKey(key);
1788 const_cast<Set<T>&
>(obj).insert(key);
1791 for (
const T& key : obj) {
1792 archive->serializeHeapMember(
1793 obj, key, (
"[" + toString(key) +
"]").c_str()
1798 dstObj = archive->objectByUID(dstObj.uid());
1805 template<
typename T,
bool T_isRecursive>
1806 struct SerializationRecursionImpl<
Set<T>*,T_isRecursive> {
1807 static void serializeObject(
Archive* archive,
const Set<T>*& obj) {
1809 SerializationRecursionImpl<Set<T>,T_isRecursive>::serializeObject(
1816 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1817 struct SerializationRecursionImpl<
Map<T_key,T_value>,T_isRecursive> {
1818 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>& obj) {
1819 const UIDChain uids = UIDChainResolver<Map<T_key,T_value>>(obj);
1820 const Object&
object = archive->objectByUID(uids[0]);
1822 for (
const auto& it : obj) {
1824 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1826 archive->serializeHeapMember(
1827 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1831 const_cast<Object&
>(object).m_sync =
1832 [&obj,archive](Object& dstObj,
const Object& srcObj,
1835 const size_t n = srcObj.members().size();
1836 const_cast<Map<T_key,T_value>&
>(obj).
clear();
1838 std::map<String,String> memberNameTranslation;
1839 for (
size_t i = 0; i < n; ++i) {
1840 const Member& member = srcObj.members()[i];
1841 String
name = member.name();
1843 if (
name.length() < 2 ||
name[0] !=
'[' ||
1844 *
name.rbegin() !=
']')
continue;
1846 T_key srcKey = T_key();
1847 const UIDChain uids = UIDChainResolver<T_key>(srcKey);
1849 Object tmpObj(uids, type, Object());
1851 tmpObj.setNativeValueFromString(
name);
1852 T_key dstKey = srcKey;
1856 ((Syncer*)syncer)->translateKey(dstKey);
1857 memberNameTranslation[member.name()] =
"[" + toString(dstKey) +
"]";
1859 const_cast<Map<T_key,T_value>&
>(obj)[dstKey] = T_value();
1862 for (
const auto& it : obj) {
1864 SerializationRecursion<T_key>::serializeObject(archive, it.first);
1866 archive->serializeHeapMember(
1867 obj, it.second, (
"[" + toString(it.first) +
"]").c_str()
1872 dstObj = archive->objectByUID(dstObj.uid());
1874 for (
size_t i = 0; i < n; ++i) {
1875 Member srcMember = srcObj.members()[i];
1876 Member dstMember = dstObj.memberNamed(
1877 memberNameTranslation[srcMember.name()]
1879 ((Syncer*)syncer)->syncMember(dstMember, srcMember);
1887 template<
typename T_key,
typename T_value,
bool T_isRecursive>
1888 struct SerializationRecursionImpl<
Map<T_key,T_value>*,T_isRecursive> {
1889 static void serializeObject(
Archive* archive,
const Map<T_key,T_value>*& obj) {
1891 SerializationRecursionImpl<Map<T_key,T_value>,T_isRecursive>::serializeObject(
1898 template<
typename T>
1899 struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
1902 class ObjectPool :
public std::map<UID,Object> {
1905 Object& operator[](
const UID& k) {
1907 return invalidObject();
1908 return std::map<UID,Object>::operator[](k);
1911 static Object& invalidObject() {
1912 static Object invalid;
1962 void syncPrimitive(
const Object& dst,
const Object& src);
1967 void syncPointer(
const Object& dst,
const Object& src);
1968 void syncMember(
const Member& dstMember,
const Member& srcMember);
1975 template<
typename T>
1976 void translateKey(T*& key) {
1983 UID uid = { (
ID) key,
sizeof(*key) };
1986 assert(pointedSrcObject);
1987 std::map<UID,UID>::iterator uidRelation = m_counterparts.find(uid);
1988 if (pointedSrcObject.
parentUID() || uidRelation != m_counterparts.end()) {
1989 assert(uidRelation != m_counterparts.end());
1990 key = (T*) uidRelation->second.id;
1992 assert(pointedSrcObject.
type());
1994 assert(pointedDstObject);
1995 m_dst.m_allObjects[pointedDstObject.
uid()] = pointedDstObject;
1996 key = (T*) pointedDstObject.
uid().
id;
1998 syncObject(pointedDstObject, pointedSrcObject);
2003 template<
typename T>
2004 void translateKey(T& key) {}
2010 std::map<UID,UID> m_counterparts;
2013 virtual void encode();
2014 virtual void encode(
format_t format);
2016 ObjectPool m_allObjects;
2024 time_t m_timeCreated;
2025 time_t m_timeModified;
2028 friend class SrxFormat;
2029 friend class SrxJSONEncoder;
2030 friend class SrxJSONDecoder;
2034 template<
typename T>
2035 UID UID::Resolver<T>::resolve(
const T& obj) {
2037 const UID uid = { (
ID) &obj, size };
2042 template<
typename T>
2043 UID UID::Resolver<T*>::resolve(
const T*
const & obj) {
2045 const UID uid = { (
ID) obj, size };
2050 template<
typename T>
2053 std::is_default_constructible<T>::value,
2054 "missing default constructor for type: registration of data "
2055 "types is only needed for creating instances of that type at "
2056 "runtime by this framework's reflection API; which in turn "
2057 "requires the type to provide a default constructor."
2059 const DataType staticType = DataType::dataType<T>(
false);
2061 const auto itType = m_nativeTypes.find(staticType.
internalID());
2062 if (itType != m_nativeTypes.end()) {
2063 assert(itType->second.size >=
sizeof(T));
2071 T* instance =
new T;
2072 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
2073 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
2075 if (obj)
return obj;
2084 template<
typename T,
typename std::enable_if<
2085 !std::is_pointer<T>::value &&
2086 std::is_default_constructible<T>::value,
bool>::type>
2088 if (!rttiType)
return;
2089 if (m_nativeTypes.find(rttiType.
internalID()) != m_nativeTypes.end())
2108 const DataType staticType = DataType::dataType<T>(
false);
2109 if (staticType != rttiType) {
2110 fprintf(stderr,
"Serialization Failure: run-time data type '%s' does not match compile-time data type '%s'!\n",
2113 assert(
false &&
"You may need to explicitly register this run-time "
2114 "data type by either calling "
2115 "DataType::registerNativeType<T>() or using class "
2116 "NativeDataTypeRegistry");
2122 [](Archive* archive) -> Object {
2123 T* instance =
new T;
2124 Archive::SerializationRecursion<T>::serializeObject(archive, *instance);
2125 const UIDChain uids = Archive::UIDChainResolver<T>(*instance);
2126 Object& obj = archive->objectByUID(uids[0]);
2127 if (obj)
return obj;
2129 return Object(uids, type, Object());
2136 template<
typename T,
typename std::enable_if<
2137 !std::is_pointer<T>::value &&
2138 !std::is_default_constructible<T>::value,
bool>::type>
2141 if (m_nativeTypes.find(type.internalID()) != m_nativeTypes.end())
2143 m_nativeTypes[type.internalID()] = {
2145 [](Archive*) -> Object {
2146 assert(
false &&
"instance not possible: native data type does not have default constructor");
2154 template<
typename T,
typename std::enable_if<
2155 std::is_default_constructible<T>::value,
bool>::type>
2157 const T*
const& nativeData)
2161 const DataType staticType = DataType::Resolver<T>::resolve(unused);
2164 if (!nativeData)
return;
2165 const DataType rttiType = DataType::Resolver<T>::resolve(*nativeData);
2171 template<
typename T,
typename std::enable_if<
2172 !std::is_default_constructible<T>::value,
bool>::type>
2174 const T*
const& nativeData)
2177 if (!nativeData)
return;
2178 const DataType nonPointerType = DataType::Resolver<T>::resolve(*nativeData);
2183 template<
typename T,
bool T_isPo
inter>
2184 DataType DataType::ResolverBase<T,T_isPointer>::resolve(
const T& data) {
2188 const std::type_info& type = (T_isPointer) ?
typeid(T) :
typeid(data);
2189 const int sz =
sizeof(data);
2194 if (type ==
typeid(
char))
2198 return DataType(T_isPointer, sz,
"char");
2199 if (type ==
typeid(int8_t))
return DataType(T_isPointer, sz,
"int8");
2200 if (type ==
typeid(uint8_t))
return DataType(T_isPointer, sz,
"uint8");
2201 if (type ==
typeid(int16_t))
return DataType(T_isPointer, sz,
"int16");
2202 if (type ==
typeid(uint16_t))
return DataType(T_isPointer, sz,
"uint16");
2203 if (type ==
typeid(int32_t))
return DataType(T_isPointer, sz,
"int32");
2204 if (type ==
typeid(uint32_t))
return DataType(T_isPointer, sz,
"uint32");
2205 if (type ==
typeid(int64_t))
return DataType(T_isPointer, sz,
"int64");
2206 if (type ==
typeid(uint64_t))
return DataType(T_isPointer, sz,
"uint64");
2209 if (type ==
typeid(
long) || type ==
typeid(int)) {
2210 if (sz == 1)
return DataType(T_isPointer, sz,
"int8");
2211 if (sz == 2)
return DataType(T_isPointer, sz,
"int16");
2212 if (sz == 4)
return DataType(T_isPointer, sz,
"int32");
2213 if (sz == 8)
return DataType(T_isPointer, sz,
"int64");
2214 else assert(
false );
2216 if (type ==
typeid(
unsigned long) || type ==
typeid(
unsigned int)) {
2217 if (sz == 1)
return DataType(T_isPointer, sz,
"uint8");
2218 if (sz == 2)
return DataType(T_isPointer, sz,
"uint16");
2219 if (sz == 4)
return DataType(T_isPointer, sz,
"uint32");
2220 if (sz == 8)
return DataType(T_isPointer, sz,
"uint64");
2221 else assert(
false );
2223 if (type ==
typeid(
bool))
return DataType(T_isPointer, sz,
"bool");
2224 if (type ==
typeid(
float))
return DataType(T_isPointer, sz,
"real32");
2225 if (type ==
typeid(
double))
return DataType(T_isPointer, sz,
"real64");
2226 if (type ==
typeid(String))
return DataType(T_isPointer, sz,
"String");
2235 const String rawCppName =
2236 (T_isPointer) ? rawCppTypeName<T>()
2237 : rawCppTypeNameOf(data);
2239 if (
IsEnum(data))
return DataType(T_isPointer, sz,
"enum", rawCppName);
2240 if (
IsUnion(data))
return DataType(T_isPointer, sz,
"union", rawCppName);
2241 if (
IsClass(data))
return DataType(T_isPointer, sz,
"class", rawCppName);
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 setCharValue(Object &object, char value)
Set new char value for given character object.
char valueAsChar(const Object &object)
Get char value of 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.
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_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.
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.
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 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).
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.
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.
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.
C++ 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...