#pragma once #include #include #include #include #include #include using std::experimental::optional; using std::experimental::nullopt; using Reader = rapidjson::GenericValue>; using Writer = rapidjson::Writer; struct IndexedFile; #define REFLECT_MEMBER_START() \ if (!ReflectMemberStart(visitor, value)) return #define REFLECT_MEMBER_START1(value) \ if (!ReflectMemberStart(visitor, value)) return #define REFLECT_MEMBER_END() \ ReflectMemberEnd(visitor, value); #define REFLECT_MEMBER_END1(value) \ ReflectMemberEnd(visitor, value); #define REFLECT_MEMBER(name) \ ReflectMember(visitor, #name, value.name) #define REFLECT_MEMBER2(name, value) \ ReflectMember(visitor, name, value) #define MAKE_REFLECT_TYPE_PROXY(type, as_type) \ template \ void Reflect(TVisitor& visitor, type& value) { \ auto value0 = static_cast(value); \ Reflect(visitor, value0); \ value = static_cast(value0); \ } #define _MAPPABLE_REFLECT_MEMBER(name) \ REFLECT_MEMBER(name); #define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \ template \ void Reflect(TVisitor& visitor, type& value) { \ REFLECT_MEMBER_START(); \ REFLECT_MEMBER_END(); \ } #define MAKE_REFLECT_STRUCT(type, ...) \ template \ void Reflect(TVisitor& visitor, type& value) { \ REFLECT_MEMBER_START(); \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ REFLECT_MEMBER_END(); \ } template struct NonElidedVector : public std::vector {}; // API: /* template void Reflect(TVisitor& visitor, T& value) { static_assert(false, "Missing implementation"); } template void DefaultReflectMemberStart(TVisitor& visitor) { static_assert(false, "Missing implementation"); } template bool ReflectMemberStart(TVisitor& visitor, T& value) { static_assert(false, "Missing implementation"); return true; } template void ReflectMemberEnd(TVisitor& visitor, T& value) { static_assert(false, "Missing implementation"); } */ // int void Reflect(Reader& visitor, int& value); void Reflect(Writer& visitor, int& value); // bool void Reflect(Reader& visitor, bool& value); void Reflect(Writer& visitor, bool& value); // std::string void Reflect(Reader& visitor, std::string& value); void Reflect(Writer& visitor, std::string& value); // Writer: template void Reflect(Writer& visitor, std::vector& values) { visitor.StartArray(); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } template void Reflect(Writer& visitor, optional value) { if (value) Reflect(visitor, value.value()); } inline void DefaultReflectMemberStart(Writer& visitor) { visitor.StartObject(); } template bool ReflectMemberStart(Writer& visitor, T& value) { visitor.StartObject(); return true; } template void ReflectMemberEnd(Writer& visitor, T& value) { visitor.EndObject(); } template void ReflectMember(Writer& visitor, const char* name, T& value) { visitor.Key(name); Reflect(visitor, value); } template void ReflectMember(Writer& visitor, const char* name, std::vector& values) { if (values.empty()) return; visitor.Key(name); visitor.StartArray(); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } template void ReflectMember(Writer& visitor, const char* name, NonElidedVector& values) { visitor.Key(name); visitor.StartArray(); for (auto& value : values) Reflect(visitor, value); visitor.EndArray(); } template void ReflectMember(Writer& visitor, const char* name, optional& value) { if (!value) return; visitor.Key(name); Reflect(visitor, value); } void ReflectMember(Writer& visitor, const char* name, std::string& value); // Reader: template void Reflect(Reader& visitor, std::vector& values) { for (auto& entry : visitor.GetArray()) { T entry_value; Reflect(entry, entry_value); values.push_back(entry_value); } } template void Reflect(Reader& visitor, optional& value) { T real_value; Reflect(visitor, real_value); value = real_value; } inline void DefaultReflectMemberStart(Reader& visitor) {} template bool ReflectMemberStart(Reader& visitor, T& value) { return true; } template void ReflectMemberEnd(Reader& visitor, T& value) {} template void ReflectMember(Reader& visitor, const char* name, T& value) { auto it = visitor.FindMember(name); if (it != visitor.MemberEnd()) { Reader& child_visitor = it->value; Reflect(child_visitor, value); } } std::string Serialize(IndexedFile& file); optional Deserialize(std::string path, std::string serialized);