2018-08-21 05:27:52 +00:00
|
|
|
// Copyright 2017-2018 ccls Authors
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2017-03-07 09:32:29 +00:00
|
|
|
#pragma once
|
|
|
|
|
2018-10-29 04:21:21 +00:00
|
|
|
#include "maybe.hh"
|
2018-05-28 00:50:02 +00:00
|
|
|
|
|
|
|
#include <llvm/Support/Compiler.h>
|
2018-01-15 16:57:47 +00:00
|
|
|
|
2017-12-29 16:29:10 +00:00
|
|
|
#include <macro_map.h>
|
|
|
|
|
2018-01-11 07:16:33 +00:00
|
|
|
#include <cassert>
|
2018-03-31 03:16:33 +00:00
|
|
|
#include <functional>
|
2017-06-14 04:00:51 +00:00
|
|
|
#include <memory>
|
2018-03-31 03:16:33 +00:00
|
|
|
#include <optional>
|
2017-03-14 08:33:39 +00:00
|
|
|
#include <string>
|
2018-03-31 03:16:33 +00:00
|
|
|
#include <string_view>
|
2018-01-11 07:16:33 +00:00
|
|
|
#include <type_traits>
|
2017-06-14 04:00:51 +00:00
|
|
|
#include <vector>
|
2017-02-23 08:47:07 +00:00
|
|
|
|
2018-09-23 19:10:40 +00:00
|
|
|
namespace llvm {
|
|
|
|
class CachedHashStringRef;
|
|
|
|
class StringRef;
|
|
|
|
}
|
|
|
|
|
2018-10-28 17:49:31 +00:00
|
|
|
namespace ccls {
|
2018-04-14 23:48:56 +00:00
|
|
|
enum class SerializeFormat { Binary, Json };
|
2018-01-06 23:29:53 +00:00
|
|
|
|
2018-04-16 19:36:02 +00:00
|
|
|
struct JsonNull {};
|
|
|
|
|
2018-01-06 21:46:41 +00:00
|
|
|
class Reader {
|
2018-08-09 17:08:14 +00:00
|
|
|
public:
|
2019-01-09 07:19:17 +00:00
|
|
|
virtual ~Reader();
|
2018-01-07 00:22:46 +00:00
|
|
|
virtual SerializeFormat Format() const = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
|
2018-01-19 06:47:44 +00:00
|
|
|
virtual bool IsBool() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual bool IsNull() = 0;
|
|
|
|
virtual bool IsInt() = 0;
|
2018-01-11 07:16:33 +00:00
|
|
|
virtual bool IsInt64() = 0;
|
2018-04-14 23:48:56 +00:00
|
|
|
virtual bool IsUInt64() = 0;
|
2018-01-19 06:47:44 +00:00
|
|
|
virtual bool IsDouble() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual bool IsString() = 0;
|
|
|
|
|
2018-01-08 04:10:16 +00:00
|
|
|
virtual void GetNull() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual bool GetBool() = 0;
|
2018-04-14 23:48:56 +00:00
|
|
|
virtual uint8_t GetUInt8() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual int GetInt() = 0;
|
2018-04-14 23:48:56 +00:00
|
|
|
virtual uint32_t GetUInt32() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual int64_t GetInt64() = 0;
|
2018-04-14 23:48:56 +00:00
|
|
|
virtual uint64_t GetUInt64() = 0;
|
2018-01-10 06:34:58 +00:00
|
|
|
virtual double GetDouble() = 0;
|
2018-08-09 17:08:14 +00:00
|
|
|
virtual const char *GetString() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
virtual bool HasMember(const char *x) = 0;
|
|
|
|
virtual std::unique_ptr<Reader> operator[](const char *x) = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
virtual void IterArray(std::function<void(Reader &)> fn) = 0;
|
|
|
|
virtual void Member(const char *name, std::function<void()> fn) = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Writer {
|
2018-08-09 17:08:14 +00:00
|
|
|
public:
|
2019-01-09 07:19:17 +00:00
|
|
|
virtual ~Writer();
|
2018-01-07 00:22:46 +00:00
|
|
|
virtual SerializeFormat Format() const = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
|
|
|
|
virtual void Null() = 0;
|
|
|
|
virtual void Bool(bool x) = 0;
|
2018-01-06 22:59:05 +00:00
|
|
|
virtual void Int(int x) = 0;
|
|
|
|
virtual void Int64(int64_t x) = 0;
|
2018-04-14 23:48:56 +00:00
|
|
|
virtual void UInt8(uint8_t x) = 0;
|
|
|
|
virtual void UInt32(uint32_t x) = 0;
|
|
|
|
virtual void UInt64(uint64_t x) = 0;
|
2018-01-10 06:34:58 +00:00
|
|
|
virtual void Double(double x) = 0;
|
2018-08-09 17:08:14 +00:00
|
|
|
virtual void String(const char *x) = 0;
|
|
|
|
virtual void String(const char *x, size_t len) = 0;
|
2018-01-07 00:22:46 +00:00
|
|
|
virtual void StartArray(size_t) = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual void EndArray() = 0;
|
2018-01-08 04:10:16 +00:00
|
|
|
virtual void StartObject() = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
virtual void EndObject() = 0;
|
2018-08-09 17:08:14 +00:00
|
|
|
virtual void Key(const char *name) = 0;
|
2018-01-06 21:46:41 +00:00
|
|
|
};
|
|
|
|
|
2017-05-12 06:08:15 +00:00
|
|
|
struct IndexFile;
|
2017-02-23 08:47:07 +00:00
|
|
|
|
2018-05-29 00:03:14 +00:00
|
|
|
#define REFLECT_MEMBER_START() ReflectMemberStart(visitor)
|
|
|
|
#define REFLECT_MEMBER_END() ReflectMemberEnd(visitor);
|
2017-09-22 01:14:57 +00:00
|
|
|
#define REFLECT_MEMBER(name) ReflectMember(visitor, #name, value.name)
|
|
|
|
#define REFLECT_MEMBER2(name, value) ReflectMember(visitor, name, value)
|
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
#define MAKE_REFLECT_TYPE_PROXY(type_name) \
|
2018-04-08 17:32:08 +00:00
|
|
|
MAKE_REFLECT_TYPE_PROXY2(type_name, std::underlying_type_t<type_name>)
|
2018-08-09 17:08:14 +00:00
|
|
|
#define MAKE_REFLECT_TYPE_PROXY2(type, as_type) \
|
|
|
|
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Reader &visitor, type &value) { \
|
|
|
|
as_type value0; \
|
2018-10-28 17:49:31 +00:00
|
|
|
::ccls::Reflect(visitor, value0); \
|
2018-08-09 17:08:14 +00:00
|
|
|
value = static_cast<type>(value0); \
|
|
|
|
} \
|
|
|
|
LLVM_ATTRIBUTE_UNUSED inline void Reflect(Writer &visitor, type &value) { \
|
|
|
|
auto value0 = static_cast<as_type>(value); \
|
2018-10-28 17:49:31 +00:00
|
|
|
::ccls::Reflect(visitor, value0); \
|
2017-03-25 22:13:19 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 01:14:57 +00:00
|
|
|
#define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name);
|
2017-03-25 23:58:11 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
#define MAKE_REFLECT_EMPTY_STRUCT(type, ...) \
|
|
|
|
template <typename TVisitor> void Reflect(TVisitor &visitor, type &value) { \
|
|
|
|
REFLECT_MEMBER_START(); \
|
|
|
|
REFLECT_MEMBER_END(); \
|
2017-03-25 23:58:11 +00:00
|
|
|
}
|
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
#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(); \
|
2017-03-25 23:58:11 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 04:10:16 +00:00
|
|
|
// clang-format off
|
|
|
|
// Config has many fields, we need to support at least its number of fields.
|
|
|
|
#define NUM_VA_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,N,...) N
|
|
|
|
#define NUM_VA_ARGS(...) NUM_VA_ARGS_IMPL(__VA_ARGS__,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)
|
|
|
|
// clang-format on
|
|
|
|
|
2017-09-22 01:14:57 +00:00
|
|
|
#define _MAPPABLE_REFLECT_ARRAY(name) Reflect(visitor, value.name);
|
2017-05-20 19:31:07 +00:00
|
|
|
|
|
|
|
// Reflects the struct so it is serialized as an array instead of an object.
|
|
|
|
// This currently only supports writers.
|
2018-08-09 17:08:14 +00:00
|
|
|
#define MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(type, ...) \
|
|
|
|
inline void Reflect(Writer &visitor, type &value) { \
|
|
|
|
visitor.StartArray(NUM_VA_ARGS(__VA_ARGS__)); \
|
|
|
|
MACRO_MAP(_MAPPABLE_REFLECT_ARRAY, __VA_ARGS__) \
|
|
|
|
visitor.EndArray(); \
|
2017-05-20 19:31:07 +00:00
|
|
|
}
|
2017-03-25 23:58:11 +00:00
|
|
|
|
2018-01-11 08:07:51 +00:00
|
|
|
//// Elementary types
|
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, uint8_t &value);
|
|
|
|
void Reflect(Writer &visitor, uint8_t &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, short &value);
|
|
|
|
void Reflect(Writer &visitor, short &value);
|
2018-02-12 18:15:43 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, unsigned short &value);
|
|
|
|
void Reflect(Writer &visitor, unsigned short &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, int &value);
|
|
|
|
void Reflect(Writer &visitor, int &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, unsigned &value);
|
|
|
|
void Reflect(Writer &visitor, unsigned &value);
|
2018-01-18 08:43:06 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, long &value);
|
|
|
|
void Reflect(Writer &visitor, long &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, unsigned long &value);
|
|
|
|
void Reflect(Writer &visitor, unsigned long &value);
|
2018-01-18 18:41:46 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, long long &value);
|
|
|
|
void Reflect(Writer &visitor, long long &value);
|
2018-01-18 18:41:46 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, unsigned long long &value);
|
|
|
|
void Reflect(Writer &visitor, unsigned long long &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, double &value);
|
|
|
|
void Reflect(Writer &visitor, double &value);
|
2018-01-11 08:07:51 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, bool &value);
|
|
|
|
void Reflect(Writer &visitor, bool &value);
|
2018-01-06 19:26:37 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, std::string &value);
|
|
|
|
void Reflect(Writer &visitor, std::string &value);
|
2017-03-07 18:01:23 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, std::string_view &view);
|
|
|
|
void Reflect(Writer &visitor, std::string_view &view);
|
2018-01-31 04:59:31 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &vis, const char *&v);
|
|
|
|
void Reflect(Writer &vis, const char *&v);
|
2018-02-06 07:22:44 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, JsonNull &value);
|
|
|
|
void Reflect(Writer &visitor, JsonNull &value);
|
2018-01-10 07:57:33 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &visitor, SerializeFormat &value);
|
|
|
|
void Reflect(Writer &visitor, SerializeFormat &value);
|
2018-01-10 07:57:33 +00:00
|
|
|
|
2018-01-11 08:07:51 +00:00
|
|
|
//// Type constructors
|
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
// ReflectMember std::optional<T> is used to represent TypeScript optional
|
|
|
|
// properties (in `key: value` context). Reflect std::optional<T> is used for a
|
|
|
|
// different purpose, whether an object is nullable (possibly in `value`
|
|
|
|
// context).
|
|
|
|
template <typename T> void Reflect(Reader &visitor, std::optional<T> &value) {
|
2018-01-08 04:10:16 +00:00
|
|
|
if (visitor.IsNull()) {
|
|
|
|
visitor.GetNull();
|
2018-01-06 19:26:37 +00:00
|
|
|
return;
|
2018-01-08 04:10:16 +00:00
|
|
|
}
|
2018-01-11 08:31:47 +00:00
|
|
|
T real_value;
|
2018-01-06 19:26:37 +00:00
|
|
|
Reflect(visitor, real_value);
|
2018-02-07 05:45:58 +00:00
|
|
|
value = std::move(real_value);
|
2017-03-07 09:32:29 +00:00
|
|
|
}
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void Reflect(Writer &visitor, std::optional<T> &value) {
|
2018-04-14 23:48:56 +00:00
|
|
|
if (value) {
|
|
|
|
if (visitor.Format() != SerializeFormat::Json)
|
|
|
|
visitor.UInt8(1);
|
2018-01-07 05:08:25 +00:00
|
|
|
Reflect(visitor, *value);
|
2018-04-14 23:48:56 +00:00
|
|
|
} else
|
2018-01-07 05:08:25 +00:00
|
|
|
visitor.Null();
|
2017-03-07 09:32:29 +00:00
|
|
|
}
|
2018-02-02 05:31:56 +00:00
|
|
|
|
|
|
|
// The same as std::optional
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void Reflect(Reader &visitor, Maybe<T> &value) {
|
2018-02-02 05:31:56 +00:00
|
|
|
if (visitor.IsNull()) {
|
|
|
|
visitor.GetNull();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
T real_value;
|
|
|
|
Reflect(visitor, real_value);
|
2018-02-07 05:45:58 +00:00
|
|
|
value = std::move(real_value);
|
2018-02-02 05:31:56 +00:00
|
|
|
}
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void Reflect(Writer &visitor, Maybe<T> &value) {
|
2018-04-14 23:48:56 +00:00
|
|
|
if (value) {
|
|
|
|
if (visitor.Format() != SerializeFormat::Json)
|
|
|
|
visitor.UInt8(1);
|
2018-02-02 05:31:56 +00:00
|
|
|
Reflect(visitor, *value);
|
2018-04-14 23:48:56 +00:00
|
|
|
} else
|
2018-02-02 05:31:56 +00:00
|
|
|
visitor.Null();
|
|
|
|
}
|
|
|
|
|
2018-01-11 08:31:47 +00:00
|
|
|
template <typename T>
|
2018-08-09 17:08:14 +00:00
|
|
|
void ReflectMember(Writer &visitor, const char *name, std::optional<T> &value) {
|
2018-03-31 03:16:33 +00:00
|
|
|
// For TypeScript std::optional property key?: value in the spec,
|
2018-01-11 08:31:47 +00:00
|
|
|
// We omit both key and value if value is std::nullopt (null) for JsonWriter
|
|
|
|
// to reduce output. But keep it for other serialization formats.
|
|
|
|
if (value || visitor.Format() != SerializeFormat::Json) {
|
2018-02-02 05:31:56 +00:00
|
|
|
visitor.Key(name);
|
|
|
|
Reflect(visitor, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The same as std::optional
|
|
|
|
template <typename T>
|
2018-08-09 17:08:14 +00:00
|
|
|
void ReflectMember(Writer &visitor, const char *name, Maybe<T> &value) {
|
2018-04-08 06:32:35 +00:00
|
|
|
if (value.Valid() || visitor.Format() != SerializeFormat::Json) {
|
2018-01-11 08:31:47 +00:00
|
|
|
visitor.Key(name);
|
|
|
|
Reflect(visitor, value);
|
|
|
|
}
|
|
|
|
}
|
2018-01-06 19:26:37 +00:00
|
|
|
|
2018-05-29 00:03:14 +00:00
|
|
|
template <typename L, typename R>
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Reader &vis, std::pair<L, R> &v) {
|
2018-05-29 00:03:14 +00:00
|
|
|
vis.Member("L", [&]() { Reflect(vis, v.first); });
|
|
|
|
vis.Member("R", [&]() { Reflect(vis, v.second); });
|
|
|
|
}
|
|
|
|
template <typename L, typename R>
|
2018-08-09 17:08:14 +00:00
|
|
|
void Reflect(Writer &vis, std::pair<L, R> &v) {
|
2018-05-29 00:03:14 +00:00
|
|
|
vis.StartObject();
|
|
|
|
ReflectMember(vis, "L", v.first);
|
|
|
|
ReflectMember(vis, "R", v.second);
|
|
|
|
vis.EndObject();
|
|
|
|
}
|
|
|
|
|
2018-01-06 19:26:37 +00:00
|
|
|
// std::vector
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void Reflect(Reader &visitor, std::vector<T> &values) {
|
|
|
|
visitor.IterArray([&](Reader &entry) {
|
2018-01-06 19:26:37 +00:00
|
|
|
T entry_value;
|
|
|
|
Reflect(entry, entry_value);
|
2018-02-06 07:22:44 +00:00
|
|
|
values.push_back(std::move(entry_value));
|
2018-01-06 21:46:41 +00:00
|
|
|
});
|
2018-01-06 19:26:37 +00:00
|
|
|
}
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void Reflect(Writer &visitor, std::vector<T> &values) {
|
2018-01-07 00:22:46 +00:00
|
|
|
visitor.StartArray(values.size());
|
2018-08-09 17:08:14 +00:00
|
|
|
for (auto &value : values)
|
2018-01-06 19:26:37 +00:00
|
|
|
Reflect(visitor, value);
|
|
|
|
visitor.EndArray();
|
2018-04-30 04:49:03 +00:00
|
|
|
}
|
|
|
|
|
2018-01-31 04:59:31 +00:00
|
|
|
// ReflectMember
|
2018-01-06 19:26:37 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
inline bool ReflectMemberStart(Reader &vis) { return false; }
|
|
|
|
inline bool ReflectMemberStart(Writer &vis) {
|
2018-05-29 00:03:14 +00:00
|
|
|
vis.StartObject();
|
2017-03-07 09:32:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
2018-01-31 04:59:31 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
inline void ReflectMemberEnd(Reader &vis) {}
|
|
|
|
inline void ReflectMemberEnd(Writer &vis) { vis.EndObject(); }
|
2018-01-31 04:59:31 +00:00
|
|
|
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void ReflectMember(Reader &vis, const char *name, T &v) {
|
2018-05-29 00:03:14 +00:00
|
|
|
vis.Member(name, [&]() { Reflect(vis, v); });
|
2018-01-31 04:59:31 +00:00
|
|
|
}
|
2018-08-09 17:08:14 +00:00
|
|
|
template <typename T> void ReflectMember(Writer &vis, const char *name, T &v) {
|
2018-05-29 00:03:14 +00:00
|
|
|
vis.Key(name);
|
|
|
|
Reflect(vis, v);
|
2017-03-07 09:32:29 +00:00
|
|
|
}
|
2017-03-01 08:36:11 +00:00
|
|
|
|
2018-01-09 06:22:24 +00:00
|
|
|
// API
|
2018-01-07 02:56:15 +00:00
|
|
|
|
2018-09-23 19:10:40 +00:00
|
|
|
const char *Intern(llvm::StringRef str);
|
|
|
|
llvm::CachedHashStringRef InternH(llvm::StringRef str);
|
2018-08-09 17:08:14 +00:00
|
|
|
std::string Serialize(SerializeFormat format, IndexFile &file);
|
|
|
|
std::unique_ptr<IndexFile>
|
|
|
|
Deserialize(SerializeFormat format, const std::string &path,
|
|
|
|
const std::string &serialized_index_content,
|
|
|
|
const std::string &file_content,
|
|
|
|
std::optional<int> expected_version);
|
|
|
|
} // namespace ccls
|