/* Copyright 2017-2018 ccls Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ #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