LCOV - code coverage report
Current view: top level - lib/BinaryFormat - MsgPackReader.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 213 240 88.8 %
Date: 2018-10-20 13:21:21 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13