24 #ifndef LIBGIG_SERIALIZATION_H 25 #define LIBGIG_SERIALIZATION_H 40 #ifndef __has_extension 41 # define __has_extension(x) 0 44 #ifndef HAS_BUILTIN_TYPE_TRAITS 45 # if __cplusplus >= 201103L 46 # define HAS_BUILTIN_TYPE_TRAITS 1 47 # elif ( __has_extension(is_class) && __has_extension(is_enum) ) 48 # define HAS_BUILTIN_TYPE_TRAITS 1 49 # elif ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 3 ) ) 50 # define HAS_BUILTIN_TYPE_TRAITS 1 51 # elif _MSC_VER >= 1400 52 # define HAS_BUILTIN_TYPE_TRAITS 1 53 # elif __INTEL_COMPILER >= 1100 54 # define HAS_BUILTIN_TYPE_TRAITS 1 56 # define HAS_BUILTIN_TYPE_TRAITS 0 60 #if !HAS_BUILTIN_TYPE_TRAITS 61 # include <tr1/type_traits> 62 # define LIBGIG_IS_CLASS(type) std::tr1::__is_union_or_class<type>::value //NOTE: without compiler support we cannot distinguish union from class 64 # define LIBGIG_IS_CLASS(type) __is_class(type) 120 typedef std::string String;
172 #if !HAS_BUILTIN_TYPE_TRAITS 173 return std::tr1::is_enum<T>::value;
191 #if !HAS_BUILTIN_TYPE_TRAITS 194 return __is_union(T);
209 #if !HAS_BUILTIN_TYPE_TRAITS 210 return std::tr1::__is_union_or_class<T>::value;
212 return __is_class(T);
249 bool operator==(
const UID& other)
const {
return id == other.
id && size == other.
size; }
250 bool operator!=(
const UID& other)
const {
return id != other.
id || size != other.
size; }
251 bool operator<(
const UID& other)
const {
return id < other.
id || (
id == other.
id && size < other.
size); }
252 bool operator>(
const UID& other)
const {
return id > other.
id || (
id == other.
id && size > other.
size); }
263 return Resolver<T>::resolve(obj);
270 static UID resolve(
const T& obj) {
271 const UID uid = { (
ID) &obj,
sizeof(obj) };
278 struct Resolver<T*> {
279 static UID resolve(
const T*
const & obj) {
280 const UID uid = { (
ID) obj,
sizeof(*obj) };
327 static String _encodePrimitiveValue(
const Object& obj);
328 static DataType _popDataTypeBlob(
const char*& p,
const char* end);
329 static Member _popMemberBlob(
const char*& p,
const char* end);
330 static Object _popObjectBlob(
const char*& p,
const char* end);
331 static void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
332 static String _primitiveObjectValueToString(
const Object& obj);
335 static T _primitiveObjectValueToNumber(
const Object& obj);
356 size_t size()
const {
return m_size; }
358 bool isPointer()
const;
359 bool isClass()
const;
360 bool isPrimitive()
const;
361 bool isInteger()
const;
365 bool isSigned()
const;
368 bool operator==(
const DataType& other)
const;
369 bool operator!=(
const DataType& other)
const;
370 bool operator<(
const DataType& other)
const;
371 bool operator>(
const DataType& other)
const;
372 String asLongDescr()
const;
373 String baseTypeName()
const;
374 String customTypeName(
bool demangle =
false)
const;
388 return Resolver<T>::resolve(data);
392 DataType(
bool isPointer,
int size, String baseType, String customType =
"");
394 template<
typename T,
bool T_isPo
inter>
395 struct ResolverBase {
396 static DataType resolve(
const T& data) {
397 const std::type_info& type =
typeid(data);
398 const int sz =
sizeof(data);
403 if (type ==
typeid(int8_t))
return DataType(T_isPointer, sz,
"int8");
404 if (type ==
typeid(uint8_t))
return DataType(T_isPointer, sz,
"uint8");
405 if (type ==
typeid(int16_t))
return DataType(T_isPointer, sz,
"int16");
406 if (type ==
typeid(uint16_t))
return DataType(T_isPointer, sz,
"uint16");
407 if (type ==
typeid(int32_t))
return DataType(T_isPointer, sz,
"int32");
408 if (type ==
typeid(uint32_t))
return DataType(T_isPointer, sz,
"uint32");
409 if (type ==
typeid(int64_t))
return DataType(T_isPointer, sz,
"int64");
410 if (type ==
typeid(uint64_t))
return DataType(T_isPointer, sz,
"uint64");
411 if (type ==
typeid(
bool))
return DataType(T_isPointer, sz,
"bool");
412 if (type ==
typeid(
float))
return DataType(T_isPointer, sz,
"real32");
413 if (type ==
typeid(
double))
return DataType(T_isPointer, sz,
"real64");
415 if (
IsEnum(data))
return DataType(T_isPointer, sz,
"enum", rawCppTypeNameOf(data));
416 if (
IsUnion(data))
return DataType(T_isPointer, sz,
"union", rawCppTypeNameOf(data));
417 if (
IsClass(data))
return DataType(T_isPointer, sz,
"class", rawCppTypeNameOf(data));
425 struct Resolver : ResolverBase<T,false> {
426 static DataType resolve(
const T& data) {
427 return ResolverBase<T,false>::resolve(data);
433 struct Resolver<T*> : ResolverBase<T,true> {
434 static DataType resolve(
const T*& data) {
435 return ResolverBase<T,true>::resolve(*data);
440 static String rawCppTypeNameOf(
const T& data) {
441 #if defined _MSC_VER // Microsoft compiler ... 442 # warning type_info::raw_name() demangling has not been tested yet with Microsoft compiler! Feedback appreciated! 443 String name =
typeid(data).raw_name();
444 #else // i.e. especially GCC and clang ... 445 String name =
typeid(data).name();
453 String m_baseTypeName;
454 String m_customTypeName;
458 friend DataType _popDataTypeBlob(
const char*& p,
const char* end);
488 size_t offset()
const;
493 bool operator==(
const Member& other)
const;
494 bool operator!=(
const Member& other)
const;
495 bool operator<(
const Member& other)
const;
496 bool operator>(
const Member& other)
const;
508 friend Member _popMemberBlob(
const char*& p,
const char* end);
540 UID uid(
int index = 0)
const;
541 const UIDChain& uidChain()
const;
543 const RawData& rawData()
const;
544 Version version()
const;
545 Version minVersion()
const;
546 bool isVersionCompatibleTo(
const Object& other)
const;
547 std::vector<Member>& members();
548 const std::vector<Member>& members()
const;
549 Member memberNamed(String name)
const;
550 Member memberByUID(
const UID& uid)
const;
551 std::vector<Member> membersOfType(
const DataType& type)
const;
552 int sequenceIndexOf(
const Member& member)
const;
556 bool operator==(
const Object& other)
const;
557 bool operator!=(
const Object& other)
const;
558 bool operator<(
const Object& other)
const;
559 bool operator>(
const Object& other)
const;
562 void remove(
const Member& member);
563 void setVersion(Version v);
564 void setMinVersion(Version v);
570 Version m_minVersion;
572 std::vector<Member> m_members;
574 friend String _encodePrimitiveValue(
const Object& obj);
575 friend Object _popObjectBlob(
const char*& p,
const char* end);
576 friend void _popPrimitiveValue(
const char*& p,
const char* end,
Object& obj);
577 friend String _primitiveObjectValueToString(
const Object& obj);
580 friend T _primitiveObjectValueToNumber(
const Object& obj);
736 m_operation = OPERATION_SERIALIZE;
737 m_allObjects.clear();
740 const_cast<T*
>(obj)->serialize(
this);
742 m_operation = OPERATION_NONE;
772 m_operation = OPERATION_DESERIALIZE;
776 m_operation = OPERATION_NONE;
821 const RawData& rawData();
822 virtual String rawDataFormat()
const;
869 template<
typename T_
classType,
typename T_memberType>
870 void serializeMember(
const T_classType& nativeObject,
const T_memberType& nativeMember,
const char* memberName) {
871 const size_t offset =
872 ((
const uint8_t*)(
const void*)&nativeMember) -
873 ((
const uint8_t*)(
const void*)&nativeObject);
874 const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
876 const Member member(memberName, uids[0], offset, type);
878 Object& parent = m_allObjects[parentUID];
880 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
882 parent =
Object(uids, type);
884 parent.
members().push_back(member);
885 const Object obj(uids, type);
886 const bool bExistsAlready = m_allObjects.count(uids[0]);
887 const bool isValidObject = obj;
888 const bool bExistingObjectIsInvalid = !m_allObjects[uids[0]];
889 if (!bExistsAlready || (bExistingObjectIsInvalid && isValidObject)) {
890 m_allObjects[uids[0]] = obj;
893 SerializationRecursion<T_memberType>::serializeObject(
this, nativeMember);
966 template<
typename T_
classType>
967 void setVersion(
const T_classType& nativeObject, Version v) {
969 Object& obj = m_allObjects[uid];
971 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1007 template<
typename T_
classType>
1010 Object& obj = m_allObjects[uid];
1012 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
1014 obj =
Object(uids, type);
1016 setMinVersion(obj, v);
1019 virtual void decode(
const RawData& data);
1020 virtual void decode(
const uint8_t* data,
size_t size);
1022 bool isModified()
const;
1023 void removeMember(
Object& parent,
const Member& member);
1024 void remove(
const Object& obj);
1027 void setAutoValue(
Object&
object, String value);
1028 void setIntValue(
Object&
object, int64_t value);
1029 void setRealValue(
Object&
object,
double value);
1030 void setBoolValue(
Object&
object,
bool value);
1031 void setEnumValue(
Object&
object, uint64_t value);
1032 String valueAsString(
const Object&
object);
1033 int64_t valueAsInt(
const Object&
object);
1034 double valueAsReal(
const Object&
object);
1035 bool valueAsBool(
const Object&
object);
1036 void setVersion(
Object&
object, Version v);
1037 void setMinVersion(
Object&
object, Version v);
1038 String name()
const;
1039 void setName(String name);
1040 String comment()
const;
1041 void setComment(String comment);
1042 time_t timeStampCreated()
const;
1043 time_t timeStampModified()
const;
1049 template<
typename T>
1050 class UIDChainResolver {
1052 UIDChainResolver(
const T& data) {
1056 operator UIDChain()
const {
return m_uid; }
1057 UIDChain operator()()
const {
return m_uid; }
1063 template<
typename T>
1064 class UIDChainResolver<T*> {
1066 UIDChainResolver(
const T*& data) {
1067 const UID uids[2] = {
1068 { &data,
sizeof(data) },
1069 { data,
sizeof(*data) }
1071 m_uid.push_back(uids[0]);
1072 m_uid.push_back(uids[1]);
1075 operator UIDChain()
const {
return m_uid; }
1076 UIDChain operator()()
const {
return m_uid; }
1082 template<
typename T,
bool T_isRecursive>
1083 struct SerializationRecursionImpl {
1084 static void serializeObject(
Archive* archive,
const T& obj) {
1085 const_cast<T&
>(obj).serialize(archive);
1090 template<
typename T,
bool T_isRecursive>
1091 struct SerializationRecursionImpl<T*,T_isRecursive> {
1092 static void serializeObject(
Archive* archive,
const T*& obj) {
1094 const_cast<T*&
>(obj)->serialize(archive);
1099 template<
typename T>
1100 struct SerializationRecursionImpl<T,false> {
1101 static void serializeObject(
Archive* archive,
const T& obj) {}
1105 template<
typename T>
1106 struct SerializationRecursionImpl<T*,
false> {
1107 static void serializeObject(
Archive* archive,
const T*& obj) {}
1111 template<
typename T>
1112 struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> {
1115 class ObjectPool :
public std::map<UID,Object> {
1124 return std::map<UID,Object>::operator[](k);
1128 friend String _encode(
const ObjectPool& objects);
1131 String _encodeRootBlob();
1132 void _popRootBlob(
const char*& p,
const char* end);
1133 void _popObjectsBlob(
const char*& p,
const char* end);
1141 void syncPrimitive(
const Object& dst,
const Object& src);
1142 void syncPointer(
const Object& dst,
const Object& src);
1143 void syncMember(
const Member& dstMember,
const Member& srcMember);
1152 OPERATION_SERIALIZE,
1153 OPERATION_DESERIALIZE
1156 virtual void encode();
1158 ObjectPool m_allObjects;
1159 operation_t m_operation;
1165 time_t m_timeCreated;
1166 time_t m_timeModified;
1179 void PrintMessage();
1184 static String assemble(String format, va_list arg);
1189 #endif // LIBGIG_SERIALIZATION_H Abstract reflection of some native serialized C/C++ data.
static UID from(const T &obj)
Create an unique indentifier for a native C++ object/member/variable.
Destination container for serialization, and source container for deserialization.
std::vector< UID > UIDChain
Chain of UIDs.
static DataType dataTypeOf(const T &data)
Construct a DataType object for the given native C++ data.
bool IsUnion(const T &data)
Check whether data is a C++ union type.
void * ID
Abstract identifier for serialized C++ objects.
void serialize(const T *obj)
Initiate serialization.
Abstract reflection of a native C++ data type.
void setMinVersion(const T_classType &nativeObject, Version v)
Set a minimum version number for your C++ class.
void deserialize(T *obj)
Initiate deserialization.
uint32_t Version
Version number data type.
void serializeMember(const T_classType &nativeObject, const T_memberType &nativeMember, const char *memberName)
Serialize a native C/C++ member variable.
time_base_t
To which time zone a certain timing information relates to.
bool isValid() const
Check whether this is a valid unique identifier.
void setVersion(const T_classType &nativeObject, Version v)
Set current version number for your C++ class.
Unique identifier referring to one specific native C++ object, member, fundamental variable...
std::vector< Member > & members()
All members of the original native C/C++ struct or class instance.
void operator<<(const T &obj)
Initiate serialization of your C++ objects.
ID id
Abstract non-unique ID of the object or member in question.
std::vector< uint8_t > RawData
Raw data stream of serialized C++ objects.
The time stamp relates to the machine's local time zone. Request a time stamp in local time if you wa...
The time stamp relates to "Greenwhich Mean Time" zone, also known as "Coordinated Universal Time"...
Will be thrown whenever an error occurs during an serialization or deserialization process...
void operator>>(T &obj)
Initiate deserialization of your C++ objects.
bool IsEnum(const T &data)
Check whether data is a C/C++ enum type.
bool IsClass(const T &data)
Check whether data is a C/C++ struct or C++ class type.
size_t size() const
Returns native memory size of the respective C++ object or variable.
const UID NO_UID
Reflects an invalid UID and behaves similar to NULL as invalid value for pointer types.
Serialization / deserialization framework.
size_t size
Memory size of the object or member in question.
Abstract reflection of a native C++ class/struct's member variable.