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));
727 void put(
const void* data,
size_t len)
738 template<
typename ...Args>
739 ALWAYS_INLINE void serialize_group(
const std::tuple<Args...>& tuple)
744 template<
typename TUPLE,
typename T,
typename ...Args>
745 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag,
const T&
t, Args&& ...args)
748 if constexpr (SerializeAsMemcpy<T>::value) {
751 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
754 serialize_group(tuple, std::forward<Args>(args)...);
760 std::vector<size_t> openSections;
761 LastDeltaBlocks& lastDeltaBlocks;
762 std::vector<std::shared_ptr<DeltaBlock>>& deltaBlocks;
763 const bool reverseSnapshot;
770 std::span<
const std::shared_ptr<DeltaBlock>> deltaBlocks_)
772 , deltaBlocks(deltaBlocks_)
786 template<
typename T>
void load(T&
t)
794 void load(std::string& s);
795 [[nodiscard]] std::string_view
loadStr();
800 template<
typename T,
typename ...Args>
804 serialize_group(std::tuple<>(), tag,
t, std::forward<Args>(args)...);
807 template<
typename T,
size_t N>
811 buffer.
read(
t.data(), N *
sizeof(T));
824 void get(
void* data,
size_t len)
827 buffer.
read(data, len);
832 template<
typename TUPLE>
835 auto read = [&](
auto* p) { buffer.
read(p,
sizeof(*p)); };
836 std::apply([&](
auto&&... args) { (read(args), ...); }, tuple);
838 template<
typename TUPLE,
typename T,
typename ...Args>
839 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag, T&
t, Args&& ...args)
841 if constexpr (SerializeAsMemcpy<T>::value) {
843 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
846 serialize_group(tuple, std::forward<Args>(args)...);
852 std::span<const std::shared_ptr<DeltaBlock>> deltaBlocks;
870 template<
typename T>
void save(
const T&
t)
875 void save(std::string_view str);
877 void save(
unsigned char b);
878 void save(
signed char c);
881 void save(
unsigned u);
882 void save(
unsigned long long ull);
890 template<
typename T,
typename ...Args>
906 void endTag(
const char* tag);
912 template<
typename T>
void attribute(
const char* name,
const T&
t)
916 void attribute(
const char* name, std::string_view str);
918 void attribute(
const char* name,
unsigned u);
921 void write(std::span<const char> buf);
923 void check(
bool condition)
const;
928 gzFile file =
nullptr;
937 [[nodiscard]]
inline bool versionAtLeast(
unsigned actual,
unsigned required)
const
939 return actual >= required;
941 [[nodiscard]]
inline bool versionBelow(
unsigned actual,
unsigned required)
const
943 return actual < required;
946 template<
typename T>
void load(T&
t)
950 std::istringstream is(str);
955 void load(
unsigned char& b);
956 void load(
signed char& c);
959 void load(
unsigned& u);
960 void load(
unsigned long long& ull);
961 void load(std::string&
t);
962 [[nodiscard]] std::string_view
loadStr();
969 template<
typename T,
typename ...Args>
978 return elems.back().first;
987 void endTag(
const char* tag);
993 std::istringstream is(str);
1000 void attribute(
const char* name, std::string&
t);
1001 void attribute(
const char* name,
int& i);
1002 void attribute(
const char* name,
unsigned& u);
1004 [[nodiscard]]
bool hasAttribute(
const char* name)
const;
1007 template<
typename T>
1011 return StringOp::stringTo<T>(attr->getValue());
1018 std::vector<std::pair<const XMLElement*, const XMLElement*>> elems;
1021#define INSTANTIATE_SERIALIZE_METHODS(CLASS) \
1022template void CLASS::serialize(MemInputArchive&, unsigned); \
1023template void CLASS::serialize(MemOutputArchive&, unsigned); \
1024template void CLASS::serialize(XmlInputArchive&, unsigned); \
1025template 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 beginTag(const char *)
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 endTag(const char *)
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)
bool hasAttribute(const char *)
Check the presence of a (optional) attribute.
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.
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.
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(size_t &size)
bool isReverseSnapshot() const
unsigned generateId(const T *p)
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)
XmlOutputArchive(zstring_view filename)
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)
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)
size_t size(std::string_view utf8)
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)