diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp | 254 |
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; +} |