// Copyright 2017-2018 ccls Authors // SPDX-License-Identifier: Apache-2.0 #pragma once #include "utils.hh" #include #include #include #include #include #include #include #include #include #include #include namespace llvm { class CachedHashStringRef; class StringRef; } namespace ccls { enum class SerializeFormat { Binary, Json }; struct JsonNull {}; struct JsonReader { rapidjson::Value *m; std::vector path_; JsonReader(rapidjson::Value *m) : m(m) {} void StartObject() {} void EndObject() {} void IterArray(std::function fn); void Member(const char *name, std::function fn); bool IsNull(); std::string GetString(); std::string GetPath() const; }; struct JsonWriter { using W = rapidjson::Writer, rapidjson::UTF8, rapidjson::CrtAllocator, 0>; W *m; JsonWriter(W *m) : m(m) {} void StartArray(); void EndArray(); void StartObject(); void EndObject(); void Key(const char *name); void Null(); void Int(int v); void String(const char *s); void String(const char *s, size_t len); }; struct BinaryReader { const char *p_; BinaryReader(std::string_view buf) : p_(buf.data()) {} template T Get() { T ret; memcpy(&ret, p_, sizeof(T)); p_ += sizeof(T); return ret; } uint64_t VarUInt() { auto x = *reinterpret_cast(p_++); if (x < 253) return x; if (x == 253) return Get(); if (x == 254) return Get(); return Get(); } int64_t VarInt() { uint64_t x = VarUInt(); return int64_t(x >> 1 ^ -(x & 1)); } const char *GetString() { const char *ret = p_; while (*p_) p_++; p_++; return ret; } }; struct BinaryWriter { std::string buf_; template void Pack(T x) { auto i = buf_.size(); buf_.resize(i + sizeof(x)); memcpy(buf_.data() + i, &x, sizeof(x)); } void VarUInt(uint64_t n) { if (n < 253) Pack(n); else if (n < 65536) { Pack(253); Pack(n); } else if (n < 4294967296) { Pack(254); Pack(n); } else { Pack(255); Pack(n); } } void VarInt(int64_t n) { VarUInt(uint64_t(n) << 1 ^ n >> 63); } std::string Take() { return std::move(buf_); } void String(const char *x) { String(x, strlen(x)); } void String(const char *x, size_t len) { auto i = buf_.size(); buf_.resize(i + len + 1); memcpy(buf_.data() + i, x, len); } }; struct IndexFile; #define REFLECT_MEMBER(name) ReflectMember(vis, #name, v.name) #define REFLECT_MEMBER2(name, v) ReflectMember(vis, name, v) #define REFLECT_UNDERLYING(T) \ LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonReader &vis, T &v) { \ std::underlying_type_t v0; \ ::ccls::Reflect(vis, v0); \ v = static_cast(v0); \ } \ LLVM_ATTRIBUTE_UNUSED inline void Reflect(JsonWriter &vis, T &v) { \ auto v0 = static_cast>(v); \ ::ccls::Reflect(vis, v0); \ } #define REFLECT_UNDERLYING_B(T) \ REFLECT_UNDERLYING(T) \ LLVM_ATTRIBUTE_UNUSED inline void Reflect(BinaryReader &vis, T &v) { \ std::underlying_type_t v0; \ ::ccls::Reflect(vis, v0); \ v = static_cast(v0); \ } \ LLVM_ATTRIBUTE_UNUSED inline void Reflect(BinaryWriter &vis, T &v) { \ auto v0 = static_cast>(v); \ ::ccls::Reflect(vis, v0); \ } #define _MAPPABLE_REFLECT_MEMBER(name) REFLECT_MEMBER(name); #define REFLECT_STRUCT(type, ...) \ template void Reflect(Vis &vis, type &v) { \ ReflectMemberStart(vis); \ MACRO_MAP(_MAPPABLE_REFLECT_MEMBER, __VA_ARGS__) \ ReflectMemberEnd(vis); \ } #define _MAPPABLE_REFLECT_ARRAY(name) Reflect(vis, v.name); void Reflect(JsonReader &vis, bool &v); void Reflect(JsonReader &vis, unsigned char &v); void Reflect(JsonReader &vis, short &v); void Reflect(JsonReader &vis, unsigned short &v); void Reflect(JsonReader &vis, int &v); void Reflect(JsonReader &vis, unsigned &v); void Reflect(JsonReader &vis, long &v); void Reflect(JsonReader &vis, unsigned long &v); void Reflect(JsonReader &vis, long long &v); void Reflect(JsonReader &vis, unsigned long long &v); void Reflect(JsonReader &vis, double &v); void Reflect(JsonReader &vis, const char *&v); void Reflect(JsonReader &vis, std::string &v); void Reflect(JsonWriter &vis, bool &v); void Reflect(JsonWriter &vis, unsigned char &v); void Reflect(JsonWriter &vis, short &v); void Reflect(JsonWriter &vis, unsigned short &v); void Reflect(JsonWriter &vis, int &v); void Reflect(JsonWriter &vis, unsigned &v); void Reflect(JsonWriter &vis, long &v); void Reflect(JsonWriter &vis, unsigned long &v); void Reflect(JsonWriter &vis, long long &v); void Reflect(JsonWriter &vis, unsigned long long &v); void Reflect(JsonWriter &vis, double &v); void Reflect(JsonWriter &vis, const char *&v); void Reflect(JsonWriter &vis, std::string &v); void Reflect(BinaryReader &vis, bool &v); void Reflect(BinaryReader &vis, unsigned char &v); void Reflect(BinaryReader &vis, short &v); void Reflect(BinaryReader &vis, unsigned short &v); void Reflect(BinaryReader &vis, int &v); void Reflect(BinaryReader &vis, unsigned &v); void Reflect(BinaryReader &vis, long &v); void Reflect(BinaryReader &vis, unsigned long &v); void Reflect(BinaryReader &vis, long long &v); void Reflect(BinaryReader &vis, unsigned long long &v); void Reflect(BinaryReader &vis, double &v); void Reflect(BinaryReader &vis, const char *&v); void Reflect(BinaryReader &vis, std::string &v); void Reflect(BinaryWriter &vis, bool &v); void Reflect(BinaryWriter &vis, unsigned char &v); void Reflect(BinaryWriter &vis, short &v); void Reflect(BinaryWriter &vis, unsigned short &v); void Reflect(BinaryWriter &vis, int &v); void Reflect(BinaryWriter &vis, unsigned &v); void Reflect(BinaryWriter &vis, long &v); void Reflect(BinaryWriter &vis, unsigned long &v); void Reflect(BinaryWriter &vis, long long &v); void Reflect(BinaryWriter &vis, unsigned long long &v); void Reflect(BinaryWriter &vis, double &v); void Reflect(BinaryWriter &vis, const char *&v); void Reflect(BinaryWriter &vis, std::string &v); void Reflect(JsonReader &vis, JsonNull &v); void Reflect(JsonWriter &vis, JsonNull &v); void Reflect(JsonReader &vis, SerializeFormat &v); void Reflect(JsonWriter &vis, SerializeFormat &v); void Reflect(JsonWriter &vis, std::string_view &v); //// Type constructors // ReflectMember std::optional is used to represent TypeScript optional // properties (in `key: value` context). Reflect std::optional is used for a // different purpose, whether an object is nullable (possibly in `value` // context). template void Reflect(JsonReader &vis, std::optional &v) { if (!vis.IsNull()) { v.emplace(); Reflect(vis, *v); } } template void Reflect(JsonWriter &vis, std::optional &v) { if (v) Reflect(vis, *v); else vis.Null(); } template void Reflect(BinaryReader &vis, std::optional &v) { if (*vis.p_++) { v.emplace(); Reflect(vis, *v); } } template void Reflect(BinaryWriter &vis, std::optional &v) { if (v) { vis.Pack(1); Reflect(vis, *v); } else { vis.Pack(0); } } // The same as std::optional template void Reflect(JsonReader &vis, Maybe &v) { if (!vis.IsNull()) Reflect(vis, *v); } template void Reflect(JsonWriter &vis, Maybe &v) { if (v) Reflect(vis, *v); else vis.Null(); } template void Reflect(BinaryReader &vis, Maybe &v) { if (*vis.p_++) Reflect(vis, *v); } template void Reflect(BinaryWriter &vis, Maybe &v) { if (v) { vis.Pack(1); Reflect(vis, *v); } else { vis.Pack(0); } } template void ReflectMember(JsonWriter &vis, const char *name, std::optional &v) { // For TypeScript std::optional property key?: value in the spec, // 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 (v) { vis.Key(name); Reflect(vis, *v); } } template void ReflectMember(BinaryWriter &vis, const char *, std::optional &v) { Reflect(vis, v); } // The same as std::optional template void ReflectMember(JsonWriter &vis, const char *name, Maybe &v) { if (v.Valid()) { vis.Key(name); Reflect(vis, v); } } template void ReflectMember(BinaryWriter &vis, const char *, Maybe &v) { Reflect(vis, v); } template void Reflect(JsonReader &vis, std::pair &v) { vis.Member("L", [&]() { Reflect(vis, v.first); }); vis.Member("R", [&]() { Reflect(vis, v.second); }); } template void Reflect(JsonWriter &vis, std::pair &v) { vis.StartObject(); ReflectMember(vis, "L", v.first); ReflectMember(vis, "R", v.second); vis.EndObject(); } template void Reflect(BinaryReader &vis, std::pair &v) { Reflect(vis, v.first); Reflect(vis, v.second); } template void Reflect(BinaryWriter &vis, std::pair &v) { Reflect(vis, v.first); Reflect(vis, v.second); } // std::vector template void Reflect(JsonReader &vis, std::vector &v) { vis.IterArray([&]() { v.emplace_back(); Reflect(vis, v.back()); }); } template void Reflect(JsonWriter &vis, std::vector &v) { vis.StartArray(); for (auto &it : v) Reflect(vis, it); vis.EndArray(); } template void Reflect(BinaryReader &vis, std::vector &v) { for (auto n = vis.VarUInt(); n; n--) { v.emplace_back(); Reflect(vis, v.back()); } } template void Reflect(BinaryWriter &vis, std::vector &v) { vis.VarUInt(v.size()); for (auto &it : v) Reflect(vis, it); } // ReflectMember template void ReflectMemberStart(T &) {} inline void ReflectMemberStart(JsonWriter &vis) { vis.StartObject(); } template void ReflectMemberEnd(T &) {} inline void ReflectMemberEnd(JsonWriter &vis) { vis.EndObject(); } template void ReflectMember(JsonReader &vis, const char *name, T &v) { vis.Member(name, [&]() { Reflect(vis, v); }); } template void ReflectMember(JsonWriter &vis, const char *name, T &v) { vis.Key(name); Reflect(vis, v); } template void ReflectMember(BinaryReader &vis, const char *, T &v) { Reflect(vis, v); } template void ReflectMember(BinaryWriter &vis, const char *, T &v) { Reflect(vis, v); } // API const char *Intern(llvm::StringRef str); llvm::CachedHashStringRef InternH(llvm::StringRef str); std::string Serialize(SerializeFormat format, IndexFile &file); std::unique_ptr Deserialize(SerializeFormat format, const std::string &path, const std::string &serialized_index_content, const std::string &file_content, std::optional expected_version); } // namespace ccls