Chrysalis - Pattern
Loading...
Searching...
No Matches
serialization.h
Go to the documentation of this file.
1#ifndef CHRYSALIS_SERIALIZATION_H
2#define CHRYSALIS_SERIALIZATION_H
3
4#include <boost/preprocessor.hpp>
5#include <boost/serialization/list.hpp>
6#include <boost/serialization/vector.hpp>
7#include <boost/serialization/optional.hpp>
8#include <boost/serialization/unique_ptr.hpp>
9#include <boost/serialization/unordered_map.hpp>
10
11// --- Helpers ---------------------------------------------------------------------------------------------------------
12
13#define LOAD_FIELD(r, data, field) archive >> field;
14#define ACCESS_FIELD(r, data, field) archive & obj.field;
15#define ACCESS_MEMBER(r, data, field) archive & this->field;
16#define ACCESS_FIELD_PTR(r, data, field) archive & obj->field;
17#define DECLARE_FIELD(r, data, field) decltype(obj->field) field;
18#define LOAD_BASE(r, data, base) archive & boost::serialization::base_object<base>(obj);
19#define FORWARD_MEMBER(r, data, field) std::forward<decltype((obj)->field)>(field)
20
21// --- Friends for constructors ----------------------------------------------------------------------------------------
22
23#define PROVIDE_CONSTRUCTION_ACCESS(Class) \
24template<class Archive> \
25friend void save_construct_data(Archive&, const Class*, const unsigned int); \
26template<class Archive> \
27friend void load_construct_data(Archive&, Class*, const unsigned int);
28
29#define PROVIDE_SERIALIZATION_ACCESS(Class) \
30template<class Archive> \
31friend void serialize(Archive& archive, Class& project, const unsigned int version); \
32template<class Archive> \
33friend void save_construct_data(Archive&, const Class*, const unsigned int); \
34template<class Archive> \
35friend void load_construct_data(Archive&, Class*, const unsigned int);
36
37#define PROVIDE_SERIALIZATION_ACCESS_T(Class) \
38template<class Archive, typename Type> \
39friend void serialize(Archive& archive, Class<Type>& project, const unsigned int version); \
40template<class Archive, typename Type> \
41friend void save_construct_data(Archive&, const Class<Type>*, const unsigned int); \
42template<class Archive, typename Type> \
43friend void load_construct_data(Archive&, Class<Type>*, const unsigned int);
44
45#define PROVIDE_DEFAULT_SERIALIZATION_ACCESS(Class) explicit Class() = default;
46
47// --- Intrusive serialization -----------------------------------------------------------------------------------------
48
49#define SERIALIZE_BASE_T(Class, ...) \
50template <class Archive, typename T> \
51void serialize_base(Archive& archive, Class<T>& obj) { \
52 __VA_OPT__( \
53 BOOST_PP_SEQ_FOR_EACH(LOAD_BASE, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
54 ) \
55}
56
57#define SERIALIZED \
58friend boost::serialization::access; \
59template<class Archive> \
60static void serialize(Archive&, const unsigned int) {}
61
62#define SERIALIZE(...) \
63friend boost::serialization::access; \
64template<class Archive> \
65void serialize(Archive& archive, const unsigned int) { \
66 __VA_OPT__( \
67 BOOST_PP_SEQ_FOR_EACH(ACCESS_MEMBER, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
68 ) \
69}
70
71#define SERIALIZE_DERIVED_FROM(Base, ...) \
72friend boost::serialization::access; \
73template<class Archive> \
74void serialize(Archive& archive, const unsigned int) { \
75 archive & boost::serialization::base_object<Base>(*this); \
76 __VA_OPT__( \
77 BOOST_PP_LIST_FOR_EACH(ACCESS_MEMBER, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
78 ) \
79}
80
81// --- Constructors ----------------------------------------------------------------------------------------------------
82
83#define SERIALIZATION_CONSTRUCTOR(Class, ...) \
84template<class Archive> \
85void save_construct_data(Archive& archive, const Class* obj, const unsigned int) { \
86 __VA_OPT__( \
87 BOOST_PP_LIST_FOR_EACH(ACCESS_FIELD_PTR, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
88 ) \
89} \
90template<class Archive> \
91void load_construct_data(Archive& archive, Class* obj, const unsigned int) { \
92 __VA_OPT__( \
93 BOOST_PP_LIST_FOR_EACH(DECLARE_FIELD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
94 BOOST_PP_LIST_FOR_EACH(LOAD_FIELD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
95 ) \
96 ::new(obj) Class( \
97 BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(FORWARD_MEMBER, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))) \
98 ); \
99}
100
101#define SERIALIZATION_CONSTRUCTOR_T(Class, ...) \
102template<class Archive, typename T> \
103void save_construct_data(Archive& archive, const Class<T>* obj, const unsigned int) { \
104 __VA_OPT__( \
105 BOOST_PP_LIST_FOR_EACH(ACCESS_FIELD_PTR, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
106 ) \
107} \
108template<class Archive, typename T> \
109void load_construct_data(Archive& archive, Class<T>* obj, const unsigned int) { \
110 __VA_OPT__( \
111 BOOST_PP_LIST_FOR_EACH(DECLARE_FIELD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
112 BOOST_PP_LIST_FOR_EACH(LOAD_FIELD, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
113 ) \
114 ::new(obj) Class<T>(__VA_ARGS__); \
115}
116
117// --- Specify members to serialize and use same members in constructor ------------------------------------------------
118
119#define SERIALIZE_CONSTRUCTION(Class, ...) \
120template<class Archive> \
121void serialize(Archive& archive, Class& obj, const unsigned int version) {} \
122SERIALIZATION_CONSTRUCTOR(Class, __VA_ARGS__)
123
124#define SERIALIZE_DERIVED_CONSTRUCTION(Class, Base, ...) \
125template<class Archive> \
126void serialize(Archive& archive, Class& obj, const unsigned int version) { \
127 archive & boost::serialization::base_object<Base>(obj); \
128} \
129SERIALIZATION_CONSTRUCTOR(Class, __VA_ARGS__)
130
131#define SERIALIZE_DERIVED_CONSTRUCTION_T(Class, Base, ...) \
132template<class Archive, typename T> \
133void serialize(Archive& archive, Class<T>& obj, const unsigned int version) { \
134 archive & boost::serialization::base_object<Base<T>>(obj); \
135} \
136SERIALIZATION_CONSTRUCTOR_T(Class, __VA_ARGS__)
137
138#endif //CHRYSALIS_SERIALIZATION_H