// Copyright 2017-2018 ccls Authors // SPDX-License-Identifier: Apache-2.0 #pragma once #include "serializer.hh" #include namespace ccls { class BinaryReader : public Reader { const char *p_; 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)); } public: BinaryReader(std::string_view buf) : p_(buf.data()) {} virtual ~BinaryReader(); SerializeFormat Format() const override { return SerializeFormat::Binary; } bool IsBool() override { return true; } // Abuse how the function is called in serializer.h bool IsNull() override { return !*p_++; } bool IsInt() override { return true; } bool IsInt64() override { return true; } bool IsUInt64() override { return true; } bool IsDouble() override { return true; } bool IsString() override { return true; } void GetNull() override {} bool GetBool() override { return Get(); } int GetInt() override { return VarInt(); } int64_t GetInt64() override { return VarInt(); } uint8_t GetUInt8() override { return Get(); } uint32_t GetUInt32() override { return VarUInt(); } uint64_t GetUInt64() override { return VarUInt(); } double GetDouble() override { return Get(); } const char *GetString() override { const char *ret = p_; while (*p_) p_++; p_++; return ret; } bool HasMember(const char *x) override { return true; } std::unique_ptr operator[](const char *x) override { return {}; } void IterArray(std::function fn) override { for (auto n = VarUInt(); n; n--) fn(*this); } void Member(const char *, std::function fn) override { fn(); } }; class BinaryWriter : public Writer { 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); } public: virtual ~BinaryWriter(); SerializeFormat Format() const override { return SerializeFormat::Binary; } std::string Take() { return std::move(buf_); } void Null() override { Pack(uint8_t(0)); } void Bool(bool x) override { Pack(x); } void Int(int x) override { VarInt(x); } void Int64(int64_t x) override { VarInt(x); } void UInt8(uint8_t x) override { Pack(x); } void UInt32(uint32_t x) override { VarUInt(x); } void UInt64(uint64_t x) override { VarUInt(x); } void Double(double x) override { Pack(x); } void String(const char *x) override { String(x, strlen(x)); } void String(const char *x, size_t len) override { auto i = buf_.size(); buf_.resize(i + len + 1); memcpy(buf_.data() + i, x, len); } void StartArray(size_t n) override { VarUInt(n); } void EndArray() override {} void StartObject() override {} void EndObject() override {} void Key(const char *name) override {} }; } // namespace ccls