1 #ifndef SERIALIZE_CORE_HH
2 #define SERIALIZE_CORE_HH
10 #include <initializer_list>
13 #include <type_traits>
19 template<
typename T>
struct Serializer : std::false_type {
34 template<>
struct is_primitive<unsigned short> : std::true_type {};
41 template<>
struct is_primitive<unsigned long long> : std::true_type {};
49 template<
typename Archive,
typename T>
54 t.serialize(ar, version);
57 template<
typename Archive,
typename T1,
typename T2>
58 void serialize(Archive& ar, std::pair<T1, T2>& p,
unsigned )
60 ar.serialize(
"first", p.first,
65 static constexpr
unsigned value = 0;
112 void enumError(
const std::string_view str);
117 for (
auto& [str,
t] : list) {
118 if (
t == t_)
return str;
121 return "internal-error-unknown-enum-value";
127 for (
auto& [str,
t] : list) {
128 if (str == str_)
return t;
134 #define SERIALIZE_ENUM(TYPE,INFO) \
135 template<> struct serialize_as_enum< TYPE > : std::true_type { \
136 serialize_as_enum() : info(INFO) {} \
137 std::initializer_list<enum_string< TYPE >> info; \
140 template<
typename Archive,
typename T,
typename SaveAction>
143 if constexpr (Archive::TRANSLATE_ENUM_TO_STRING) {
150 template<
typename Archive,
typename T,
typename LoadAction>
153 if constexpr (Archive::TRANSLATE_ENUM_TO_STRING) {
166 template<
size_t I,
typename Variant>
169 if constexpr (I == std::variant_size_v<Variant>) {
171 }
else if (index == I) {
172 return std::variant_alternative_t<I, Variant>{};
178 template<
typename Variant>
190 template<
typename Archive>
193 [&](
const auto&
t) { ar.attribute(
"type", t); });
195 using TNC = std::remove_cvref_t<decltype(
e)>;
196 auto& e2 =
const_cast<TNC&
>(
e);
198 saver(ar, e2, saveId);
203 template<
typename Archive,
typename TUPLE>
207 [&](
auto& l) { ar.attribute(
"type", l); });
208 v = defaultConstructVariant<V>(idx);
211 loader(ar,
e, args,
id);
251 "can't serialize ptr to primitive type");
258 template<
typename Archive>
266 static inline T*
getPointer(
const std::unique_ptr<T>&
t) {
return t.get(); }
267 template<
typename Archive>
268 static inline void setPointer(std::unique_ptr<T>&
t, T* p, Archive& ) {
276 template<
typename Archive>
277 static void setPointer(std::shared_ptr<T>&
t, T* p, Archive& ar) {
278 ar.resetSharedPtr(
t, p);
331 static const T*
begin(
const T (&array)[
N]) {
return &array[0]; }
332 static const T*
end (
const T (&array)[
N]) {
return &array[
N]; }
334 static constexpr
bool loadInPlace =
true;
336 static T*
output(T (&array)[
N]) {
return &array[0]; }
382 template<
typename Archive>
void operator()(Archive& ar,
const T&
t,
391 template<
typename Archive>
void operator()(Archive& ar,
const T&
t,
395 saveEnum<Archive>(sae.info,
t,
396 [&](
const auto& s) { ar.save(s); });
402 Archive& ar,
const T&
t,
bool saveId,
403 const char* type =
nullptr,
bool saveConstrArgs =
false)
418 unsigned id = ar.generateId(&
t);
419 ar.attribute(
"id",
id);
423 ar.attribute(
"type", type);
427 if ((version != 0) && ar.NEED_VERSION) {
428 if (!ar.CAN_HAVE_OPTIONAL_ATTRIBUTES ||
430 ar.attribute(
"version", version);
434 if (saveConstrArgs) {
437 constrArgs.
save(ar,
t);
440 using TNC = std::remove_const_t<T>;
441 auto& t2 =
const_cast<TNC&
>(
t);
448 template<
typename Archive>
void operator()(Archive& ar,
const TP& tp2,
452 "must be serialized as pointer");
457 ar.attribute(
"id_ref",
id);
460 if (
unsigned id = ar.getId(tp)) {
461 ar.attribute(
"id_ref",
id);
463 if constexpr (std::is_polymorphic_v<T>) {
469 saver(ar, *tp,
true,
nullptr,
true);
476 template<
typename Archive>
void operator()(Archive& ar,
const TP& tp2)
479 "must be serialized as pointer");
488 ar.attribute(
"id_ref",
id);
493 template<
typename Archive>
void operator()(Archive& ar,
const TC& tc,
497 static_assert(sac::value,
"must be serialized as collection");
500 if ((
sac::size < 0) && (!ar.CAN_COUNT_CHILDREN)) {
506 ar.serialize(
"size", n);
510 ar.serializeWithID(
"item", *
begin);
512 ar.serialize(
"item", *
begin);
521 : std::conditional_t<is_primitive<T>::value, PrimitiveSaver<T>,
522 std::conditional_t<Serializer<T>::value, typename Serializer<T>::Saver,
523 std::conditional_t<serialize_as_enum<T>::value, EnumSaver<T>,
524 std::conditional_t<serialize_as_pointer<T>::value, PointerSaver<T>,
525 std::conditional_t<serialize_as_collection<T>::value, CollectionSaver<T>,
526 ClassSaver<T>>>>>> {};
548 template<
typename Archive,
typename TUPLE>
551 static_assert(std::tuple_size_v<TUPLE> == 0,
552 "can't have constructor arguments");
558 template<
typename Archive,
typename TUPLE>
561 static_assert(std::tuple_size_v<TUPLE> == 0,
562 "can't have constructor arguments");
564 loadEnum<Archive>(sae.info,
t, [&](
auto& l) { ar.load(l); });
569 unsigned latestVersion);
571 unsigned latestVersion);
572 template<
typename T,
typename Archive>
unsigned loadVersion(Archive& ar)
575 if ((latestVersion != 0) && ar.NEED_VERSION) {
578 return latestVersion;
583 template<
typename Archive,
typename TUPLE>
587 static_assert(std::tuple_size_v<TUPLE> == 0,
588 "can't have constructor arguments");
595 ar.attribute(
"id",
id);
597 ar.addPointer(
id, &
t);
603 version = loadVersion<T>(ar);
606 using TNC = std::remove_const_t<T>;
607 auto& t2 =
const_cast<TNC&
>(
t);
613 template<
typename Archive,
typename GlobalTuple>
614 T*
operator()(Archive& ar,
unsigned id, GlobalTuple globalArgs)
616 int version = loadVersion<T>(ar);
619 using TNC = std::remove_const_t<T>;
621 ConstrArgs constrArgs;
622 auto localArgs = constrArgs.
load(ar, version);
625 auto args = std::tuple_cat(globalArgs, localArgs);
629 auto tp = creator(args);
631 loader(ar, *tp, std::tuple<>(),
id, version);
637 template<
typename Archive,
typename TUPLE>
641 static_assert(std::is_same_v<TUPLE, ArgsType>,
642 "constructor arguments types must match");
643 return static_cast<T*
>(
651 : std::conditional_t<std::is_polymorphic_v<T>,
652 PolymorphicPointerLoader<T>,
653 NonPolymorphicPointerLoader<T>> {};
657 template<
typename Archive,
typename GlobalTuple>
658 void operator()(Archive& ar, TP& tp2, GlobalTuple globalArgs,
int )
661 "must be serialized as a pointer");
665 if constexpr (Archive::CAN_HAVE_OPTIONAL_ATTRIBUTES) {
666 if (
auto i = ar.template findAttributeAs<unsigned>(
"id_ref")) {
671 ar.attribute(
"id", i);
676 T* tp = [&]() -> T* {
680 if (
void* p = ar.getPointer(
id)) {
681 return static_cast<T*
>(p);
684 return loader(ar,
id, globalArgs);
694 template<
typename Archive>
698 "must be serialized as a pointer");
700 ar.attribute(
"id_ref",
id);
707 void* p = ar.getPointer(
id);
711 tp =
static_cast<T*
>(p);
721 template<
typename Archive,
typename TUPLE,
typename OUT_ITER>
722 void operator()(Archive& ar, TUPLE args, OUT_ITER it,
int id)
724 ar.doSerialize(
"item", *it, args,
id);
733 template<
typename Archive,
typename TUPLE,
typename OUT_ITER>
734 void operator()(Archive& ar, TUPLE args, OUT_ITER it,
int id)
736 typename sac::value_type elem;
737 ar.doSerialize(
"item", elem, args,
id);
738 *it = std::move(elem);
743 template<
typename Archive,
typename TUPLE>
746 assert(
id ==
one_of(0, -1));
748 static_assert(sac::value,
"must be serialized as a collection");
752 if constexpr (Archive::CAN_COUNT_CHILDREN) {
753 n = ar.countChildren();
755 ar.serialize(
"size", n);
759 auto it = sac::output(tc);
762 loadOneElement(ar, args, it,
id);
768 : std::conditional_t<is_primitive<T>::value, PrimitiveLoader<T>,
769 std::conditional_t<Serializer<T>::value, typename Serializer<T>::Loader,
770 std::conditional_t<serialize_as_enum<T>::value, EnumLoader<T>,
771 std::conditional_t<serialize_as_pointer<T>::value, PointerLoader<T>,
772 std::conditional_t<serialize_as_collection<T>::value, CollectionLoader<T>,
773 ClassLoader<T>>>>>> {};
static void * load(Archive &ar, unsigned id, const void *args)
static void save(Archive &ar, T *t)
SDLSurfacePtr load(const std::string &filename, bool want32bpp)
Load the given PNG file in a SDL_Surface.
This file implemented 3 utility functions:
Variant defaultConstructVariant(size_t index)
unsigned loadVersion(Archive &ar)
auto visit(Visitor &&visitor, const Event &event)
T fromString(std::initializer_list< enum_string< T >> list, std::string_view str_)
void serialize(Archive &ar, T &t, unsigned version)
void pointerError(unsigned id)
unsigned loadVersionHelper(MemInputArchive &, const char *, unsigned)
void enumError(const std::string_view str)
void saveEnum(std::initializer_list< enum_string< T >> list, T t, SaveAction save)
std::string toString(const Event &event)
Get a string representation of this event.
void loadEnum(std::initializer_list< enum_string< T >> list, T &t, LoadAction load)
size_t size(std::string_view utf8)
auto distance(octet_iterator first, octet_iterator last)
void operator()(Archive &ar, T &t, TUPLE, int id=0, int version=-1)
void operator()(Archive &ar, const T &t, bool saveId, const char *type=nullptr, bool saveConstrArgs=false)
void operator()(Archive &ar, TUPLE args, OUT_ITER it, int id)
void operator()(Archive &ar, TUPLE args, OUT_ITER it, int id)
void operator()(Archive &ar, TC &tc, TUPLE args, int id=0)
void operator()(Archive &ar, const TC &tc, bool saveId)
Utility to do T* t = new T(...)
Variant operator()(size_t index) const
void operator()(Archive &ar, T &t, TUPLE, int)
void operator()(Archive &ar, const T &t, bool)
void operator()(Archive &ar, TP &tp2)
void operator()(Archive &ar, const TP &tp2)
T * operator()(Archive &ar, unsigned id, GlobalTuple globalArgs)
void operator()(Archive &ar, TP &tp2, GlobalTuple globalArgs, int)
void operator()(Archive &ar, const TP &tp2, bool)
Store association between polymorphic class (base- or subclass) and the list of constructor arguments...
T * operator()(Archive &ar, unsigned id, TUPLE args)
void operator()(Archive &ar, T &t, TUPLE, int)
void operator()(Archive &ar, const T &t, bool)
Store serialization-version number of a class.
static constexpr unsigned value
Serialize (local) constructor arguments.
type load(Archive &, unsigned)
void save(Archive &, const T &)
void operator()(Archive &ar, V &v, TUPLE args, int id)
void operator()(Archive &ar, const V &v, bool saveId)
static constexpr size_t index
static const T * begin(const T(&array)[N])
static T * output(T(&array)[N])
static void prepare(T(&)[N], int)
static const T * end(const T(&array)[N])
static void setPointer(T *&t, T *p, Archive &)
static T * getPointer(T *t)
static T * getPointer(const std::shared_ptr< T > &t)
static void setPointer(std::shared_ptr< T > &t, T *p, Archive &ar)
static T * getPointer(const std::unique_ptr< T > &t)
static void setPointer(std::unique_ptr< T > &t, T *p, Archive &)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)