aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-12-20 19:53:05 +0000
commit0b57cec536236d46e3dba9bd041533462f33dbb7 (patch)
tree56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
parent718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff)
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp b/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
new file mode 100644
index 000000000000..872a6e0e29f8
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
@@ -0,0 +1,254 @@
+//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements a MessagePack reader.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/BinaryFormat/MsgPackReader.h"
+#include "llvm/BinaryFormat/MsgPack.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace msgpack;
+
+Reader::Reader(MemoryBufferRef InputBuffer)
+ : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
+ End(InputBuffer.getBufferEnd()) {}
+
+Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
+
+Expected<bool> Reader::read(Object &Obj) {
+ if (Current == End)
+ return false;
+
+ uint8_t FB = static_cast<uint8_t>(*Current++);
+
+ switch (FB) {
+ case FirstByte::Nil:
+ Obj.Kind = Type::Nil;
+ return true;
+ case FirstByte::True:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = true;
+ return true;
+ case FirstByte::False:
+ Obj.Kind = Type::Boolean;
+ Obj.Bool = false;
+ return true;
+ case FirstByte::Int8:
+ Obj.Kind = Type::Int;
+ return readInt<int8_t>(Obj);
+ case FirstByte::Int16:
+ Obj.Kind = Type::Int;
+ return readInt<int16_t>(Obj);
+ case FirstByte::Int32:
+ Obj.Kind = Type::Int;
+ return readInt<int32_t>(Obj);
+ case FirstByte::Int64:
+ Obj.Kind = Type::Int;
+ return readInt<int64_t>(Obj);
+ case FirstByte::UInt8:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint8_t>(Obj);
+ case FirstByte::UInt16:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint16_t>(Obj);
+ case FirstByte::UInt32:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint32_t>(Obj);
+ case FirstByte::UInt64:
+ Obj.Kind = Type::UInt;
+ return readUInt<uint64_t>(Obj);
+ case FirstByte::Float32:
+ Obj.Kind = Type::Float;
+ if (sizeof(float) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float32 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
+ Current += sizeof(float);
+ return true;
+ case FirstByte::Float64:
+ Obj.Kind = Type::Float;
+ if (sizeof(double) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Float64 with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
+ Current += sizeof(double);
+ return true;
+ case FirstByte::Str8:
+ Obj.Kind = Type::String;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Str16:
+ Obj.Kind = Type::String;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Str32:
+ Obj.Kind = Type::String;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Bin8:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint8_t>(Obj);
+ case FirstByte::Bin16:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint16_t>(Obj);
+ case FirstByte::Bin32:
+ Obj.Kind = Type::Binary;
+ return readRaw<uint32_t>(Obj);
+ case FirstByte::Array16:
+ Obj.Kind = Type::Array;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Array32:
+ Obj.Kind = Type::Array;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::Map16:
+ Obj.Kind = Type::Map;
+ return readLength<uint16_t>(Obj);
+ case FirstByte::Map32:
+ Obj.Kind = Type::Map;
+ return readLength<uint32_t>(Obj);
+ case FirstByte::FixExt1:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext1);
+ case FirstByte::FixExt2:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext2);
+ case FirstByte::FixExt4:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext4);
+ case FirstByte::FixExt8:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext8);
+ case FirstByte::FixExt16:
+ Obj.Kind = Type::Extension;
+ return createExt(Obj, FixLen::Ext16);
+ case FirstByte::Ext8:
+ Obj.Kind = Type::Extension;
+ return readExt<uint8_t>(Obj);
+ case FirstByte::Ext16:
+ Obj.Kind = Type::Extension;
+ return readExt<uint16_t>(Obj);
+ case FirstByte::Ext32:
+ Obj.Kind = Type::Extension;
+ return readExt<uint32_t>(Obj);
+ }
+
+ if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
+ Obj.Kind = Type::Int;
+ int8_t I;
+ static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
+ memcpy(&I, &FB, sizeof(FB));
+ Obj.Int = I;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
+ Obj.Kind = Type::UInt;
+ Obj.UInt = FB;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::String) == FixBits::String) {
+ Obj.Kind = Type::String;
+ uint8_t Size = FB & ~FixBitsMask::String;
+ return createRaw(Obj, Size);
+ }
+
+ if ((FB & FixBitsMask::Array) == FixBits::Array) {
+ Obj.Kind = Type::Array;
+ Obj.Length = FB & ~FixBitsMask::Array;
+ return true;
+ }
+
+ if ((FB & FixBitsMask::Map) == FixBits::Map) {
+ Obj.Kind = Type::Map;
+ Obj.Length = FB & ~FixBitsMask::Map;
+ return true;
+ }
+
+ return make_error<StringError>(
+ "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
+}
+
+template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createRaw(Obj, Size);
+}
+
+template <class T> Expected<bool> Reader::readInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Int with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readLength(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Map/Array with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
+ Current += sizeof(T);
+ return true;
+}
+
+template <class T> Expected<bool> Reader::readExt(Object &Obj) {
+ if (sizeof(T) > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with invalid length",
+ std::make_error_code(std::errc::invalid_argument));
+ T Size = endian::read<T, Endianness>(Current);
+ Current += sizeof(T);
+ return createExt(Obj, Size);
+}
+
+Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Raw with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Raw = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}
+
+Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
+ if (Current == End)
+ return make_error<StringError>(
+ "Invalid Ext with no type",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Type = *Current++;
+ if (Size > remainingSpace())
+ return make_error<StringError>(
+ "Invalid Ext with insufficient payload",
+ std::make_error_code(std::errc::invalid_argument));
+ Obj.Extension.Bytes = StringRef(Current, Size);
+ Current += Size;
+ return true;
+}