From ce88a94adc42807f1cda3b97a7fa8f16320d48a8 Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Wed, 13 Nov 2024 15:48:14 -0800 Subject: [SharedCache] Rework metadata serialization to reduce memory overhead api/MetadataSerializable.hpp is removed in favor of including core/MetadataSerializable.hpp. Both headers defined types with the same name leading to One Definition Rule violations and surprising behavior. The serialization and deserialization context are now created on-demand during serialization rather than being a member of `MetadataSerializable`. This reduces the size of every serializable object by ~220 bytes. The context is passed explicitly as an argument to `Serialize` / `Deserialize`. As a result, `Serialize` / `Deserialize` can now be free functions rather than member functions. Since `MetadataSerializable` is not used for dynamic dispatch, the virtual methods are removed and the class is updated to be a class template using CRTP. This allows delegating to the derived class's `Load` and `Store` methods without the additional size overhead of the vtable pointer in every serializable object. These changes reduce the memory footprint of Binary Ninja after loading the macOS shared cache and loading a single dylib from it from 8.3GB to 4.6GB. --- view/sharedcache/core/MetadataSerializable.hpp | 820 ++++++++++++------------- 1 file changed, 401 insertions(+), 419 deletions(-) (limited to 'view/sharedcache/core/MetadataSerializable.hpp') diff --git a/view/sharedcache/core/MetadataSerializable.hpp b/view/sharedcache/core/MetadataSerializable.hpp index c49a9e8c..1b7a03d0 100644 --- a/view/sharedcache/core/MetadataSerializable.hpp +++ b/view/sharedcache/core/MetadataSerializable.hpp @@ -12,15 +12,17 @@ * * Great news. * - * Implement these on your `public MetadataSerializable` subclass: + * Implement these on your `public MetadataSerializable` subclass: * ``` - void Store() override { - MSS(m_someVariable); - MSS(m_someOtherVariable); - } - void Load() override { - MSL(m_someVariable); - MSL(m_someOtherVariable); + class MyClass : public MetadataSerializable { + void Store(SerializationContext& context) const { + MSS(m_someVariable); + MSS(m_someOtherVariable); + } + void Load(DeserializationContext& context) { + MSL(m_someVariable); + MSL(m_someOtherVariable); + } } ``` * Then, you can turn your object into a Metadata object with `AsMetadata()`, and load it back with @@ -37,501 +39,481 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" -#ifndef SHAREDCACHE_METADATASERIALIZABLE_HPP -#define SHAREDCACHE_METADATASERIALIZABLE_HPP +#ifndef SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP +#define SHAREDCACHE_CORE_METADATASERIALIZABLE_HPP + +namespace SharedCacheCore { -#define MSS(name) store(#name, name) -#define MSS_CAST(name, type) store(#name, (type) name) -#define MSS_SUBCLASS(name) Serialize(#name, name) -#define MSL(name) name = load(#name, name) -#define MSL_CAST(name, storedType, type) name = (type)load(#name, (storedType) name) -#define MSL_SUBCLASS(name) Deserialize(#name, name) +#define MSS(name) context.store(#name, name) +#define MSS_CAST(name, type) context.store(#name, (type) name) +#define MSS_SUBCLASS(name) Serialize(context, #name, name) +#define MSL(name) name = context.load(#name) +#define MSL_CAST(name, storedType, type) name = (type)context.load(#name) +#define MSL_SUBCLASS(name) Deserialize(context, #name, name) using namespace BinaryNinja; -class MetadataSerializable -{ -protected: - struct SerialContext - { - rapidjson::Document doc; - rapidjson::Document::AllocatorType allocator; - }; - struct DeserContext - { - rapidjson::Document doc; - }; +struct DeserializationContext; - DeserContext m_activeDeserContext; - SerialContext m_activeContext; +struct SerializationContext { + rapidjson::Document doc; + rapidjson::Document::AllocatorType allocator; -public: - MetadataSerializable() - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); + SerializationContext() { + doc.SetObject(); + allocator = doc.GetAllocator(); } - // copy constructor - MetadataSerializable(const MetadataSerializable& other) + template + void store(std::string_view x, const T& y) { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); + Serialize(*this, x, y); } +}; - // copy assignment - MetadataSerializable& operator=(const MetadataSerializable& other) - { - m_activeContext.doc.CopyFrom(other.m_activeContext.doc, m_activeContext.doc.GetAllocator()); - return *this; - } +struct DeserializationContext { + rapidjson::Document doc; - virtual ~MetadataSerializable() + template + T load(std::string_view x) { + T value; + Deserialize(*this, x, value); + return value; } +}; - void SetupSerContext(rapidjson::Document::AllocatorType* alloc = nullptr) - { - m_activeContext.doc.SetObject(); - m_activeContext.allocator = m_activeContext.doc.GetAllocator(); - } - void S() - { - // fixme factor out - } - void Serialize(std::string& name, bool b) +template +class MetadataSerializable +{ +public: + std::string AsString() const { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, bool& b) { b = m_activeDeserContext.doc[name.c_str()].GetBool(); } + rapidjson::StringBuffer strbuf; + rapidjson::PrettyWriter writer(strbuf); + AsDocument().Accept(writer); - void Serialize(std::string& name, uint8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint8_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + return strbuf.GetString(); } - void Serialize(std::string& name, uint16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint16_t& b) - { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + rapidjson::Document AsDocument() const { + SerializationContext context; + AsDerived().Store(context); + return std::move(context.doc); } - void Serialize(std::string& name, uint32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint32_t& b) + void LoadFromString(const std::string& s) { - b = static_cast(m_activeDeserContext.doc[name.c_str()].GetUint64()); + DeserializationContext context; + context.doc.Parse(s.c_str()); + AsDerived().Load(context); } - void Serialize(std::string& name, uint64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, uint64_t& b) + void LoadFromValue(rapidjson::Value& s) { - b = m_activeDeserContext.doc[name.c_str()].GetUint64(); + DeserializationContext context; + context.doc.CopyFrom(s, context.doc.GetAllocator()); + AsDerived().Load(context); } - void Serialize(std::string& name, int8_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int8_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } + Ref AsMetadata() { return new Metadata(AsString()); } - void Serialize(std::string& name, int16_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int16_t& b) + bool LoadFromMetadata(const Ref& meta) { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); + if (!meta->IsString()) + return false; + LoadFromString(meta->GetString()); + return true; } - void Serialize(std::string& name, int32_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int32_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt(); - } +private: + const Derived& AsDerived() const { return static_cast(*this); } + Derived& AsDerived() { return static_cast(*this); } +}; - void Serialize(std::string& name, int64_t b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, b, m_activeContext.allocator); - } - void Deserialize(std::string& name, int64_t& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetInt64(); - } +inline void Serialize(SerializationContext& context, std::string_view name, bool b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::string b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value value(b.c_str(), m_activeContext.allocator); - m_activeContext.doc.AddMember(key, value, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::string& b) - { - b = m_activeDeserContext.doc[name.c_str()].GetString(); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, bool& b) { + b = context.doc[name.data()].GetBool(); +} - void Serialize(std::string& name, std::map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); - } +inline void Serialize(SerializationContext& context, std::string_view name, uint8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, uint8_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint16_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint32_t& b) +{ + b = static_cast(context.doc[name.data()].GetUint64()); +} + +inline void Serialize(SerializationContext& context, std::string_view name, uint64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, uint64_t& b) +{ + b = context.doc[name.data()].GetUint64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int8_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int8_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int16_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int16_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int32_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, int32_t& b) +{ + b = context.doc[name.data()].GetInt(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, int64_t b) +{ + rapidjson::Value key(name.data(), context.allocator); + context.doc.AddMember(key, b, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) +inline void Deserialize(DeserializationContext& context, std::string_view name, int64_t& b) +{ + b = context.doc[name.data()].GetInt64(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, std::string_view b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value value(b.data(), context.allocator); + context.doc.AddMember(key, value, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::string& b) +{ + b = context.doc[name.data()].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), m_activeContext.allocator); - rapidjson::Value value(i.second.c_str(), m_activeContext.allocator); - p.PushBack(_key, m_activeContext.allocator); - p.PushBack(value, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} - void Serialize(std::string& name, std::unordered_map b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - p.PushBack(i.first, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + rapidjson::Value value(i.second.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(value, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetString(); +} + +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); + rapidjson::Value p(rapidjson::kArrayType); + p.PushBack(i.first, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} - // std::unordered_map> - void Serialize(std::string& name, std::unordered_map> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value classes(rapidjson::kArrayType); - for (auto& i : b) +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetUint64()] = i.GetArray()[1].GetUint64(); +} + +// std::unordered_map> +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value classes(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value classArr(rapidjson::kArrayType); + rapidjson::Value classKey(i.first.c_str(), context.allocator); + classArr.PushBack(classKey, context.allocator); + rapidjson::Value membersArr(rapidjson::kArrayType); + for (auto& j : i.second) { - rapidjson::Value classArr(rapidjson::kArrayType); - rapidjson::Value classKey(i.first.c_str(), m_activeContext.allocator); - classArr.PushBack(classKey, m_activeContext.allocator); - rapidjson::Value membersArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value member(rapidjson::kArrayType); - member.PushBack(j.first, m_activeContext.allocator); - member.PushBack(j.second, m_activeContext.allocator); - membersArr.PushBack(member, m_activeContext.allocator); - } - classArr.PushBack(membersArr, m_activeContext.allocator); - classes.PushBack(classArr, m_activeContext.allocator); + rapidjson::Value member(rapidjson::kArrayType); + member.PushBack(j.first, context.allocator); + member.PushBack(j.second, context.allocator); + membersArr.PushBack(member, context.allocator); } - m_activeContext.doc.AddMember(key, classes, m_activeContext.allocator); + classArr.PushBack(membersArr, context.allocator); + classes.PushBack(classArr, context.allocator); } - void Deserialize(std::string& name, std::unordered_map>& b) + context.doc.AddMember(key, classes, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) + std::string key = i.GetArray()[0].GetString(); + std::unordered_map memArray; + for (auto& member : i.GetArray()[1].GetArray()) { - std::string key = i.GetArray()[0].GetString(); - std::unordered_map memArray; - for (auto& member : i.GetArray()[1].GetArray()) - { - memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); - } - b[key] = memArray; + memArray[member.GetArray()[0].GetUint64()] = member.GetArray()[1].GetUint64(); } + b[key] = memArray; } +} - void Deserialize(std::string& name, std::unordered_map& b) - { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); - } +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetString(); +} - void Serialize(std::string& name, std::vector b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (const auto& s : b) - { - rapidjson::Value value(s.c_str(), m_activeContext.allocator); - bArr.PushBack(value, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); - } - void Deserialize(std::string& name, std::vector& b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (const auto& s : b) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - b.emplace_back(i.GetString()); + rapidjson::Value value(s.c_str(), context.allocator); + bArr.PushBack(value, context.allocator); } + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) + b.emplace_back(i.GetString()); +} - void Serialize(std::string& name, std::vector>> b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second.first, m_activeContext.allocator); - segV.PushBack(i.second.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second.first, context.allocator); + segV.PushBack(i.second.second, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair> j; - j.first = i.GetArray()[0].GetUint64(); - j.second.first = i.GetArray()[1].GetUint64(); - j.second.second = i.GetArray()[2].GetUint64(); - b.push_back(j); - } + std::pair> j; + j.first = i.GetArray()[0].GetUint64(); + j.second.first = i.GetArray()[1].GetUint64(); + j.second.second = i.GetArray()[2].GetUint64(); + b.push_back(j); } +} - void Serialize(std::string& name, std::vector> b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - segV.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + segV.PushBack(i.second, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - std::pair j; - j.first = i.GetArray()[0].GetUint64(); - j.second = i.GetArray()[1].GetBool(); - b.push_back(j); - } + std::pair j; + j.first = i.GetArray()[0].GetUint64(); + j.second = i.GetArray()[1].GetBool(); + b.push_back(j); } +} - void Serialize(std::string& name, std::vector b) +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - bArr.PushBack(i, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + bArr.PushBack(i, context.allocator); } - void Deserialize(std::string& name, std::vector& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b.push_back(i.GetUint64()); - } + b.push_back(i.GetUint64()); } +} - // std::unordered_map - void Serialize(std::string& name, std::unordered_map b) +// std::unordered_map +inline void Serialize(SerializationContext& context, std::string_view name, const std::unordered_map& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) - { - rapidjson::Value p(rapidjson::kArrayType); - rapidjson::Value _key(i.first.c_str(), m_activeContext.allocator); - p.PushBack(_key, m_activeContext.allocator); - p.PushBack(i.second, m_activeContext.allocator); - bArr.PushBack(p, m_activeContext.allocator); - } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + rapidjson::Value p(rapidjson::kArrayType); + rapidjson::Value _key(i.first.c_str(), context.allocator); + p.PushBack(_key, context.allocator); + p.PushBack(i.second, context.allocator); + bArr.PushBack(p, context.allocator); } - void Deserialize(std::string& name, std::unordered_map& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::unordered_map& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) - { - b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); - } + b[i.GetArray()[0].GetString()] = i.GetArray()[1].GetUint64(); } - // std::vector>>> - void Serialize(std::string& name, std::vector>>> b) - { - S(); - rapidjson::Value key(name.c_str(), m_activeContext.allocator); - rapidjson::Value bArr(rapidjson::kArrayType); - for (auto& i : b) +} + +// std::vector>>> +inline void Serialize(SerializationContext& context, std::string_view name, const std::vector>>>& b) +{ + rapidjson::Value key(name.data(), context.allocator); + rapidjson::Value bArr(rapidjson::kArrayType); + for (auto& i : b) + { + rapidjson::Value segV(rapidjson::kArrayType); + segV.PushBack(i.first, context.allocator); + rapidjson::Value segArr(rapidjson::kArrayType); + for (auto& j : i.second) { - rapidjson::Value segV(rapidjson::kArrayType); - segV.PushBack(i.first, m_activeContext.allocator); - rapidjson::Value segArr(rapidjson::kArrayType); - for (auto& j : i.second) - { - rapidjson::Value segPair(rapidjson::kArrayType); - segPair.PushBack(j.first, m_activeContext.allocator); - rapidjson::Value segStr(j.second.c_str(), m_activeContext.allocator); - segPair.PushBack(segStr, m_activeContext.allocator); - segArr.PushBack(segPair, m_activeContext.allocator); - } - segV.PushBack(segArr, m_activeContext.allocator); - bArr.PushBack(segV, m_activeContext.allocator); + rapidjson::Value segPair(rapidjson::kArrayType); + segPair.PushBack(j.first, context.allocator); + rapidjson::Value segStr(j.second.c_str(), context.allocator); + segPair.PushBack(segStr, context.allocator); + segArr.PushBack(segPair, context.allocator); } - m_activeContext.doc.AddMember(key, bArr, m_activeContext.allocator); + segV.PushBack(segArr, context.allocator); + bArr.PushBack(segV, context.allocator); } - void Deserialize(std::string& name, std::vector>>>& b) + context.doc.AddMember(key, bArr, context.allocator); +} + +inline void Deserialize(DeserializationContext& context, std::string_view name, std::vector>>>& b) +{ + for (auto& i : context.doc[name.data()].GetArray()) { - for (auto& i : m_activeDeserContext.doc[name.c_str()].GetArray()) + std::pair>> j; + j.first = i.GetArray()[0].GetUint64(); + for (auto& k : i.GetArray()[1].GetArray()) { - std::pair>> j; - j.first = i.GetArray()[0].GetUint64(); - for (auto& k : i.GetArray()[1].GetArray()) - { - j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); - } - b.push_back(j); + j.second.push_back({k.GetArray()[0].GetUint64(), k.GetArray()[1].GetString()}); } + b.push_back(j); } +} - template - void store(std::string x, T y) - { - Serialize(x, y); - } - - template - T load(std::string x, T y) - { - T val; - Deserialize(x, val); - return val; - } - - rapidjson::Document& GetDoc() - { - S(); - Store(); - return m_activeContext.doc; - } - -public: - virtual void Store() = 0; - virtual void Load() = 0; - - std::string AsString() - { - rapidjson::StringBuffer strbuf; - rapidjson::PrettyWriter writer(strbuf); - GetDoc().Accept(writer); - - std::string s = strbuf.GetString(); - return s; - } - rapidjson::Document& AsDocument() { return GetDoc(); } - void LoadFromString(const std::string& s) - { - m_activeDeserContext.doc.Parse(s.c_str()); - Load(); - } - void LoadFromValue(rapidjson::Value& s) - { - m_activeDeserContext.doc.CopyFrom(s, m_activeDeserContext.doc.GetAllocator()); - Load(); - } - Ref AsMetadata() { return new Metadata(AsString()); } - bool LoadFromMetadata(const Ref& meta) - { - if (!meta->IsString()) - return false; - LoadFromString(meta->GetString()); - return true; - } -}; +} // namespace SharedCacheCore #endif // SHAREDCACHE_METADATASERIALIZABLE_HPP -- cgit v1.3.1