ccls/src/serializer.h
Jacob Dufault 511f6c5248 Fix crash when loading old cache when file format changed.
Also eliminate an unnecessary copy after finishing deserialization.
2017-06-13 21:00:51 -07:00

228 lines
5.7 KiB
C++

#pragma once
#include <macro_map.h>
#include <optional.h>
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
#include <memory>
#include <string>
#include <vector>
using std::experimental::optional;
using std::experimental::nullopt;
using Reader = rapidjson::GenericValue<rapidjson::UTF8<>>;
using Writer = rapidjson::Writer<rapidjson::StringBuffer>;
struct IndexFile;
#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<typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
auto value0 = static_cast<as_type>(value); \
Reflect(visitor, value0); \
value = static_cast<type>(value0); \
}
#define _MAPPABLE_REFLECT_MEMBER(name) \
REFLECT_MEMBER(name);
#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
template<typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
REFLECT_MEMBER_START(); \
REFLECT_MEMBER_END(); \
}
#define MAKE_REFLECT_STRUCT(type, ...) \
template<typename TVisitor> \
void Reflect(TVisitor& visitor, type& value) { \
REFLECT_MEMBER_START(); \
MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \
REFLECT_MEMBER_END(); \
}
#define _MAPPABLE_REFLECT_ARRAY(name) \
Reflect(visitor, value.name);
// Reflects the struct so it is serialized as an array instead of an object.
// This currently only supports writers.
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
inline void Reflect(Writer& visitor, type& value) { \
visitor.StartArray(); \
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
visitor.EndArray(); \
}
template<typename T>
struct NonElidedVector : public std::vector<T> {};
// API:
/*
template<typename TVisitor, typename T>
void Reflect(TVisitor& visitor, T& value) {
static_assert(false, "Missing implementation");
}
template<typename TVisitor>
void DefaultReflectMemberStart(TVisitor& visitor) {
static_assert(false, "Missing implementation");
}
template<typename TVisitor, typename T>
bool ReflectMemberStart(TVisitor& visitor, T& value) {
static_assert(false, "Missing implementation");
return true;
}
template<typename TVisitor, typename T>
void ReflectMemberEnd(TVisitor& visitor, T& value) {
static_assert(false, "Missing implementation");
}
*/
// int16_t
void Reflect(Reader& visitor, int16_t& value);
void Reflect(Writer& visitor, int16_t& value);
// int32_t
void Reflect(Reader& visitor, int32_t& value);
void Reflect(Writer& visitor, int32_t& value);
// int64_t
void Reflect(Reader& visitor, int64_t& value);
void Reflect(Writer& visitor, int64_t& value);
// uint64_t
void Reflect(Reader& visitor, uint64_t& value);
void Reflect(Writer& visitor, uint64_t& 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<typename T>
void Reflect(Writer& visitor, std::vector<T>& values) {
visitor.StartArray();
for (auto& value : values)
Reflect(visitor, value);
visitor.EndArray();
}
template<typename T>
void Reflect(Writer& visitor, optional<T> value) {
if (value)
Reflect(visitor, value.value());
}
inline void DefaultReflectMemberStart(Writer& visitor) {
visitor.StartObject();
}
template<typename T>
bool ReflectMemberStart(Writer& visitor, T& value) {
visitor.StartObject();
return true;
}
template<typename T>
void ReflectMemberEnd(Writer& visitor, T& value) {
visitor.EndObject();
}
template<typename T>
void ReflectMember(Writer& visitor, const char* name, T& value) {
visitor.Key(name);
Reflect(visitor, value);
}
template<typename T>
void ReflectMember(Writer& visitor, const char* name, std::vector<T>& values) {
if (values.empty())
return;
visitor.Key(name);
visitor.StartArray();
for (auto& value : values)
Reflect(visitor, value);
visitor.EndArray();
}
template<typename T>
void ReflectMember(Writer& visitor, const char* name, NonElidedVector<T>& values) {
visitor.Key(name);
visitor.StartArray();
for (auto& value : values)
Reflect(visitor, value);
visitor.EndArray();
}
template<typename T>
void ReflectMember(Writer& visitor, const char* name, optional<T>& value) {
if (!value)
return;
visitor.Key(name);
Reflect(visitor, value);
}
void ReflectMember(Writer& visitor, const char* name, std::string& value);
// Reader:
template<typename T>
void Reflect(Reader& visitor, std::vector<T>& values) {
for (auto& entry : visitor.GetArray()) {
T entry_value;
Reflect(entry, entry_value);
values.push_back(entry_value);
}
}
template<typename T>
void Reflect(Reader& visitor, optional<T>& value) {
T real_value;
Reflect(visitor, real_value);
value = real_value;
}
inline void DefaultReflectMemberStart(Reader& visitor) {}
template<typename T>
bool ReflectMemberStart(Reader& visitor, T& value) {
return true;
}
template<typename T>
void ReflectMemberEnd(Reader& visitor, T& value) {}
template<typename T>
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(IndexFile& file);
std::unique_ptr<IndexFile> Deserialize(std::string path, std::string serialized, optional<int> expected_version);
void SetTestOutputMode();