LLVM 17.0.0git
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"
18
19using namespace llvm;
20using namespace llvm::support;
21using namespace msgpack;
22
24 : InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
25 End(InputBuffer.getBufferEnd()) {}
26
27Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
28
30 if (Current == End)
31 return false;
32
33 uint8_t FB = static_cast<uint8_t>(*Current++);
34
35 switch (FB) {
36 case FirstByte::Nil:
37 Obj.Kind = Type::Nil;
38 return true;
39 case FirstByte::True:
40 Obj.Kind = Type::Boolean;
41 Obj.Bool = true;
42 return true;
43 case FirstByte::False:
44 Obj.Kind = Type::Boolean;
45 Obj.Bool = false;
46 return true;
47 case FirstByte::Int8:
48 Obj.Kind = Type::Int;
49 return readInt<int8_t>(Obj);
50 case FirstByte::Int16:
51 Obj.Kind = Type::Int;
52 return readInt<int16_t>(Obj);
53 case FirstByte::Int32:
54 Obj.Kind = Type::Int;
55 return readInt<int32_t>(Obj);
56 case FirstByte::Int64:
57 Obj.Kind = Type::Int;
58 return readInt<int64_t>(Obj);
59 case FirstByte::UInt8:
60 Obj.Kind = Type::UInt;
61 return readUInt<uint8_t>(Obj);
62 case FirstByte::UInt16:
63 Obj.Kind = Type::UInt;
64 return readUInt<uint16_t>(Obj);
65 case FirstByte::UInt32:
66 Obj.Kind = Type::UInt;
67 return readUInt<uint32_t>(Obj);
68 case FirstByte::UInt64:
69 Obj.Kind = Type::UInt;
70 return readUInt<uint64_t>(Obj);
71 case FirstByte::Float32:
72 Obj.Kind = Type::Float;
73 if (sizeof(float) > remainingSpace())
74 return make_error<StringError>(
75 "Invalid Float32 with insufficient payload",
76 std::make_error_code(std::errc::invalid_argument));
77 Obj.Float = BitsToFloat(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 = BitsToDouble(endian::read<uint64_t, Endianness>(Current));
87 Current += sizeof(double);
88 return true;
89 case FirstByte::Str8:
90 Obj.Kind = Type::String;
91 return readRaw<uint8_t>(Obj);
92 case FirstByte::Str16:
93 Obj.Kind = Type::String;
94 return readRaw<uint16_t>(Obj);
95 case FirstByte::Str32:
96 Obj.Kind = Type::String;
97 return readRaw<uint32_t>(Obj);
98 case FirstByte::Bin8:
99 Obj.Kind = Type::Binary;
100 return readRaw<uint8_t>(Obj);
101 case FirstByte::Bin16:
102 Obj.Kind = Type::Binary;
103 return readRaw<uint16_t>(Obj);
104 case FirstByte::Bin32:
105 Obj.Kind = Type::Binary;
106 return readRaw<uint32_t>(Obj);
107 case FirstByte::Array16:
108 Obj.Kind = Type::Array;
109 return readLength<uint16_t>(Obj);
110 case FirstByte::Array32:
111 Obj.Kind = Type::Array;
112 return readLength<uint32_t>(Obj);
113 case FirstByte::Map16:
114 Obj.Kind = Type::Map;
115 return readLength<uint16_t>(Obj);
116 case FirstByte::Map32:
117 Obj.Kind = Type::Map;
118 return readLength<uint32_t>(Obj);
119 case FirstByte::FixExt1:
120 Obj.Kind = Type::Extension;
121 return createExt(Obj, FixLen::Ext1);
122 case FirstByte::FixExt2:
123 Obj.Kind = Type::Extension;
124 return createExt(Obj, FixLen::Ext2);
125 case FirstByte::FixExt4:
126 Obj.Kind = Type::Extension;
127 return createExt(Obj, FixLen::Ext4);
128 case FirstByte::FixExt8:
129 Obj.Kind = Type::Extension;
130 return createExt(Obj, FixLen::Ext8);
131 case FirstByte::FixExt16:
132 Obj.Kind = Type::Extension;
133 return createExt(Obj, FixLen::Ext16);
134 case FirstByte::Ext8:
135 Obj.Kind = Type::Extension;
136 return readExt<uint8_t>(Obj);
137 case FirstByte::Ext16:
138 Obj.Kind = Type::Extension;
139 return readExt<uint16_t>(Obj);
140 case FirstByte::Ext32:
141 Obj.Kind = Type::Extension;
142 return readExt<uint32_t>(Obj);
143 }
144
145 if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
146 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 Obj.Int = I;
151 return true;
152 }
153
154 if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
155 Obj.Kind = Type::UInt;
156 Obj.UInt = FB;
157 return true;
158 }
159
160 if ((FB & FixBitsMask::String) == FixBits::String) {
161 Obj.Kind = Type::String;
162 uint8_t Size = FB & ~FixBitsMask::String;
163 return createRaw(Obj, Size);
164 }
165
166 if ((FB & FixBitsMask::Array) == FixBits::Array) {
167 Obj.Kind = Type::Array;
168 Obj.Length = FB & ~FixBitsMask::Array;
169 return true;
170 }
171
172 if ((FB & FixBitsMask::Map) == FixBits::Map) {
173 Obj.Kind = Type::Map;
174 Obj.Length = FB & ~FixBitsMask::Map;
175 return true;
176 }
177
178 return make_error<StringError>(
179 "Invalid first byte", std::make_error_code(std::errc::invalid_argument));
180}
181
182template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
183 if (sizeof(T) > remainingSpace())
184 return make_error<StringError>(
185 "Invalid Raw with insufficient payload",
186 std::make_error_code(std::errc::invalid_argument));
187 T Size = endian::read<T, Endianness>(Current);
188 Current += sizeof(T);
189 return createRaw(Obj, Size);
190}
191
192template <class T> Expected<bool> Reader::readInt(Object &Obj) {
193 if (sizeof(T) > remainingSpace())
194 return make_error<StringError>(
195 "Invalid Int with insufficient payload",
196 std::make_error_code(std::errc::invalid_argument));
197 Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
198 Current += sizeof(T);
199 return true;
200}
201
202template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
203 if (sizeof(T) > remainingSpace())
204 return make_error<StringError>(
205 "Invalid Int with insufficient payload",
206 std::make_error_code(std::errc::invalid_argument));
207 Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
208 Current += sizeof(T);
209 return true;
210}
211
212template <class T> Expected<bool> Reader::readLength(Object &Obj) {
213 if (sizeof(T) > remainingSpace())
214 return make_error<StringError>(
215 "Invalid Map/Array with invalid length",
216 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 return true;
220}
221
222template <class T> Expected<bool> Reader::readExt(Object &Obj) {
223 if (sizeof(T) > remainingSpace())
224 return make_error<StringError>(
225 "Invalid Ext with invalid length",
226 std::make_error_code(std::errc::invalid_argument));
227 T Size = endian::read<T, Endianness>(Current);
228 Current += sizeof(T);
229 return createExt(Obj, Size);
230}
231
232Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
233 if (Size > remainingSpace())
234 return make_error<StringError>(
235 "Invalid Raw with insufficient payload",
236 std::make_error_code(std::errc::invalid_argument));
237 Obj.Raw = StringRef(Current, Size);
238 Current += Size;
239 return true;
240}
241
242Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
243 if (Current == End)
244 return make_error<StringError>(
245 "Invalid Ext with no type",
246 std::make_error_code(std::errc::invalid_argument));
247 Obj.Extension.Type = *Current++;
248 if (Size > remainingSpace())
249 return make_error<StringError>(
250 "Invalid Ext with insufficient payload",
251 std::make_error_code(std::errc::invalid_argument));
252 Obj.Extension.Bytes = StringRef(Current, Size);
253 Current += Size;
254 return true;
255}
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains constants used for implementing MessagePack support.
Tagged union holding either a T or a Error.
Definition: Error.h:470
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Reads MessagePack objects from memory, one at a time.
Definition: MsgPackReader.h:99
Reader(MemoryBufferRef InputBuffer)
Construct a reader, keeping a reference to the InputBuffer.
Expected< bool > read(Object &Obj)
Read one object from the input buffer, advancing past it.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
float BitsToFloat(uint32_t Bits)
This function takes a 32-bit integer and returns the bit equivalent float.
Definition: MathExtras.h:403
double BitsToDouble(uint64_t Bits)
This function takes a 64-bit integer and returns the bit equivalent double.
Definition: MathExtras.h:397
int8_t Type
User-defined extension type.
Definition: MsgPackReader.h:66
StringRef Bytes
Raw bytes of the extension object.
Definition: MsgPackReader.h:68
MessagePack object, represented as a tagged union of C++ types.
Definition: MsgPackReader.h:76
int64_t Int
Value for Type::Int.
Definition: MsgPackReader.h:80
double Float
Value for Type::Float.
Definition: MsgPackReader.h:86
StringRef Raw
Value for Type::String and Type::Binary.
Definition: MsgPackReader.h:88
uint64_t UInt
Value for Type::Uint.
Definition: MsgPackReader.h:82
bool Bool
Value for Type::Boolean.
Definition: MsgPackReader.h:84
ExtensionType Extension
Value for Type::Extension.
Definition: MsgPackReader.h:92
size_t Length
Value for Type::Array and Type::Map.
Definition: MsgPackReader.h:90