34 |
#include <string> |
#include <string> |
35 |
#include <vector> |
#include <vector> |
36 |
#include <map> |
#include <map> |
37 |
|
#include <set> |
38 |
#include <time.h> |
#include <time.h> |
39 |
#include <stdarg.h> |
#include <stdarg.h> |
40 |
#include <assert.h> |
#include <assert.h> |
144 |
template<class T> |
template<class T> |
145 |
using Array = std::vector<T>; |
using Array = std::vector<T>; |
146 |
|
|
147 |
|
/** @brief Set<> template. |
148 |
|
* |
149 |
|
* This type is used for built-in automatic serialization / deserialization |
150 |
|
* of C++ unique data set containers (a.k.a. @c std::set from the STL). This |
151 |
|
* framework supports serializing this common data type out of the box, with |
152 |
|
* the following constraint: the precise key type used with sets must be |
153 |
|
* either a primitive data type (e.g. @c int, @c double, @c bool, etc.) or a |
154 |
|
* @c String object. |
155 |
|
*/ |
156 |
|
template<class T> |
157 |
|
using Set = std::set<T>; |
158 |
|
|
159 |
/** @brief Raw data stream of serialized C++ objects. |
/** @brief Raw data stream of serialized C++ objects. |
160 |
* |
* |
161 |
* This data type is used for the data stream as a result of serializing |
* This data type is used for the data stream as a result of serializing |
270 |
return true; |
return true; |
271 |
}*/ |
}*/ |
272 |
|
|
273 |
|
template<typename T> inline |
274 |
|
String toString(const T& value) { |
275 |
|
return std::to_string(value); |
276 |
|
} |
277 |
|
|
278 |
|
template<> inline |
279 |
|
String toString(const String& value) { |
280 |
|
return value; |
281 |
|
} |
282 |
|
|
283 |
/** @brief Unique identifier referring to one specific native C++ object, member, fundamental variable, or any other native C++ data. |
/** @brief Unique identifier referring to one specific native C++ object, member, fundamental variable, or any other native C++ data. |
284 |
* |
* |
285 |
* Reflects a unique identifier for one specific serialized C++ data, i.e. |
* Reflects a unique identifier for one specific serialized C++ data, i.e. |
423 |
bool isBool() const; |
bool isBool() const; |
424 |
bool isEnum() const; |
bool isEnum() const; |
425 |
bool isArray() const; |
bool isArray() const; |
426 |
|
bool isSet() const; |
427 |
bool isSigned() const; |
bool isSigned() const; |
428 |
operator bool() const { return isValid(); } ///< Same as calling isValid(). |
operator bool() const { return isValid(); } ///< Same as calling isValid(). |
429 |
//bool operator()() const { return isValid(); } |
//bool operator()() const { return isValid(); } |
533 |
} |
} |
534 |
}; |
}; |
535 |
|
|
536 |
|
// DataType resolver for non-pointer Set<> container object types. |
537 |
|
template<typename T> |
538 |
|
struct Resolver<Set<T>> { |
539 |
|
static DataType resolve(const Set<T>& data) { |
540 |
|
const int sz = sizeof(data); |
541 |
|
T unused; |
542 |
|
return DataType(false, sz, "Set", rawCppTypeNameOf(unused)); |
543 |
|
} |
544 |
|
}; |
545 |
|
|
546 |
|
// DataType resolver for Set<> pointer types (of 1st degree). |
547 |
|
template<typename T> |
548 |
|
struct Resolver<Set<T>*> { |
549 |
|
static DataType resolve(const Set<T>*& data) { |
550 |
|
const int sz = sizeof(*data); |
551 |
|
T unused; |
552 |
|
return DataType(true, sz, "Set", rawCppTypeNameOf(unused)); |
553 |
|
} |
554 |
|
}; |
555 |
|
|
556 |
template<typename T> |
template<typename T> |
557 |
static String rawCppTypeNameOf(const T& data) { |
static String rawCppTypeNameOf(const T& data) { |
558 |
#if defined _MSC_VER // Microsoft compiler ... |
#if defined _MSC_VER // Microsoft compiler ... |
677 |
bool operator!=(const Object& other) const; |
bool operator!=(const Object& other) const; |
678 |
bool operator<(const Object& other) const; |
bool operator<(const Object& other) const; |
679 |
bool operator>(const Object& other) const; |
bool operator>(const Object& other) const; |
680 |
|
void setNativeValueFromString(const String& s); |
681 |
|
|
682 |
protected: |
protected: |
683 |
void remove(const Member& member); |
void remove(const Member& member); |
1339 |
if (archive->operation() == OPERATION_SERIALIZE) { |
if (archive->operation() == OPERATION_SERIALIZE) { |
1340 |
for (size_t i = 0; i < obj.size(); ++i) { |
for (size_t i = 0; i < obj.size(); ++i) { |
1341 |
archive->serializeHeapMember( |
archive->serializeHeapMember( |
1342 |
obj, obj[i], ("[" + std::to_string(i) + "]").c_str() |
obj, obj[i], ("[" + toString(i) + "]").c_str() |
1343 |
); |
); |
1344 |
} |
} |
1345 |
} else { |
} else { |
1351 |
const_cast<Array<T>&>(obj).resize(n); |
const_cast<Array<T>&>(obj).resize(n); |
1352 |
for (size_t i = 0; i < obj.size(); ++i) { |
for (size_t i = 0; i < obj.size(); ++i) { |
1353 |
archive->serializeHeapMember( |
archive->serializeHeapMember( |
1354 |
obj, obj[i], ("[" + std::to_string(i) + "]").c_str() |
obj, obj[i], ("[" + toString(i) + "]").c_str() |
1355 |
); |
); |
1356 |
} |
} |
1357 |
// updating dstObj required as serializeHeapMember() |
// updating dstObj required as serializeHeapMember() |
1358 |
// replaced the original object by a new one |
// replaced the original object by a new one |
1359 |
dstObj = archive->objectByUID(dstObj.uid()); |
dstObj = archive->objectByUID(dstObj.uid()); |
1360 |
for (size_t i = 0; i < obj.size(); ++i) { |
for (size_t i = 0; i < obj.size(); ++i) { |
1361 |
String name = "[" + std::to_string(i) + "]"; |
String name = "[" + toString(i) + "]"; |
1362 |
Member srcMember = srcObj.memberNamed(name); |
Member srcMember = srcObj.memberNamed(name); |
1363 |
Member dstMember = dstObj.memberNamed(name); |
Member dstMember = dstObj.memberNamed(name); |
1364 |
((Syncer*)syncer)->syncMember(dstMember, srcMember); |
((Syncer*)syncer)->syncMember(dstMember, srcMember); |
1379 |
} |
} |
1380 |
}; |
}; |
1381 |
|
|
1382 |
|
// SerializationRecursion for Set<> objects. |
1383 |
|
template<typename T, bool T_isRecursive> |
1384 |
|
struct SerializationRecursionImpl<Set<T>,T_isRecursive> { |
1385 |
|
static void serializeObject(Archive* archive, const Set<T>& obj) { |
1386 |
|
const UIDChain uids = UIDChainResolver<Set<T>>(obj); |
1387 |
|
const Object& object = archive->objectByUID(uids[0]); |
1388 |
|
if (archive->operation() == OPERATION_SERIALIZE) { |
1389 |
|
for (const T& key : obj) { |
1390 |
|
archive->serializeHeapMember( |
1391 |
|
obj, key, ("[" + toString(key) + "]").c_str() |
1392 |
|
); |
1393 |
|
} |
1394 |
|
} else { |
1395 |
|
const_cast<Object&>(object).m_sync = |
1396 |
|
[&obj,archive](Object& dstObj, const Object& srcObj, |
1397 |
|
void* syncer) |
1398 |
|
{ |
1399 |
|
const size_t n = srcObj.members().size(); |
1400 |
|
const_cast<Set<T>&>(obj).clear(); |
1401 |
|
for (size_t i = 0; i < n; ++i) { |
1402 |
|
const Member& member = srcObj.members()[i]; |
1403 |
|
String name = member.name(); |
1404 |
|
if (name.length() < 2 || name[0] != '[' || |
1405 |
|
*name.rbegin() != ']') continue; |
1406 |
|
name = name.substr(1, name.length() - 2); |
1407 |
|
T key; |
1408 |
|
const UIDChain uids = UIDChainResolver<T>(key); |
1409 |
|
const DataType type = DataType::dataTypeOf(key); |
1410 |
|
Object tmpObj(uids, type); |
1411 |
|
tmpObj.setNativeValueFromString(name); |
1412 |
|
const_cast<Set<T>&>(obj).insert(key); |
1413 |
|
} |
1414 |
|
for (const T& key : obj) { |
1415 |
|
archive->serializeHeapMember( |
1416 |
|
obj, key, ("[" + toString(key) + "]").c_str() |
1417 |
|
); |
1418 |
|
} |
1419 |
|
// updating dstObj required as serializeHeapMember() |
1420 |
|
// replaced the original object by a new one |
1421 |
|
dstObj = archive->objectByUID(dstObj.uid()); |
1422 |
|
}; |
1423 |
|
} |
1424 |
|
} |
1425 |
|
}; |
1426 |
|
|
1427 |
|
// SerializationRecursion for Set<> pointers (of 1st degree). |
1428 |
|
template<typename T, bool T_isRecursive> |
1429 |
|
struct SerializationRecursionImpl<Set<T>*,T_isRecursive> { |
1430 |
|
static void serializeObject(Archive* archive, const Set<T>*& obj) { |
1431 |
|
if (!obj) return; |
1432 |
|
SerializationRecursionImpl<Set<T>,T_isRecursive>::serializeObject( |
1433 |
|
archive, *obj |
1434 |
|
); |
1435 |
|
} |
1436 |
|
}; |
1437 |
|
|
1438 |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
// Automatically handles recursion for class/struct types, while ignoring all primitive types. |
1439 |
template<typename T> |
template<typename T> |
1440 |
struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> { |
struct SerializationRecursion : SerializationRecursionImpl<T, LIBGIG_IS_CLASS(T)> { |
1507 |
void syncPrimitive(const Object& dst, const Object& src); |
void syncPrimitive(const Object& dst, const Object& src); |
1508 |
void syncString(const Object& dst, const Object& src); |
void syncString(const Object& dst, const Object& src); |
1509 |
void syncArray(const Object& dst, const Object& src); |
void syncArray(const Object& dst, const Object& src); |
1510 |
|
void syncSet(const Object& dst, const Object& src); |
1511 |
void syncPointer(const Object& dst, const Object& src); |
void syncPointer(const Object& dst, const Object& src); |
1512 |
void syncMember(const Member& dstMember, const Member& srcMember); |
void syncMember(const Member& dstMember, const Member& srcMember); |
1513 |
protected: |
protected: |