1 |
/*************************************************************************** |
/*************************************************************************** |
2 |
* * |
* * |
3 |
* Copyright (C) 2017 Christian Schoenebeck * |
* Copyright (C) 2017-2020 Christian Schoenebeck * |
4 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
5 |
* * |
* * |
6 |
* This library is part of libgig. * |
* This library is part of libgig. * |
7 |
* * |
* * |
35 |
#include <vector> |
#include <vector> |
36 |
#include <map> |
#include <map> |
37 |
#include <time.h> |
#include <time.h> |
38 |
|
#include <stdarg.h> |
39 |
|
#include <assert.h> |
40 |
|
|
41 |
#ifndef __has_extension |
#ifndef __has_extension |
42 |
# define __has_extension(x) 0 |
# define __has_extension(x) 0 |
324 |
*/ |
*/ |
325 |
typedef std::vector<UID> UIDChain; |
typedef std::vector<UID> UIDChain; |
326 |
|
|
327 |
|
#if LIBGIG_SERIALIZATION_INTERNAL |
328 |
// prototyping of private internal friend functions |
// prototyping of private internal friend functions |
329 |
static String _encodePrimitiveValue(const Object& obj); |
static String _encodePrimitiveValue(const Object& obj); |
330 |
static DataType _popDataTypeBlob(const char*& p, const char* end); |
static DataType _popDataTypeBlob(const char*& p, const char* end); |
335 |
// | |
// | |
336 |
template<typename T> |
template<typename T> |
337 |
static T _primitiveObjectValueToNumber(const Object& obj); |
static T _primitiveObjectValueToNumber(const Object& obj); |
338 |
|
#endif // LIBGIG_SERIALIZATION_INTERNAL |
339 |
|
|
340 |
/** @brief Abstract reflection of a native C++ data type. |
/** @brief Abstract reflection of a native C++ data type. |
341 |
* |
* |
361 |
bool isPointer() const; |
bool isPointer() const; |
362 |
bool isClass() const; |
bool isClass() const; |
363 |
bool isPrimitive() const; |
bool isPrimitive() const; |
364 |
|
bool isString() const; |
365 |
bool isInteger() const; |
bool isInteger() const; |
366 |
bool isReal() const; |
bool isReal() const; |
367 |
bool isBool() const; |
bool isBool() const; |
412 |
if (type == typeid(uint32_t)) return DataType(T_isPointer, sz, "uint32"); |
if (type == typeid(uint32_t)) return DataType(T_isPointer, sz, "uint32"); |
413 |
if (type == typeid(int64_t)) return DataType(T_isPointer, sz, "int64"); |
if (type == typeid(int64_t)) return DataType(T_isPointer, sz, "int64"); |
414 |
if (type == typeid(uint64_t)) return DataType(T_isPointer, sz, "uint64"); |
if (type == typeid(uint64_t)) return DataType(T_isPointer, sz, "uint64"); |
415 |
|
if (type == typeid(size_t)) { |
416 |
|
if (sz == 1) return DataType(T_isPointer, sz, "uint8"); |
417 |
|
if (sz == 2) return DataType(T_isPointer, sz, "uint16"); |
418 |
|
if (sz == 4) return DataType(T_isPointer, sz, "uint32"); |
419 |
|
if (sz == 8) return DataType(T_isPointer, sz, "uint64"); |
420 |
|
else assert(false /* unknown size_t size */); |
421 |
|
} |
422 |
|
if (type == typeid(ssize_t)) { |
423 |
|
if (sz == 1) return DataType(T_isPointer, sz, "int8"); |
424 |
|
if (sz == 2) return DataType(T_isPointer, sz, "int16"); |
425 |
|
if (sz == 4) return DataType(T_isPointer, sz, "int32"); |
426 |
|
if (sz == 8) return DataType(T_isPointer, sz, "int64"); |
427 |
|
else assert(false /* unknown ssize_t size */); |
428 |
|
} |
429 |
if (type == typeid(bool)) return DataType(T_isPointer, sz, "bool"); |
if (type == typeid(bool)) return DataType(T_isPointer, sz, "bool"); |
430 |
if (type == typeid(float)) return DataType(T_isPointer, sz, "real32"); |
if (type == typeid(float)) return DataType(T_isPointer, sz, "real32"); |
431 |
if (type == typeid(double)) return DataType(T_isPointer, sz, "real64"); |
if (type == typeid(double)) return DataType(T_isPointer, sz, "real64"); |
432 |
|
if (type == typeid(String)) return DataType(T_isPointer, sz, "String"); |
433 |
|
|
434 |
if (IsEnum(data)) return DataType(T_isPointer, sz, "enum", rawCppTypeNameOf(data)); |
if (IsEnum(data)) return DataType(T_isPointer, sz, "enum", rawCppTypeNameOf(data)); |
435 |
if (IsUnion(data)) return DataType(T_isPointer, sz, "union", rawCppTypeNameOf(data)); |
if (IsUnion(data)) return DataType(T_isPointer, sz, "union", rawCppTypeNameOf(data)); |
458 |
template<typename T> |
template<typename T> |
459 |
static String rawCppTypeNameOf(const T& data) { |
static String rawCppTypeNameOf(const T& data) { |
460 |
#if defined _MSC_VER // Microsoft compiler ... |
#if defined _MSC_VER // Microsoft compiler ... |
461 |
# warning type_info::raw_name() demangling has not been tested yet with Microsoft compiler! Feedback appreciated! |
String name = typeid(data).raw_name(); |
|
String name = typeid(data).raw_name(); //NOTE: I haven't checked yet what MSC actually outputs here exactly |
|
462 |
#else // i.e. especially GCC and clang ... |
#else // i.e. especially GCC and clang ... |
463 |
String name = typeid(data).name(); |
String name = typeid(data).name(); |
464 |
#endif |
#endif |
473 |
int m_size; |
int m_size; |
474 |
bool m_isPointer; |
bool m_isPointer; |
475 |
|
|
476 |
|
#if LIBGIG_SERIALIZATION_INTERNAL |
477 |
friend DataType _popDataTypeBlob(const char*& p, const char* end); |
friend DataType _popDataTypeBlob(const char*& p, const char* end); |
478 |
|
#endif |
479 |
friend class Archive; |
friend class Archive; |
480 |
}; |
}; |
481 |
|
|
525 |
String m_name; |
String m_name; |
526 |
DataType m_type; |
DataType m_type; |
527 |
|
|
528 |
|
#if LIBGIG_SERIALIZATION_INTERNAL |
529 |
friend Member _popMemberBlob(const char*& p, const char* end); |
friend Member _popMemberBlob(const char*& p, const char* end); |
530 |
|
#endif |
531 |
}; |
}; |
532 |
|
|
533 |
/** @brief Abstract reflection of some native serialized C/C++ data. |
/** @brief Abstract reflection of some native serialized C/C++ data. |
593 |
RawData m_data; |
RawData m_data; |
594 |
std::vector<Member> m_members; |
std::vector<Member> m_members; |
595 |
|
|
596 |
|
#if LIBGIG_SERIALIZATION_INTERNAL |
597 |
friend String _encodePrimitiveValue(const Object& obj); |
friend String _encodePrimitiveValue(const Object& obj); |
598 |
friend Object _popObjectBlob(const char*& p, const char* end); |
friend Object _popObjectBlob(const char*& p, const char* end); |
599 |
friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj); |
friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj); |
600 |
friend String _primitiveObjectValueToString(const Object& obj); |
friend String _primitiveObjectValueToString(const Object& obj); |
601 |
|
// | |
602 |
template<typename T> |
template<typename T> |
603 |
friend T _primitiveObjectValueToNumber(const Object& obj); |
friend T _primitiveObjectValueToNumber(const Object& obj); |
604 |
|
#endif // LIBGIG_SERIALIZATION_INTERNAL |
605 |
|
|
606 |
friend class Archive; |
friend class Archive; |
607 |
}; |
}; |
725 |
*/ |
*/ |
726 |
class Archive { |
class Archive { |
727 |
public: |
public: |
728 |
|
/** @brief Current activity of @c Archive object. |
729 |
|
*/ |
730 |
|
enum operation_t { |
731 |
|
OPERATION_NONE, ///< Archive is currently neither serializing, nor deserializing. |
732 |
|
OPERATION_SERIALIZE, ///< Archive is currently serializing. |
733 |
|
OPERATION_DESERIALIZE ///< Archive is currently deserializing. |
734 |
|
}; |
735 |
|
|
736 |
Archive(); |
Archive(); |
737 |
Archive(const RawData& data); |
Archive(const RawData& data); |
738 |
Archive(const uint8_t* data, size_t size); |
Archive(const uint8_t* data, size_t size); |
801 |
template<typename T> |
template<typename T> |
802 |
void deserialize(T* obj) { |
void deserialize(T* obj) { |
803 |
Archive a; |
Archive a; |
804 |
m_operation = OPERATION_DESERIALIZE; |
a.m_operation = m_operation = OPERATION_DESERIALIZE; |
805 |
obj->serialize(&a); |
obj->serialize(&a); |
806 |
a.m_root = UID::from(obj); |
a.m_root = UID::from(obj); |
807 |
Syncer s(a, *this); |
Syncer s(a, *this); |
808 |
m_operation = OPERATION_NONE; |
a.m_operation = m_operation = OPERATION_NONE; |
809 |
} |
} |
810 |
|
|
811 |
/** @brief Initiate serialization of your C++ objects. |
/** @brief Initiate serialization of your C++ objects. |
1061 |
void setRealValue(Object& object, double value); |
void setRealValue(Object& object, double value); |
1062 |
void setBoolValue(Object& object, bool value); |
void setBoolValue(Object& object, bool value); |
1063 |
void setEnumValue(Object& object, uint64_t value); |
void setEnumValue(Object& object, uint64_t value); |
1064 |
|
void setStringValue(Object& object, String value); |
1065 |
String valueAsString(const Object& object); |
String valueAsString(const Object& object); |
1066 |
int64_t valueAsInt(const Object& object); |
int64_t valueAsInt(const Object& object); |
1067 |
double valueAsReal(const Object& object); |
double valueAsReal(const Object& object); |
1076 |
time_t timeStampModified() const; |
time_t timeStampModified() const; |
1077 |
tm dateTimeCreated(time_base_t base = LOCAL_TIME) const; |
tm dateTimeCreated(time_base_t base = LOCAL_TIME) const; |
1078 |
tm dateTimeModified(time_base_t base = LOCAL_TIME) const; |
tm dateTimeModified(time_base_t base = LOCAL_TIME) const; |
1079 |
|
operation_t operation() const; |
1080 |
|
|
1081 |
protected: |
protected: |
1082 |
// UID resolver for non-pointer types |
// UID resolver for non-pointer types |
1141 |
static void serializeObject(Archive* archive, const T*& obj) {} |
static void serializeObject(Archive* archive, const T*& obj) {} |
1142 |
}; |
}; |
1143 |
|
|
1144 |
|
// NOOP SerializationRecursion for String objects. |
1145 |
|
template<bool T_isRecursive> |
1146 |
|
struct SerializationRecursionImpl<String,T_isRecursive> { |
1147 |
|
static void serializeObject(Archive* archive, const String& obj) {} |
1148 |
|
}; |
1149 |
|
|
1150 |
|
// NOOP SerializationRecursion for String pointers (of 1st degree). |
1151 |
|
template<bool T_isRecursive> |
1152 |
|
struct SerializationRecursionImpl<String*,T_isRecursive> { |
1153 |
|
static void serializeObject(Archive* archive, const String*& obj) {} |
1154 |
|
}; |
1155 |
|
|
1156 |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
1157 |
template<typename T> |
template<typename T> |
1158 |
struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> { |
struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> { |
1185 |
protected: |
protected: |
1186 |
void syncObject(const Object& dst, const Object& src); |
void syncObject(const Object& dst, const Object& src); |
1187 |
void syncPrimitive(const Object& dst, const Object& src); |
void syncPrimitive(const Object& dst, const Object& src); |
1188 |
|
void syncString(const Object& dst, const Object& src); |
1189 |
void syncPointer(const Object& dst, const Object& src); |
void syncPointer(const Object& dst, const Object& src); |
1190 |
void syncMember(const Member& dstMember, const Member& srcMember); |
void syncMember(const Member& dstMember, const Member& srcMember); |
1191 |
static Member dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember); |
static Member dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember); |
1194 |
Archive& m_src; |
Archive& m_src; |
1195 |
}; |
}; |
1196 |
|
|
|
enum operation_t { |
|
|
OPERATION_NONE, |
|
|
OPERATION_SERIALIZE, |
|
|
OPERATION_DESERIALIZE |
|
|
}; |
|
|
|
|
1197 |
virtual void encode(); |
virtual void encode(); |
1198 |
|
|
1199 |
ObjectPool m_allObjects; |
ObjectPool m_allObjects; |
1215 |
public: |
public: |
1216 |
String Message; |
String Message; |
1217 |
|
|
1218 |
Exception(String Message) { Exception::Message = Message; } |
Exception(String format, ...); |
1219 |
|
Exception(String format, va_list arg); |
1220 |
void PrintMessage(); |
void PrintMessage(); |
1221 |
virtual ~Exception() {} |
virtual ~Exception() {} |
1222 |
|
|
1223 |
|
protected: |
1224 |
|
Exception(); |
1225 |
|
static String assemble(String format, va_list arg); |
1226 |
}; |
}; |
1227 |
|
|
1228 |
} // namespace Serialization |
} // namespace Serialization |