brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · 99841c5 Raw
257 lines · cpp
1//===- MsgPackReader.cpp - Simple MsgPack reader ----------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9///  \file10///  This file implements a MessagePack reader.11///12//===----------------------------------------------------------------------===//13 14#include "llvm/BinaryFormat/MsgPackReader.h"15#include "llvm/BinaryFormat/MsgPack.h"16#include "llvm/Support/Endian.h"17 18using namespace llvm;19using namespace llvm::support;20using namespace msgpack;21 22Reader::Reader(MemoryBufferRef InputBuffer)23    : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),24      End(InputBuffer.getBufferEnd()) {}25 26Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}27 28Expected<bool> Reader::read(Object &Obj) {29  if (Current == End)30    return false;31 32  uint8_t FB = static_cast<uint8_t>(*Current++);33 34  switch (FB) {35  case FirstByte::Nil:36    Obj.Kind = Type::Nil;37    return true;38  case FirstByte::True:39    Obj.Kind = Type::Boolean;40    Obj.Bool = true;41    return true;42  case FirstByte::False:43    Obj.Kind = Type::Boolean;44    Obj.Bool = false;45    return true;46  case FirstByte::Int8:47    Obj.Kind = Type::Int;48    return readInt<int8_t>(Obj);49  case FirstByte::Int16:50    Obj.Kind = Type::Int;51    return readInt<int16_t>(Obj);52  case FirstByte::Int32:53    Obj.Kind = Type::Int;54    return readInt<int32_t>(Obj);55  case FirstByte::Int64:56    Obj.Kind = Type::Int;57    return readInt<int64_t>(Obj);58  case FirstByte::UInt8:59    Obj.Kind = Type::UInt;60    return readUInt<uint8_t>(Obj);61  case FirstByte::UInt16:62    Obj.Kind = Type::UInt;63    return readUInt<uint16_t>(Obj);64  case FirstByte::UInt32:65    Obj.Kind = Type::UInt;66    return readUInt<uint32_t>(Obj);67  case FirstByte::UInt64:68    Obj.Kind = Type::UInt;69    return readUInt<uint64_t>(Obj);70  case FirstByte::Float32:71    Obj.Kind = Type::Float;72    if (sizeof(float) > remainingSpace())73      return make_error<StringError>(74          "Invalid Float32 with insufficient payload",75          std::make_error_code(std::errc::invalid_argument));76    Obj.Float =77        llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current));78    Current += sizeof(float);79    return true;80  case FirstByte::Float64:81    Obj.Kind = Type::Float;82    if (sizeof(double) > remainingSpace())83      return make_error<StringError>(84          "Invalid Float64 with insufficient payload",85          std::make_error_code(std::errc::invalid_argument));86    Obj.Float =87        llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current));88    Current += sizeof(double);89    return true;90  case FirstByte::Str8:91    Obj.Kind = Type::String;92    return readRaw<uint8_t>(Obj);93  case FirstByte::Str16:94    Obj.Kind = Type::String;95    return readRaw<uint16_t>(Obj);96  case FirstByte::Str32:97    Obj.Kind = Type::String;98    return readRaw<uint32_t>(Obj);99  case FirstByte::Bin8:100    Obj.Kind = Type::Binary;101    return readRaw<uint8_t>(Obj);102  case FirstByte::Bin16:103    Obj.Kind = Type::Binary;104    return readRaw<uint16_t>(Obj);105  case FirstByte::Bin32:106    Obj.Kind = Type::Binary;107    return readRaw<uint32_t>(Obj);108  case FirstByte::Array16:109    Obj.Kind = Type::Array;110    return readLength<uint16_t>(Obj);111  case FirstByte::Array32:112    Obj.Kind = Type::Array;113    return readLength<uint32_t>(Obj);114  case FirstByte::Map16:115    Obj.Kind = Type::Map;116    return readLength<uint16_t>(Obj);117  case FirstByte::Map32:118    Obj.Kind = Type::Map;119    return readLength<uint32_t>(Obj);120  case FirstByte::FixExt1:121    Obj.Kind = Type::Extension;122    return createExt(Obj, FixLen::Ext1);123  case FirstByte::FixExt2:124    Obj.Kind = Type::Extension;125    return createExt(Obj, FixLen::Ext2);126  case FirstByte::FixExt4:127    Obj.Kind = Type::Extension;128    return createExt(Obj, FixLen::Ext4);129  case FirstByte::FixExt8:130    Obj.Kind = Type::Extension;131    return createExt(Obj, FixLen::Ext8);132  case FirstByte::FixExt16:133    Obj.Kind = Type::Extension;134    return createExt(Obj, FixLen::Ext16);135  case FirstByte::Ext8:136    Obj.Kind = Type::Extension;137    return readExt<uint8_t>(Obj);138  case FirstByte::Ext16:139    Obj.Kind = Type::Extension;140    return readExt<uint16_t>(Obj);141  case FirstByte::Ext32:142    Obj.Kind = Type::Extension;143    return readExt<uint32_t>(Obj);144  }145 146  if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {147    Obj.Kind = Type::Int;148    int8_t I;149    static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");150    memcpy(&I, &FB, sizeof(FB));151    Obj.Int = I;152    return true;153  }154 155  if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {156    Obj.Kind = Type::UInt;157    Obj.UInt = FB;158    return true;159  }160 161  if ((FB & FixBitsMask::String) == FixBits::String) {162    Obj.Kind = Type::String;163    uint8_t Size = FB & ~FixBitsMask::String;164    return createRaw(Obj, Size);165  }166 167  if ((FB & FixBitsMask::Array) == FixBits::Array) {168    Obj.Kind = Type::Array;169    Obj.Length = FB & ~FixBitsMask::Array;170    return true;171  }172 173  if ((FB & FixBitsMask::Map) == FixBits::Map) {174    Obj.Kind = Type::Map;175    Obj.Length = FB & ~FixBitsMask::Map;176    return true;177  }178 179  return make_error<StringError>(180      "Invalid first byte", std::make_error_code(std::errc::invalid_argument));181}182 183template <class T> Expected<bool> Reader::readRaw(Object &Obj) {184  if (sizeof(T) > remainingSpace())185    return make_error<StringError>(186        "Invalid Raw with insufficient payload",187        std::make_error_code(std::errc::invalid_argument));188  T Size = endian::read<T, Endianness>(Current);189  Current += sizeof(T);190  return createRaw(Obj, Size);191}192 193template <class T> Expected<bool> Reader::readInt(Object &Obj) {194  if (sizeof(T) > remainingSpace())195    return make_error<StringError>(196        "Invalid Int with insufficient payload",197        std::make_error_code(std::errc::invalid_argument));198  Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));199  Current += sizeof(T);200  return true;201}202 203template <class T> Expected<bool> Reader::readUInt(Object &Obj) {204  if (sizeof(T) > remainingSpace())205    return make_error<StringError>(206        "Invalid Int with insufficient payload",207        std::make_error_code(std::errc::invalid_argument));208  Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));209  Current += sizeof(T);210  return true;211}212 213template <class T> Expected<bool> Reader::readLength(Object &Obj) {214  if (sizeof(T) > remainingSpace())215    return make_error<StringError>(216        "Invalid Map/Array with invalid length",217        std::make_error_code(std::errc::invalid_argument));218  Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));219  Current += sizeof(T);220  return true;221}222 223template <class T> Expected<bool> Reader::readExt(Object &Obj) {224  if (sizeof(T) > remainingSpace())225    return make_error<StringError>(226        "Invalid Ext with invalid length",227        std::make_error_code(std::errc::invalid_argument));228  T Size = endian::read<T, Endianness>(Current);229  Current += sizeof(T);230  return createExt(Obj, Size);231}232 233Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {234  if (Size > remainingSpace())235    return make_error<StringError>(236        "Invalid Raw with insufficient payload",237        std::make_error_code(std::errc::invalid_argument));238  Obj.Raw = StringRef(Current, Size);239  Current += Size;240  return true;241}242 243Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {244  if (Current == End)245    return make_error<StringError>(246        "Invalid Ext with no type",247        std::make_error_code(std::errc::invalid_argument));248  Obj.Extension.Type = *Current++;249  if (Size > remainingSpace())250    return make_error<StringError>(251        "Invalid Ext with insufficient payload",252        std::make_error_code(std::errc::invalid_argument));253  Obj.Extension.Bytes = StringRef(Current, Size);254  Current += Size;255  return true;256}257