LLVM  10.0.0svn
MsgPackReader.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements a MessagePack reader.
11 ///
12 //===----------------------------------------------------------------------===//
13 
16 #include "llvm/Support/Endian.h"
17 
18 using namespace llvm;
19 using namespace llvm::support;
20 using namespace msgpack;
21 
22 Reader::Reader(MemoryBufferRef InputBuffer)
23  : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
24  End(InputBuffer.getBufferEnd()) {}
25 
26 Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
27 
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 = BitsToFloat(endian::read<uint32_t, Endianness>(Current));
77  Current += sizeof(float);
78  return true;
79  case FirstByte::Float64:
80  Obj.Kind = Type::Float;
81  if (sizeof(double) > remainingSpace())
82  return make_error<StringError>(
83  "Invalid Float64 with insufficient payload",
84  std::make_error_code(std::errc::invalid_argument));
85  Obj.Float = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
86  Current += sizeof(double);
87  return true;
88  case FirstByte::Str8:
89  Obj.Kind = Type::String;
90  return readRaw<uint8_t>(Obj);
91  case FirstByte::Str16:
92  Obj.Kind = Type::String;
93  return readRaw<uint16_t>(Obj);
94  case FirstByte::Str32:
95  Obj.Kind = Type::String;
96  return readRaw<uint32_t>(Obj);
97  case FirstByte::Bin8:
98  Obj.Kind = Type::Binary;
99  return readRaw<uint8_t>(Obj);
100  case FirstByte::Bin16:
101  Obj.Kind = Type::Binary;
102  return readRaw<uint16_t>(Obj);
103  case FirstByte::Bin32:
104  Obj.Kind = Type::Binary;
105  return readRaw<uint32_t>(Obj);
106  case FirstByte::Array16:
107  Obj.Kind = Type::Array;
108  return readLength<uint16_t>(Obj);
109  case FirstByte::Array32:
110  Obj.Kind = Type::Array;
111  return readLength<uint32_t>(Obj);
112  case FirstByte::Map16:
113  Obj.Kind = Type::Map;
114  return readLength<uint16_t>(Obj);
115  case FirstByte::Map32:
116  Obj.Kind = Type::Map;
117  return readLength<uint32_t>(Obj);
118  case FirstByte::FixExt1:
119  Obj.Kind = Type::Extension;
120  return createExt(Obj, FixLen::Ext1);
121  case FirstByte::FixExt2:
122  Obj.Kind = Type::Extension;
123  return createExt(Obj, FixLen::Ext2);
124  case FirstByte::FixExt4:
125  Obj.Kind = Type::Extension;
126  return createExt(Obj, FixLen::Ext4);
127  case FirstByte::FixExt8:
128  Obj.Kind = Type::Extension;
129  return createExt(Obj, FixLen::Ext8);
130  case FirstByte::FixExt16:
131  Obj.Kind = Type::Extension;
132  return createExt(Obj, FixLen::Ext16);
133  case FirstByte::Ext8:
134  Obj.Kind = Type::Extension;
135  return readExt<uint8_t>(Obj);
136  case FirstByte::Ext16:
137  Obj.Kind = Type::Extension;
138  return readExt<uint16_t>(Obj);
139  case FirstByte::Ext32:
140  Obj.Kind = Type::Extension;
141  return readExt<uint32_t>(Obj);
142  }
143 
144  if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
145  Obj.Kind = Type::Int;
146  int8_t I;
147  static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
148  memcpy(&I, &FB, sizeof(FB));
149  Obj.Int = I;
150  return true;
151  }
152 
153  if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
154  Obj.Kind = Type::UInt;
155  Obj.UInt = FB;
156  return true;
157  }
158 
159  if ((FB & FixBitsMask::String) == FixBits::String) {
160  Obj.Kind = Type::String;
161  uint8_t Size = FB & ~FixBitsMask::String;
162  return createRaw(Obj, Size);
163  }
164 
165  if ((FB & FixBitsMask::Array) == FixBits::Array) {
166  Obj.Kind = Type::Array;
167  Obj.Length = FB & ~FixBitsMask::Array;
168  return true;
169  }
170 
171  if ((FB & FixBitsMask::Map) == FixBits::Map) {
172  Obj.Kind = Type::Map;
173  Obj.Length = FB & ~FixBitsMask::Map;
174  return true;
175  }
176 
177  return make_error<StringError>(
178  "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
179 }
180 
181 template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
182  if (sizeof(T) > remainingSpace())
183  return make_error<StringError>(
184  "Invalid Raw with insufficient payload",
185  std::make_error_code(std::errc::invalid_argument));
186  T Size = endian::read<T, Endianness>(Current);
187  Current += sizeof(T);
188  return createRaw(Obj, Size);
189 }
190 
191 template <class T> Expected<bool> Reader::readInt(Object &Obj) {
192  if (sizeof(T) > remainingSpace())
193  return make_error<StringError>(
194  "Invalid Int with insufficient payload",
195  std::make_error_code(std::errc::invalid_argument));
196  Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
197  Current += sizeof(T);
198  return true;
199 }
200 
201 template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
202  if (sizeof(T) > remainingSpace())
203  return make_error<StringError>(
204  "Invalid Int with insufficient payload",
205  std::make_error_code(std::errc::invalid_argument));
206  Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
207  Current += sizeof(T);
208  return true;
209 }
210 
211 template <class T> Expected<bool> Reader::readLength(Object &Obj) {
212  if (sizeof(T) > remainingSpace())
213  return make_error<StringError>(
214  "Invalid Map/Array with invalid length",
215  std::make_error_code(std::errc::invalid_argument));
216  Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
217  Current += sizeof(T);
218  return true;
219 }
220 
221 template <class T> Expected<bool> Reader::readExt(Object &Obj) {
222  if (sizeof(T) > remainingSpace())
223  return make_error<StringError>(
224  "Invalid Ext with invalid length",
225  std::make_error_code(std::errc::invalid_argument));
226  T Size = endian::read<T, Endianness>(Current);
227  Current += sizeof(T);
228  return createExt(Obj, Size);
229 }
230 
231 Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
232  if (Size > remainingSpace())
233  return make_error<StringError>(
234  "Invalid Raw with insufficient payload",
235  std::make_error_code(std::errc::invalid_argument));
236  Obj.Raw = StringRef(Current, Size);
237  Current += Size;
238  return true;
239 }
240 
241 Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
242  if (Current == End)
243  return make_error<StringError>(
244  "Invalid Ext with no type",
245  std::make_error_code(std::errc::invalid_argument));
246  Obj.Extension.Type = *Current++;
247  if (Size > remainingSpace())
248  return make_error<StringError>(
249  "Invalid Ext with insufficient payload",
250  std::make_error_code(std::errc::invalid_argument));
251  Obj.Extension.Bytes = StringRef(Current, Size);
252  Current += Size;
253  return true;
254 }
ExtensionType Extension
Value for Type::Extension.
Definition: MsgPackReader.h:91
Expected< bool > read(Object &Obj)
Read one object from the input buffer, advancing past it.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
float BitsToFloat(uint32_t Bits)
This function takes a 32-bit integer and returns the bit equivalent float.
Definition: MathExtras.h:632
std::error_code make_error_code(BitcodeError E)
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
MessagePack object, represented as a tagged union of C++ types.
Definition: MsgPackReader.h:75
Reads MessagePack objects from memory, one at a time.
Definition: MsgPackReader.h:98
double Float
Value for Type::Float.
Definition: MsgPackReader.h:85
This is a MessagePack reader.
double BitsToDouble(uint64_t Bits)
This function takes a 64-bit integer and returns the bit equivalent double.
Definition: MathExtras.h:624
int8_t Type
User-defined extension type.
Definition: MsgPackReader.h:65
StringRef Raw
Value for Type::String and Type::Binary.
Definition: MsgPackReader.h:87
#define I(x, y, z)
Definition: MD5.cpp:58
int64_t Int
Value for Type::Int.
Definition: MsgPackReader.h:79
uint32_t Size
Definition: Profile.cpp:46
This file contains constants used for implementing MessagePack support.
StringRef Bytes
Raw bytes of the extension object.
Definition: MsgPackReader.h:67
bool Bool
Value for Type::Boolean.
Definition: MsgPackReader.h:83
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
uint64_t UInt
Value for Type::Uint.
Definition: MsgPackReader.h:81
size_t Length
Value for Type::Array and Type::Map.
Definition: MsgPackReader.h:89
Reader(MemoryBufferRef InputBuffer)
Construct a reader, keeping a reference to the InputBuffer.