1 #ifndef SERIALIZE_CORE_HH
2 #define SERIALIZE_CORE_HH
24 template<>
struct is_primitive<unsigned short> : std::true_type {};
31 template<>
struct is_primitive<unsigned long long> : std::true_type {};
40 template <
typename Archive,
typename T>
45 t.serialize(ar, version);
48 template <
typename Archive,
typename T1,
typename T2>
49 void serialize(Archive& ar, std::pair<T1, T2>& p,
unsigned )
51 ar.serialize(
"first", p.first);
52 ar.serialize(
"second", p.second);
56 static const unsigned value = 0;
110 if (p->e == t)
return p->str;
118 if (p->str == str)
return p->e;
128 #define SERIALIZE_ENUM(TYPE,INFO) \
129 template<> struct serialize_as_enum< TYPE > : serialize_as_enum_impl< TYPE > { \
130 serialize_as_enum() : serialize_as_enum_impl< TYPE >( INFO ) {} \
165 "can't serialize ptr to primitive type");
172 template<
typename Archive>
180 static inline T*
getPointer(
const std::unique_ptr<T>& t) {
return t.get(); }
181 template<
typename Archive>
182 static inline void setPointer(std::unique_ptr<T>& t, T* p, Archive& ) {
189 static T*
getPointer(
const std::shared_ptr<T>& t) {
return t.get(); }
190 template<
typename Archive>
191 static void setPointer(std::shared_ptr<T>& t, T* p, Archive& ar) {
192 ar.resetSharedPtr(t, p);
246 static const T*
begin(
const T (&array)[N]) {
return &array[0]; }
247 static const T*
end (
const T (&array)[N]) {
return &array[N]; }
249 static const bool loadInPlace =
true;
252 static T*
output(T (&array)[N]) {
return &array[0]; }
298 template<
typename Archive>
void operator()(Archive& ar,
const T& t,
307 template<
typename Archive>
void operator()(Archive& ar,
const T& t,
310 if (ar.translateEnumToString()) {
312 std::string str = sae.toString(t);
322 Archive& ar,
const T& t,
bool saveId,
323 const char* type =
nullptr,
bool saveConstrArgs =
false)
338 unsigned id = ar.generateId(&t);
339 ar.attribute(
"id",
id);
343 ar.attribute(
"type", type);
347 if ((version != 0) && ar.needVersion()) {
348 if (!ar.canHaveOptionalAttributes() ||
350 ar.attribute(
"version", version);
354 if (saveConstrArgs) {
357 constrArgs.
save(ar, t);
360 typedef typename std::remove_const<T>::type TNC;
361 auto& t2 =
const_cast<TNC&
>(t);
368 template<
typename Archive>
void operator()(Archive& ar,
const TP& tp2,
372 "must be serialized as pointer");
377 ar.attribute(
"id_ref",
id);
380 if (
unsigned id = ar.getId(tp)) {
381 ar.attribute(
"id_ref",
id);
383 if (std::is_polymorphic<T>::value) {
389 saver(ar, *tp,
true,
nullptr,
true);
396 template<
typename Archive>
void operator()(Archive& ar,
const TP& tp2)
399 "must be serialized as pointer");
408 ar.attribute(
"id_ref",
id);
413 template<
typename Archive>
void operator()(Archive& ar,
const TC& tc,
417 static_assert(sac::value,
"must be serialized as collection");
418 auto begin = sac::begin(tc);
419 auto end = sac::end (tc);
420 if ((
sac::size < 0) && (!ar.canCountChildren())) {
426 ar.serialize(
"size", n);
428 for (; begin != end; ++begin) {
430 ar.serializeWithID(
"item", *begin);
432 ar.serialize(
"item", *begin);
441 :
if_<is_primitive<T>,
443 if_<serialize_as_enum<T>,
445 if_<serialize_as_pointer<T>,
447 if_<serialize_as_collection<T>,
449 ClassSaver<T>>>>> {};
471 template<
typename Archive,
typename TUPLE>
475 "can't have constructor arguments");
481 template<
typename Archive,
typename TUPLE>
485 "can't have constructor arguments");
486 if (ar.translateEnumToString()) {
490 t = sae.fromString(str);
500 unsigned latestVersion);
502 unsigned latestVersion);
503 template<
typename T,
typename Archive>
unsigned loadVersion(Archive& ar)
506 if ((latestVersion != 0) && ar.needVersion()) {
509 return latestVersion;
514 template<
typename Archive,
typename TUPLE>
519 "can't have constructor arguments");
526 ar.attribute(
"id",
id);
528 ar.addPointer(
id, &t);
534 version = loadVersion<T>(ar);
537 typedef typename std::remove_const<T>::type TNC;
538 auto& t2 =
const_cast<TNC&
>(t);
544 template<
typename Archive,
typename GlobalTuple>
545 T*
operator()(Archive& ar,
unsigned id, GlobalTuple globalArgs)
547 int version = loadVersion<T>(ar);
550 typedef typename std::remove_const<T>::type TNC;
552 ConstrArgs constrArgs;
553 auto localArgs = constrArgs.
load(ar, version);
556 auto args = std::tuple_cat(globalArgs, localArgs);
560 auto tp = creator(args);
562 loader(ar, *tp, std::make_tuple(),
id, version);
568 template<
typename Archive,
typename TUPLE>
571 typedef typename PolymorphicConstructorArgs<T>::type ArgsType;
573 "constructor arguments types must match");
574 return static_cast<T*
>(
582 :
if_<std::is_polymorphic<T>, PolymorphicPointerLoader<T>,
583 NonPolymorphicPointerLoader<T>> {};
587 template<
typename Archive,
typename GlobalTuple>
588 void operator()(Archive& ar, TP& tp2, GlobalTuple globalArgs,
int )
591 "must be serialized as a pointer");
595 if (ar.canHaveOptionalAttributes() &&
596 ar.findAttribute(
"id_ref",
id)) {
599 ar.attribute(
"id",
id);
607 if (
void* p = ar.getPointer(
id)) {
608 tp =
static_cast<T*
>(p);
611 tp = loader(ar,
id, globalArgs);
620 template<
typename Archive>
624 "must be serialized as a pointer");
626 ar.attribute(
"id_ref",
id);
633 void* p = ar.getPointer(
id);
637 tp =
static_cast<T*
>(p);
643 template<
typename sac,
bool IN_PLACE = sac::loadInPlace>
struct CollectionLoaderHelper;
644 template<
typename sac>
struct CollectionLoaderHelper<sac, true>
647 template<
typename Archive,
typename TUPLE,
typename OUT_ITER>
648 void operator()(Archive& ar, TUPLE args, OUT_ITER it,
int id)
650 ar.doSerialize(
"item", *it, args,
id);
653 template<
typename sac>
struct CollectionLoaderHelper<sac, false>
659 template<
typename Archive,
typename TUPLE,
typename OUT_ITER>
660 void operator()(Archive& ar, TUPLE args, OUT_ITER it,
int id)
662 typename sac::value_type elem;
663 ar.doSerialize(
"item", elem, args,
id);
664 *it = std::move(elem);
669 template<
typename Archive,
typename TUPLE>
672 assert((
id == 0) || (
id == -1));
674 static_assert(sac::value,
"must be serialized as a collection");
678 if (ar.canCountChildren()) {
679 n = ar.countChildren();
681 ar.serialize(
"size", n);
685 auto it = sac::output(tc);
686 CollectionLoaderHelper<sac> loadOneElement;
687 for (
int i = 0; i < n; ++i, ++it) {
688 loadOneElement(ar, args, it,
id);
693 :
if_<is_primitive<T>,
695 if_<serialize_as_enum<T>,
697 if_<serialize_as_pointer<T>,
699 if_<serialize_as_collection<T>,
701 ClassLoader<T>>>>> {};