34 |
#include <string> |
#include <string> |
35 |
#include <vector> |
#include <vector> |
36 |
#include <map> |
#include <map> |
37 |
|
#include <time.h> |
38 |
|
#if __cplusplus < 201103L |
39 |
|
# include <tr1/type_traits> |
40 |
|
# define LIBGIG_IS_CLASS(type) std::tr1::__is_union_or_class<type>::value //NOTE: without compiler support we cannot distinguish union from class |
41 |
|
#else |
42 |
|
# define LIBGIG_IS_CLASS(type) __is_class(type) |
43 |
|
#endif |
44 |
|
|
45 |
/** @brief Serialization / deserialization framework. |
/** @brief Serialization / deserialization framework. |
46 |
* |
* |
87 |
*/ |
*/ |
88 |
namespace Serialization { |
namespace Serialization { |
89 |
|
|
90 |
|
// just symbol prototyping |
91 |
|
class DataType; |
92 |
|
class Object; |
93 |
|
class Member; |
94 |
class Archive; |
class Archive; |
95 |
|
class ObjectPool; |
96 |
class Exception; |
class Exception; |
97 |
|
|
98 |
typedef std::string String; |
typedef std::string String; |
109 |
OPERATION_DESERIALIZE |
OPERATION_DESERIALIZE |
110 |
}; |
}; |
111 |
|
|
112 |
|
enum time_base_t { |
113 |
|
LOCAL_TIME, |
114 |
|
UTC_TIME |
115 |
|
}; |
116 |
|
|
117 |
template<typename T> |
template<typename T> |
118 |
bool IsEnum(const T& data) { |
bool IsEnum(const T& data) { |
119 |
|
#if __cplusplus < 201103L |
120 |
|
return std::tr1::is_enum<T>::value; |
121 |
|
#else |
122 |
return __is_enum(T); |
return __is_enum(T); |
123 |
|
#endif |
124 |
} |
} |
125 |
|
|
126 |
template<typename T> |
template<typename T> |
127 |
bool IsUnion(const T& data) { |
bool IsUnion(const T& data) { |
128 |
|
#if __cplusplus < 201103L |
129 |
|
return false; // without compiler support we cannot distinguish union from class |
130 |
|
#else |
131 |
return __is_union(T); |
return __is_union(T); |
132 |
|
#endif |
133 |
} |
} |
134 |
|
|
135 |
template<typename T> |
template<typename T> |
136 |
bool IsClass(const T& data) { |
bool IsClass(const T& data) { |
137 |
|
#if __cplusplus < 201103L |
138 |
|
return std::tr1::__is_union_or_class<T>::value; // without compiler support we cannot distinguish union from class |
139 |
|
#else |
140 |
return __is_class(T); |
return __is_class(T); |
141 |
|
#endif |
142 |
} |
} |
143 |
|
|
144 |
/*template<typename T> |
/*template<typename T> |
180 |
template<typename T> |
template<typename T> |
181 |
struct Resolver { |
struct Resolver { |
182 |
static UID resolve(const T& obj) { |
static UID resolve(const T& obj) { |
183 |
return (UID) { (ID) &obj, sizeof(obj) }; |
const UID uid = { (ID) &obj, sizeof(obj) }; |
184 |
|
return uid; |
185 |
} |
} |
186 |
}; |
}; |
187 |
|
|
189 |
template<typename T> |
template<typename T> |
190 |
struct Resolver<T*> { |
struct Resolver<T*> { |
191 |
static UID resolve(const T* const & obj) { |
static UID resolve(const T* const & obj) { |
192 |
return (UID) { (ID) obj, sizeof(*obj) }; |
const UID uid = { (ID) obj, sizeof(*obj) }; |
193 |
|
return uid; |
194 |
} |
} |
195 |
}; |
}; |
196 |
}; |
}; |
203 |
|
|
204 |
typedef std::vector<UID> UIDChain; |
typedef std::vector<UID> UIDChain; |
205 |
|
|
206 |
|
// prototyping of private internal friend functions |
207 |
|
static String _encodePrimitiveValue(const Object& obj); |
208 |
|
static DataType _popDataTypeBlob(const char*& p, const char* end); |
209 |
|
static Member _popMemberBlob(const char*& p, const char* end); |
210 |
|
static Object _popObjectBlob(const char*& p, const char* end); |
211 |
|
static void _popPrimitiveValue(const char*& p, const char* end, Object& obj); |
212 |
|
static String _primitiveObjectValueToString(const Object& obj); |
213 |
|
// | |
214 |
|
template<typename T> |
215 |
|
static T _primitiveObjectValueToNumber(const Object& obj); |
216 |
|
|
217 |
/** @brief Abstract reflection of a native C++ data type. |
/** @brief Abstract reflection of a native C++ data type. |
218 |
* |
* |
219 |
* Provides detailed information about a C++ data type, whether it is a |
* Provides detailed information about a C++ data type, whether it is a |
242 |
bool operator>(const DataType& other) const; |
bool operator>(const DataType& other) const; |
243 |
String asLongDescr() const; |
String asLongDescr() const; |
244 |
String baseTypeName() const { return m_baseTypeName; } |
String baseTypeName() const { return m_baseTypeName; } |
245 |
String customTypeName() const { return m_customTypeName; } |
String customTypeName(bool demangle = false) const; |
246 |
|
|
247 |
template<typename T> |
template<typename T> |
248 |
static DataType dataTypeOf(const T& data) { |
static DataType dataTypeOf(const T& data) { |
317 |
bool m_isPointer; |
bool m_isPointer; |
318 |
|
|
319 |
friend DataType _popDataTypeBlob(const char*& p, const char* end); |
friend DataType _popDataTypeBlob(const char*& p, const char* end); |
320 |
|
friend class Archive; |
321 |
}; |
}; |
322 |
|
|
323 |
/** @brief Abstract reflection of a native C++ class/struct's member variable. |
/** @brief Abstract reflection of a native C++ class/struct's member variable. |
391 |
std::vector<Member>& members() { return m_members; } |
std::vector<Member>& members() { return m_members; } |
392 |
const std::vector<Member>& members() const { return m_members; } |
const std::vector<Member>& members() const { return m_members; } |
393 |
Member memberNamed(String name) const; |
Member memberNamed(String name) const; |
394 |
void remove(const Member& member); |
Member memberByUID(const UID& uid) const; |
395 |
std::vector<Member> membersOfType(const DataType& type) const; |
std::vector<Member> membersOfType(const DataType& type) const; |
396 |
int sequenceIndexOf(const Member& member) const; |
int sequenceIndexOf(const Member& member) const; |
397 |
bool isValid() const; |
bool isValid() const; |
402 |
bool operator<(const Object& other) const; |
bool operator<(const Object& other) const; |
403 |
bool operator>(const Object& other) const; |
bool operator>(const Object& other) const; |
404 |
|
|
405 |
|
protected: |
406 |
|
void remove(const Member& member); |
407 |
|
|
408 |
private: |
private: |
409 |
DataType m_type; |
DataType m_type; |
410 |
UIDChain m_uid; |
UIDChain m_uid; |
413 |
RawData m_data; |
RawData m_data; |
414 |
std::vector<Member> m_members; |
std::vector<Member> m_members; |
415 |
|
|
416 |
|
friend String _encodePrimitiveValue(const Object& obj); |
417 |
friend Object _popObjectBlob(const char*& p, const char* end); |
friend Object _popObjectBlob(const char*& p, const char* end); |
418 |
friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj); |
friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj); |
419 |
|
friend String _primitiveObjectValueToString(const Object& obj); |
420 |
|
|
421 |
|
template<typename T> |
422 |
|
friend T _primitiveObjectValueToNumber(const Object& obj); |
423 |
|
|
424 |
|
friend class Archive; |
425 |
}; |
}; |
426 |
|
|
427 |
/** @brief Destination container for serialization, and source container for deserialization. |
/** @brief Destination container for serialization, and source container for deserialization. |
435 |
* @code |
* @code |
436 |
* Archive a; |
* Archive a; |
437 |
* a.serialize(&myRootObject); |
* a.serialize(&myRootObject); |
438 |
* @encode |
* @endcode |
439 |
* Or if you prefer the look of operator based code: |
* Or if you prefer the look of operator based code: |
440 |
* @code |
* @code |
441 |
* Archive a; |
* Archive a; |
442 |
* a << myRootObject; |
* a << myRootObject; |
443 |
* @encode |
* @endcode |
444 |
* The Archive object will then serialize all members of the passed C++ |
* The Archive object will then serialize all members of the passed C++ |
445 |
* object, and will recursively serialize all other C++ objects which it |
* object, and will recursively serialize all other C++ objects which it |
446 |
* contains or points to. So the root object is the starting point for the |
* contains or points to. So the root object is the starting point for the |
455 |
* @code |
* @code |
456 |
* Archive a(rawDataStream); |
* Archive a(rawDataStream); |
457 |
* a.deserialize(&myRootObject); |
* a.deserialize(&myRootObject); |
458 |
* @encode |
* @endcode |
459 |
* Or with operator instead: |
* Or with operator instead: |
460 |
* @code |
* @code |
461 |
* Archive a(rawDataStream); |
* Archive a(rawDataStream); |
462 |
* a >> myRootObject; |
* a >> myRootObject; |
463 |
* @encode |
* @endcode |
464 |
* Now this framework automatically handles serialization and |
* Now this framework automatically handles serialization and |
465 |
* deserialization of fundamental data types automatically for you (like |
* deserialization of fundamental data types automatically for you (like |
466 |
* i.e. char, int, long int, float, double, etc.). However for your own |
* i.e. char, int, long int, float, double, etc.). However for your own |
575 |
deserialize(&obj); |
deserialize(&obj); |
576 |
} |
} |
577 |
|
|
578 |
const RawData& rawData() const { return m_rawData; } |
const RawData& rawData(); |
579 |
virtual String rawDataFormat() const; |
virtual String rawDataFormat() const; |
580 |
|
|
581 |
template<typename T_classType, typename T_memberType> |
template<typename T_classType, typename T_memberType> |
609 |
virtual void decode(const RawData& data); |
virtual void decode(const RawData& data); |
610 |
virtual void decode(const uint8_t* data, size_t size); |
virtual void decode(const uint8_t* data, size_t size); |
611 |
void clear(); |
void clear(); |
612 |
|
bool isModified() const; |
613 |
|
void removeMember(Object& parent, const Member& member); |
614 |
void remove(const Object& obj); |
void remove(const Object& obj); |
615 |
Object& rootObject(); |
Object& rootObject(); |
616 |
Object& objectByUID(const UID& uid); |
Object& objectByUID(const UID& uid); |
617 |
|
void setAutoValue(Object& object, String value); |
618 |
|
void setIntValue(Object& object, int64_t value); |
619 |
|
void setRealValue(Object& object, double value); |
620 |
|
void setBoolValue(Object& object, bool value); |
621 |
|
void setEnumValue(Object& object, uint64_t value); |
622 |
|
String valueAsString(const Object& object); |
623 |
|
int64_t valueAsInt(const Object& object); |
624 |
|
double valueAsReal(const Object& object); |
625 |
|
bool valueAsBool(const Object& object); |
626 |
|
String name() const; |
627 |
|
void setName(String name); |
628 |
|
String comment() const; |
629 |
|
void setComment(String comment); |
630 |
|
time_t timeStampCreated() const; |
631 |
|
time_t timeStampModified() const; |
632 |
|
tm dateTimeCreated(time_base_t base = LOCAL_TIME) const; |
633 |
|
tm dateTimeModified(time_base_t base = LOCAL_TIME) const; |
634 |
|
|
635 |
protected: |
protected: |
636 |
// UID resolver for non-pointer types |
// UID resolver for non-pointer types |
652 |
class UIDChainResolver<T*> { |
class UIDChainResolver<T*> { |
653 |
public: |
public: |
654 |
UIDChainResolver(const T*& data) { |
UIDChainResolver(const T*& data) { |
655 |
m_uid.push_back((UID) { &data, sizeof(data) }); |
const UID uids[2] = { |
656 |
m_uid.push_back((UID) { data, sizeof(*data) }); |
{ &data, sizeof(data) }, |
657 |
|
{ data, sizeof(*data) } |
658 |
|
}; |
659 |
|
m_uid.push_back(uids[0]); |
660 |
|
m_uid.push_back(uids[1]); |
661 |
} |
} |
662 |
|
|
663 |
operator UIDChain() const { return m_uid; } |
operator UIDChain() const { return m_uid; } |
697 |
|
|
698 |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
699 |
template<typename T> |
template<typename T> |
700 |
struct SerializationRecursion : SerializationRecursionImpl<T, __is_class(T)> { |
struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> { |
701 |
}; |
}; |
702 |
|
|
703 |
class ObjectPool : public std::map<UID,Object> { |
class ObjectPool : public std::map<UID,Object> { |
741 |
operation_t m_operation; |
operation_t m_operation; |
742 |
UID m_root; |
UID m_root; |
743 |
RawData m_rawData; |
RawData m_rawData; |
744 |
|
bool m_isModified; |
745 |
|
String m_name; |
746 |
|
String m_comment; |
747 |
|
time_t m_timeCreated; |
748 |
|
time_t m_timeModified; |
749 |
}; |
}; |
750 |
|
|
751 |
/** |
/** |