Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/BinaryFormat/MsgPackReader.cpp
35232 views
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
14
#include "llvm/BinaryFormat/MsgPackReader.h"
15
#include "llvm/BinaryFormat/MsgPack.h"
16
#include "llvm/Support/Endian.h"
17
#include "llvm/Support/MathExtras.h"
18
19
using namespace llvm;
20
using namespace llvm::support;
21
using namespace msgpack;
22
23
Reader::Reader(MemoryBufferRef InputBuffer)
24
: InputBuffer(InputBuffer), Current(InputBuffer.getBufferStart()),
25
End(InputBuffer.getBufferEnd()) {}
26
27
Reader::Reader(StringRef Input) : Reader({Input, "MsgPack"}) {}
28
29
Expected<bool> Reader::read(Object &Obj) {
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 =
78
llvm::bit_cast<float>(endian::read<uint32_t, Endianness>(Current));
79
Current += sizeof(float);
80
return true;
81
case FirstByte::Float64:
82
Obj.Kind = Type::Float;
83
if (sizeof(double) > remainingSpace())
84
return make_error<StringError>(
85
"Invalid Float64 with insufficient payload",
86
std::make_error_code(std::errc::invalid_argument));
87
Obj.Float =
88
llvm::bit_cast<double>(endian::read<uint64_t, Endianness>(Current));
89
Current += sizeof(double);
90
return true;
91
case FirstByte::Str8:
92
Obj.Kind = Type::String;
93
return readRaw<uint8_t>(Obj);
94
case FirstByte::Str16:
95
Obj.Kind = Type::String;
96
return readRaw<uint16_t>(Obj);
97
case FirstByte::Str32:
98
Obj.Kind = Type::String;
99
return readRaw<uint32_t>(Obj);
100
case FirstByte::Bin8:
101
Obj.Kind = Type::Binary;
102
return readRaw<uint8_t>(Obj);
103
case FirstByte::Bin16:
104
Obj.Kind = Type::Binary;
105
return readRaw<uint16_t>(Obj);
106
case FirstByte::Bin32:
107
Obj.Kind = Type::Binary;
108
return readRaw<uint32_t>(Obj);
109
case FirstByte::Array16:
110
Obj.Kind = Type::Array;
111
return readLength<uint16_t>(Obj);
112
case FirstByte::Array32:
113
Obj.Kind = Type::Array;
114
return readLength<uint32_t>(Obj);
115
case FirstByte::Map16:
116
Obj.Kind = Type::Map;
117
return readLength<uint16_t>(Obj);
118
case FirstByte::Map32:
119
Obj.Kind = Type::Map;
120
return readLength<uint32_t>(Obj);
121
case FirstByte::FixExt1:
122
Obj.Kind = Type::Extension;
123
return createExt(Obj, FixLen::Ext1);
124
case FirstByte::FixExt2:
125
Obj.Kind = Type::Extension;
126
return createExt(Obj, FixLen::Ext2);
127
case FirstByte::FixExt4:
128
Obj.Kind = Type::Extension;
129
return createExt(Obj, FixLen::Ext4);
130
case FirstByte::FixExt8:
131
Obj.Kind = Type::Extension;
132
return createExt(Obj, FixLen::Ext8);
133
case FirstByte::FixExt16:
134
Obj.Kind = Type::Extension;
135
return createExt(Obj, FixLen::Ext16);
136
case FirstByte::Ext8:
137
Obj.Kind = Type::Extension;
138
return readExt<uint8_t>(Obj);
139
case FirstByte::Ext16:
140
Obj.Kind = Type::Extension;
141
return readExt<uint16_t>(Obj);
142
case FirstByte::Ext32:
143
Obj.Kind = Type::Extension;
144
return readExt<uint32_t>(Obj);
145
}
146
147
if ((FB & FixBitsMask::NegativeInt) == FixBits::NegativeInt) {
148
Obj.Kind = Type::Int;
149
int8_t I;
150
static_assert(sizeof(I) == sizeof(FB), "Unexpected type sizes");
151
memcpy(&I, &FB, sizeof(FB));
152
Obj.Int = I;
153
return true;
154
}
155
156
if ((FB & FixBitsMask::PositiveInt) == FixBits::PositiveInt) {
157
Obj.Kind = Type::UInt;
158
Obj.UInt = FB;
159
return true;
160
}
161
162
if ((FB & FixBitsMask::String) == FixBits::String) {
163
Obj.Kind = Type::String;
164
uint8_t Size = FB & ~FixBitsMask::String;
165
return createRaw(Obj, Size);
166
}
167
168
if ((FB & FixBitsMask::Array) == FixBits::Array) {
169
Obj.Kind = Type::Array;
170
Obj.Length = FB & ~FixBitsMask::Array;
171
return true;
172
}
173
174
if ((FB & FixBitsMask::Map) == FixBits::Map) {
175
Obj.Kind = Type::Map;
176
Obj.Length = FB & ~FixBitsMask::Map;
177
return true;
178
}
179
180
return make_error<StringError>(
181
"Invalid first byte", std::make_error_code(std::errc::invalid_argument));
182
}
183
184
template <class T> Expected<bool> Reader::readRaw(Object &Obj) {
185
if (sizeof(T) > remainingSpace())
186
return make_error<StringError>(
187
"Invalid Raw with insufficient payload",
188
std::make_error_code(std::errc::invalid_argument));
189
T Size = endian::read<T, Endianness>(Current);
190
Current += sizeof(T);
191
return createRaw(Obj, Size);
192
}
193
194
template <class T> Expected<bool> Reader::readInt(Object &Obj) {
195
if (sizeof(T) > remainingSpace())
196
return make_error<StringError>(
197
"Invalid Int with insufficient payload",
198
std::make_error_code(std::errc::invalid_argument));
199
Obj.Int = static_cast<int64_t>(endian::read<T, Endianness>(Current));
200
Current += sizeof(T);
201
return true;
202
}
203
204
template <class T> Expected<bool> Reader::readUInt(Object &Obj) {
205
if (sizeof(T) > remainingSpace())
206
return make_error<StringError>(
207
"Invalid Int with insufficient payload",
208
std::make_error_code(std::errc::invalid_argument));
209
Obj.UInt = static_cast<uint64_t>(endian::read<T, Endianness>(Current));
210
Current += sizeof(T);
211
return true;
212
}
213
214
template <class T> Expected<bool> Reader::readLength(Object &Obj) {
215
if (sizeof(T) > remainingSpace())
216
return make_error<StringError>(
217
"Invalid Map/Array with invalid length",
218
std::make_error_code(std::errc::invalid_argument));
219
Obj.Length = static_cast<size_t>(endian::read<T, Endianness>(Current));
220
Current += sizeof(T);
221
return true;
222
}
223
224
template <class T> Expected<bool> Reader::readExt(Object &Obj) {
225
if (sizeof(T) > remainingSpace())
226
return make_error<StringError>(
227
"Invalid Ext with invalid length",
228
std::make_error_code(std::errc::invalid_argument));
229
T Size = endian::read<T, Endianness>(Current);
230
Current += sizeof(T);
231
return createExt(Obj, Size);
232
}
233
234
Expected<bool> Reader::createRaw(Object &Obj, uint32_t Size) {
235
if (Size > remainingSpace())
236
return make_error<StringError>(
237
"Invalid Raw with insufficient payload",
238
std::make_error_code(std::errc::invalid_argument));
239
Obj.Raw = StringRef(Current, Size);
240
Current += Size;
241
return true;
242
}
243
244
Expected<bool> Reader::createExt(Object &Obj, uint32_t Size) {
245
if (Current == End)
246
return make_error<StringError>(
247
"Invalid Ext with no type",
248
std::make_error_code(std::errc::invalid_argument));
249
Obj.Extension.Type = *Current++;
250
if (Size > remainingSpace())
251
return make_error<StringError>(
252
"Invalid Ext with insufficient payload",
253
std::make_error_code(std::errc::invalid_argument));
254
Obj.Extension.Bytes = StringRef(Current, Size);
255
Current += Size;
256
return true;
257
}
258
259