34 template<
typename T1,
typename T2>
36 return 31 * std::hash<T1>()(p.first) +
37 std::hash<T2>()(p.second);
42template<
typename T>
struct SerializeClassVersion;
92 template<
typename Base,
typename T>
96 self().serialize(tag,
static_cast<Base&
>(
t));
115 template<
typename Base,
typename T>
155 self().serialize_blob(tag, std::span<uint8_t>{
static_cast<uint8_t*
>(data.data()), data.size_bytes()}, diff);
160 self().serialize_blob(tag, std::span<uint8_t>{
static_cast<const uint8_t*
>(data.data()), data.size_bytes()}, diff);
250 self().serialize(name,
t);
252 void attribute(
const char* name,
const char* value);
361 return static_cast<Derived&
>(*this);
391 [[nodiscard]]
static NEVER_INLINE bool addressOnStack(
const void* p)
405 template<
typename T> [[nodiscard]]
unsigned generateId(
const T* p)
417 if constexpr (std::is_polymorphic_v<T>) {
418 return generateID1(p);
420 return generateID2(p,
typeid(T));
424 template<
typename T> [[nodiscard]]
unsigned getId(
const T* p)
426 if constexpr (std::is_polymorphic_v<T>) {
429 return getID2(p,
typeid(T));
437 [[nodiscard]]
unsigned generateID1(
const void* p);
438 [[nodiscard]]
unsigned generateID2(
const void* p,
const std::type_info& typeInfo);
439 [[nodiscard]]
unsigned getID1(
const void* p);
440 [[nodiscard]]
unsigned getID2(
const void* p,
const std::type_info& typeInfo);
448template<
typename Derived>
452 template<
typename Base,
typename T>
458 "base and derived must have same version when "
459 "using serializeInlinedBase()");
467 template<
typename T,
typename... Args>
470 this->
self().beginTag(tag);
472 saver(this->
self(), t,
true);
473 this->
self().endTag(tag);
478 void serialize_blob(
const char* tag, std::span<const uint8_t> data,
481 template<
typename T>
void serialize(
const char* tag,
const T&
t)
483 this->
self().beginTag(tag);
485 saver(this->
self(), t,
false);
486 this->
self().endTag(tag);
490 this->
self().beginTag(tag);
492 saver(this->
self(), t);
493 this->
self().endTag(tag);
497 static_assert(std::is_polymorphic_v<T>,
498 "must be a polymorphic type");
511 this->
self().beginTag(tag);
512 this->
self().saveChar(c);
513 this->
self().endTag(tag);
539 [[nodiscard]]
unsigned getId(
const void* p)
const;
547 auto it = sharedPtrMap.
find(r);
548 if (it ==
end(sharedPtrMap)) {
552 s = std::static_pointer_cast<T>(it->second);
564template<
typename Derived>
568 template<
typename T,
typename... Args>
579 this->
self().beginTag(tag);
580 using TNC = std::remove_const_t<T>;
581 auto& tnc =
const_cast<TNC&
>(
t);
583 loader(this->
self(), tnc, std::tuple<>(), -1);
584 this->
self().endTag(tag);
588 this->
self().beginTag(tag);
589 using TNC = std::remove_const_t<T>;
590 auto& tnc =
const_cast<TNC&
>(
t);
592 loader(this->
self(), tnc);
593 this->
self().endTag(tag);
597 static_assert(std::is_polymorphic_v<T>,
598 "must be a polymorphic type");
611 this->
self().beginTag(tag);
612 this->
self().loadChar(c);
613 this->
self().endTag(tag);
618 template<
typename T,
typename TUPLE>
621 this->
self().beginTag(tag);
622 using TNC = std::remove_const_t<T>;
623 auto& tnc =
const_cast<TNC&
>(
t);
625 loader(this->
self(), tnc, args,
id);
626 this->
self().endTag(tag);
658 std::vector<std::shared_ptr<DeltaBlock>>& deltaBlocks_,
659 bool reverseSnapshot_)
660 : lastDeltaBlocks(lastDeltaBlocks_)
661 , deltaBlocks(deltaBlocks_)
662 , reverseSnapshot(reverseSnapshot_)
668 assert(openSections.empty());
674 template<
typename T>
void save(
const T&
t)
682 void save(
const std::string& s) {
save(std::string_view(s)); }
683 void save(std::string_view s);
684 void serialize_blob(
const char* tag, std::span<const uint8_t> data,
688 template<
typename T,
typename ...Args>
697 serialize_group(std::tuple<>(), tag,
t, std::forward<Args>(args)...);
699 template<
typename T,
size_t N>
703 buffer.
insert(
t.data(), N *
sizeof(T));
711 openSections.push_back(beginPos);
715 assert(!openSections.empty());
717 size_t beginPos = openSections.back();
718 openSections.pop_back();
719 size_t skip = endPos - beginPos;
720 buffer.
insertAt(beginPos -
sizeof(skip),
721 &skip,
sizeof(skip));
726 return std::move(buffer).release();
730 ALWAYS_INLINE void serialize_group(
const std::tuple<>& )
const
734 template<
typename ...Args>
735 ALWAYS_INLINE void serialize_group(
const std::tuple<Args...>& tuple)
740 template<
typename TUPLE,
typename T,
typename ...Args>
741 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag,
const T&
t, Args&& ...args)
744 if constexpr (SerializeAsMemcpy<T>::value) {
747 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
750 serialize_group(tuple, std::forward<Args>(args)...);
756 std::vector<size_t> openSections;
757 LastDeltaBlocks& lastDeltaBlocks;
758 std::vector<std::shared_ptr<DeltaBlock>>& deltaBlocks;
759 const bool reverseSnapshot;
766 std::span<
const std::shared_ptr<DeltaBlock>> deltaBlocks_)
768 , deltaBlocks(deltaBlocks_)
782 template<
typename T>
void load(T&
t)
784 buffer.
read(&
t,
sizeof(
t));
790 void load(std::string& s);
791 [[nodiscard]] std::string_view
loadStr();
796 template<
typename T,
typename ...Args>
800 serialize_group(std::tuple<>(), tag,
t, std::forward<Args>(args)...);
803 template<
typename T,
size_t N>
807 buffer.
read(
t.data(), N *
sizeof(T));
821 template<
typename TUPLE>
824 auto read = [&](
auto* p) { buffer.
read(p,
sizeof(*p)); };
825 std::apply([&](
auto&&... args) { (read(args), ...); }, tuple);
827 template<
typename TUPLE,
typename T,
typename ...Args>
828 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag, T&
t, Args&& ...args)
830 if constexpr (SerializeAsMemcpy<T>::value) {
832 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
835 serialize_group(tuple, std::forward<Args>(args)...);
841 std::span<const std::shared_ptr<DeltaBlock>> deltaBlocks;
859 template<
typename T>
void save(
const T&
t)
864 void save(std::string_view str);
866 void save(
unsigned char b);
867 void save(
signed char c);
870 void save(
unsigned u);
871 void save(
unsigned long long ull);
879 template<
typename T,
typename ...Args>
883 this->
self().serialize(tag,
t);
884 this->
self().serialize(std::forward<Args>(args)...);
895 void endTag(
const char* tag);
901 template<
typename T>
void attribute(
const char* name,
const T&
t)
905 void attribute(
const char* name, std::string_view str);
907 void attribute(
const char* name,
unsigned u);
910 void write(std::span<const char> buf);
912 void check(
bool condition)
const;
913 [[noreturn]]
void error();
917 gzFile file =
nullptr;
926 [[nodiscard]]
inline bool versionAtLeast(
unsigned actual,
unsigned required)
const
928 return actual >= required;
930 [[nodiscard]]
inline bool versionBelow(
unsigned actual,
unsigned required)
const
932 return actual < required;
936 void load(
bool& b)
const;
937 void load(
unsigned char& b)
const;
938 void load(
signed char& c)
const;
939 void load(
char& c)
const;
940 void load(
int& i)
const;
941 void load(
unsigned& u)
const;
942 void load(
unsigned long long& ull)
const;
943 void load(std::string&
t)
const;
944 template<
typename T>
void load(T&
t)
const
948 std::istringstream is(str);
951 [[nodiscard]] std::string_view
loadStr()
const;
958 template<
typename T,
typename ...Args>
962 this->
self().serialize(tag,
t);
963 this->
self().serialize(std::forward<Args>(args)...);
967 return elems.back().first;
976 void endTag(
const char* tag);
982 std::istringstream is(str);
989 void attribute(
const char* name, std::string&
t)
const;
990 void attribute(
const char* name,
int& i)
const;
991 void attribute(
const char* name,
unsigned& u)
const;
993 [[nodiscard]]
bool hasAttribute(
const char* name)
const;
1000 return StringOp::stringTo<T>(attr->getValue());
1007 std::vector<std::pair<const XMLElement*, const XMLElement*>> elems;
1010#define INSTANTIATE_SERIALIZE_METHODS(CLASS) \
1011template void CLASS::serialize(MemInputArchive&, unsigned); \
1012template void CLASS::serialize(MemOutputArchive&, unsigned); \
1013template void CLASS::serialize(XmlInputArchive&, unsigned); \
1014template void CLASS::serialize(XmlOutputArchive&, unsigned);
'XMLOutputStream' is a helper to write an XML file in a streaming way.
iterator emplace_noDuplicateCheck(Args &&... args)
iterator find(const K &key)
static constexpr bool CAN_HAVE_OPTIONAL_ATTRIBUTES
Some archives (like XML archives) can store optional attributes.
bool isReverseSnapshot() const
Is this a reverse-snapshot?
void endTag(const char *) const
Indicate begin of a tag.
std::optional< T > findAttributeAs(const char *)
Optimization: combination of hasAttribute() and getAttribute().
static constexpr bool NEED_VERSION
Does this archive store version information.
Derived & self()
Returns a reference to the most derived class.
void beginTag(const char *) const
Indicate begin of a tag.
static constexpr bool CAN_COUNT_CHILDREN
Some archives (like XML archives) can count the number of subtags that belong to the current tag.
void serialize_blob(const char *tag, std::span< const T > data, bool diff=true)
void serialize_blob(const char *tag, std::span< T > data, bool diff=true)
void attribute(const char *name, T &t)
Load/store an attribute from/in the archive.
bool hasAttribute(const char *) const
Check the presence of a (optional) attribute.
int countChildren() const
Count the number of child tags.
static constexpr bool TRANSLATE_ENUM_TO_STRING
Does this archive store enums as strings.
void serializeInlinedBase(T &t, unsigned version)
Serialize the base class of this classtype.
void serializeBase(T &t)
Is this archive a loader or a saver.
This class manages the lifetime of a block of memory.
static constexpr bool NEED_VERSION
void serialize_blob(const char *tag, std::span< const uint8_t > data, bool diff=true)
ALWAYS_INLINE void serialize(const char *tag, const T &t, Args &&...args)
MemOutputArchive(LastDeltaBlocks &lastDeltaBlocks_, std::vector< std::shared_ptr< DeltaBlock > > &deltaBlocks_, bool reverseSnapshot_)
ALWAYS_INLINE void serialize(const char *, const std::array< T, N > &t)
void save(const std::string &s)
MemBuffer< uint8_t > releaseBuffer() &&
bool isReverseSnapshot() const
unsigned generateId(const T *p)
void skipSection(bool) const
unsigned getId(const T *p)
bool versionBelow(unsigned, unsigned) const
OutputArchiveBase2()=default
static constexpr bool IS_LOADER
bool versionAtLeast(unsigned, unsigned) const
void serializePolymorphic(const char *tag, const T &t)
void serializePointerID(const char *tag, const T &t)
void serializeOnlyOnce(const char *tag, const T &t)
void serialize_blob(const char *tag, std::span< const uint8_t > data, bool diff=true)
void serializeChar(const char *tag, char c)
OutputArchiveBase()=default
void serializeInlinedBase(T &t, unsigned version)
void serialize(const char *tag, const T &t)
void serializeWithID(const char *tag, const T &t, Args...)
void insertAt(size_t pos, const void *data, size_t len)
Insert data at a given position.
ALWAYS_INLINE void insert_tuple_ptr(const TUPLE &tuple)
Insert all the elements of the given tuple.
size_t getPosition() const
Free part of a previously allocated buffer.
void insert(const void *data, size_t len)
Insert data at the end of this buffer.
static void init(const char *tag, Archive &ar, void *t)
static void save(Archive &ar, T *t)
void saveImpl(const T &t)
void check(bool condition) const
void write(std::span< const char > buf)
static constexpr bool CAN_HAVE_OPTIONAL_ATTRIBUTES
ALWAYS_INLINE void serialize(const char *tag, const T &t, Args &&...args)
void attributeImpl(const char *name, const T &t)
static constexpr bool TRANSLATE_ENUM_TO_STRING
auto & getXMLOutputStream()
void endTag(const char *tag)
void beginTag(const char *tag)
void beginSection() const
static constexpr bool CAN_COUNT_CHILDREN
void attribute(const char *name, const T &t)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
This file implemented 3 utility functions:
void serialize(Archive &ar, T &t, unsigned version)
TemporaryString tmpStrCat(Ts &&... ts)
Stores the name of a base class.
size_t operator()(const std::pair< T1, T2 > &p) const
Store serialization-version number of a class.
constexpr auto end(const zstring_view &x)