23 #include <type_traits>
28 class LastDeltaBlocks;
33 template<
typename T1,
typename T2>
35 return 31 * std::hash<T1>()(p.first) +
36 std::hash<T2>()(p.second);
41 template<
typename T>
struct SerializeClassVersion;
91 template<
typename Base,
typename T>
114 template<
typename Base,
typename T>
240 void attribute(
const char* name,
const char* value);
347 inline Derived&
self()
349 return static_cast<Derived&
>(*this);
379 [[nodiscard]]
static NEVER_INLINE bool addressOnStack(
const void* p)
393 template<
typename T> [[nodiscard]]
unsigned generateId(
const T* p)
405 if constexpr (std::is_polymorphic_v<T>) {
406 return generateID1(p);
408 return generateID2(p,
typeid(T));
412 template<
typename T> [[nodiscard]]
unsigned getId(
const T* p)
414 if constexpr (std::is_polymorphic_v<T>) {
417 return getID2(p,
typeid(T));
425 [[nodiscard]]
unsigned generateID1(
const void* p);
426 [[nodiscard]]
unsigned generateID2(
const void* p,
const std::type_info& typeInfo);
427 [[nodiscard]]
unsigned getID1(
const void* p);
428 [[nodiscard]]
unsigned getID2(
const void* p,
const std::type_info& typeInfo);
436 template<
typename Derived>
440 template<
typename Base,
typename T>
446 "base and derived must have same version when "
447 "using serializeInlinedBase()");
455 template<
typename T,
typename... Args>
460 saver(this->
self(), t,
true);
466 void serialize_blob(
const char* tag,
const void* data,
size_t len,
469 template<
typename T>
void serialize(
const char* tag,
const T&
t)
473 saver(this->
self(), t,
false);
480 saver(this->
self(), t);
485 static_assert(std::is_polymorphic_v<T>,
486 "must be a polymorphic type");
500 this->
self().saveChar(c);
527 [[nodiscard]]
unsigned getId(
const void* p)
const;
535 auto it = sharedPtrMap.
find(r);
536 if (it ==
end(sharedPtrMap)) {
540 s = std::static_pointer_cast<T>(it->second);
552 template<
typename Derived>
556 template<
typename T,
typename... Args>
568 using TNC = std::remove_const_t<T>;
569 auto& tnc =
const_cast<TNC&
>(
t);
571 loader(this->
self(), tnc, std::tuple<>(), -1);
577 using TNC = std::remove_const_t<T>;
578 auto& tnc =
const_cast<TNC&
>(
t);
580 loader(this->
self(), tnc);
585 static_assert(std::is_polymorphic_v<T>,
586 "must be a polymorphic type");
600 this->
self().loadChar(c);
606 template<
typename T,
typename TUPLE>
610 using TNC = std::remove_const_t<T>;
611 auto& tnc =
const_cast<TNC&
>(
t);
613 loader(this->
self(), tnc, args,
id);
646 std::vector<std::shared_ptr<DeltaBlock>>& deltaBlocks_,
647 bool reverseSnapshot_)
648 : lastDeltaBlocks(lastDeltaBlocks_)
649 , deltaBlocks(deltaBlocks_)
650 , reverseSnapshot(reverseSnapshot_)
656 assert(openSections.empty());
662 template<
typename T>
void save(
const T&
t)
670 void save(
const std::string& s) {
save(std::string_view(s)); }
671 void save(std::string_view s);
672 void serialize_blob(
const char* tag,
const void* data,
size_t len,
676 template<
typename T,
typename ...Args>
685 serialize_group(std::tuple<>(), tag,
t, std::forward<Args>(args)...);
687 template<
typename T,
size_t N>
691 buffer.
insert(&
t[0],
N *
sizeof(T));
699 openSections.push_back(beginPos);
703 assert(!openSections.empty());
705 size_t beginPos = openSections.back();
706 openSections.pop_back();
707 size_t skip = endPos - beginPos;
708 buffer.
insertAt(beginPos -
sizeof(skip),
709 &skip,
sizeof(skip));
715 void put(
const void* data,
size_t len)
726 template<
typename ...Args>
727 ALWAYS_INLINE void serialize_group(
const std::tuple<Args...>& tuple)
732 template<
typename TUPLE,
typename T,
typename ...Args>
733 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag,
const T&
t, Args&& ...args)
736 if constexpr (SerializeAsMemcpy<T>::value) {
739 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
742 serialize_group(tuple, std::forward<Args>(args)...);
748 std::vector<size_t> openSections;
749 LastDeltaBlocks& lastDeltaBlocks;
750 std::vector<std::shared_ptr<DeltaBlock>>& deltaBlocks;
751 const bool reverseSnapshot;
758 std::span<
const std::shared_ptr<DeltaBlock>> deltaBlocks_)
760 , deltaBlocks(deltaBlocks_)
774 template<
typename T>
void load(T&
t)
782 void load(std::string& s);
783 [[nodiscard]] std::string_view
loadStr();
788 template<
typename T,
typename ...Args>
792 serialize_group(std::tuple<>(), tag,
t, std::forward<Args>(args)...);
795 template<
typename T,
size_t N>
799 buffer.
read(&
t[0],
N *
sizeof(T));
812 void get(
void* data,
size_t len)
815 buffer.
read(data, len);
820 template<
typename TUPLE>
823 auto read = [&](
auto* p) { buffer.
read(p,
sizeof(*p)); };
824 std::apply([&](
auto&&... args) { (read(args), ...); }, tuple);
826 template<
typename TUPLE,
typename T,
typename ...Args>
827 ALWAYS_INLINE void serialize_group(
const TUPLE& tuple,
const char* tag, T&
t, Args&& ...args)
829 if constexpr (SerializeAsMemcpy<T>::value) {
831 serialize_group(std::tuple_cat(tuple, std::tuple(&
t)), std::forward<Args>(args)...);
834 serialize_group(tuple, std::forward<Args>(args)...);
840 std::span<const std::shared_ptr<DeltaBlock>> deltaBlocks;
858 template<
typename T>
void save(
const T&
t)
863 void save(std::string_view str);
865 void save(
unsigned char b);
866 void save(
signed char c);
869 void save(
unsigned u);
870 void save(
unsigned long long ull);
878 template<
typename T,
typename ...Args>
883 this->
self().
serialize(std::forward<Args>(args)...);
894 void endTag(
const char* tag);
900 template<
typename T>
void attribute(
const char* name,
const T&
t)
904 void attribute(
const char* name, std::string_view str);
906 void attribute(
const char* name,
unsigned u);
909 void write(
const char* buf,
size_t len);
911 void check(
bool condition)
const;
916 gzFile file =
nullptr;
925 [[nodiscard]]
inline bool versionAtLeast(
unsigned actual,
unsigned required)
const
927 return actual >= required;
929 [[nodiscard]]
inline bool versionBelow(
unsigned actual,
unsigned required)
const
931 return actual < required;
934 template<
typename T>
void load(T&
t)
938 std::istringstream is(str);
943 void load(
unsigned char& b);
944 void load(
signed char& c);
947 void load(
unsigned& u);
948 void load(
unsigned long long& ull);
949 void load(std::string&
t);
950 [[nodiscard]] std::string_view
loadStr();
957 template<
typename T,
typename ...Args>
962 this->
self().
serialize(std::forward<Args>(args)...);
966 return elems.back().first;
975 void endTag(
const char* tag);
981 std::istringstream is(str);
988 void attribute(
const char* name, std::string&
t);
989 void attribute(
const char* name,
int& i);
990 void attribute(
const char* name,
unsigned& u);
999 return StringOp::stringTo<T>(attr->getValue());
1006 std::vector<std::pair<const XMLElement*, const XMLElement*>> elems;
1009 #define INSTANTIATE_SERIALIZE_METHODS(CLASS) \
1010 template void CLASS::serialize(MemInputArchive&, unsigned); \
1011 template void CLASS::serialize(MemOutputArchive&, unsigned); \
1012 template void CLASS::serialize(XmlInputArchive&, unsigned); \
1013 template 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.
static constexpr bool NEED_VERSION
Does this archive store version information.
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.
bool hasAttribute(const char *)
Check the presence of a (optional) attribute.
std::optional< T > findAttributeAs(const char *)
Optimization: combination of hasAttribute() and getAttribute().
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.
MemOutputArchive(LastDeltaBlocks &lastDeltaBlocks_, std::vector< std::shared_ptr< DeltaBlock >> &deltaBlocks_, bool reverseSnapshot_)
static constexpr bool NEED_VERSION
ALWAYS_INLINE void serialize(const char *tag, const T &t, Args &&...args)
ALWAYS_INLINE void serialize(const char *, const T(&t)[N]) requires(SerializeAsMemcpy< T >
void save(const std::string &s)
MemBuffer< uint8_t > releaseBuffer(size_t &size)
void serialize_blob(const char *tag, const void *data, size_t len, bool diff=true)
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 serialize_blob(const char *tag, const void *data, size_t len, bool diff=true)
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 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
Get the current size of the 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)
auto & getXMLOutputStream()
void check(bool condition) const
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
void endTag(const char *tag)
void beginTag(const char *tag)
static constexpr bool CAN_COUNT_CHILDREN
void attribute(const char *name, const T &t)
void write(const char *buf, size_t len)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
std::string getName(KeyCode keyCode)
Translate key code to key name.
This file implemented 3 utility functions:
constexpr const char *const filename
void serialize(Archive &ar, T &t, unsigned version)
size_t size(std::string_view utf8)
TemporaryString tmpStrCat(Ts &&... ts)
size_t operator()(const std::pair< T1, T2 > &p) const
Store serialization-version number of a class.
constexpr auto end(const zstring_view &x)