Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Support/BinaryStreamReader.cpp
35232 views
1
//===- BinaryStreamReader.cpp - Reads objects from a binary stream --------===//
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
#include "llvm/Support/BinaryStreamReader.h"
10
11
#include "llvm/Support/BinaryStreamError.h"
12
#include "llvm/Support/BinaryStreamRef.h"
13
#include "llvm/Support/LEB128.h"
14
15
using namespace llvm;
16
17
BinaryStreamReader::BinaryStreamReader(BinaryStreamRef Ref) : Stream(Ref) {}
18
19
BinaryStreamReader::BinaryStreamReader(BinaryStream &Stream) : Stream(Stream) {}
20
21
BinaryStreamReader::BinaryStreamReader(ArrayRef<uint8_t> Data,
22
endianness Endian)
23
: Stream(Data, Endian) {}
24
25
BinaryStreamReader::BinaryStreamReader(StringRef Data, endianness Endian)
26
: Stream(Data, Endian) {}
27
28
Error BinaryStreamReader::readLongestContiguousChunk(
29
ArrayRef<uint8_t> &Buffer) {
30
if (auto EC = Stream.readLongestContiguousChunk(Offset, Buffer))
31
return EC;
32
Offset += Buffer.size();
33
return Error::success();
34
}
35
36
Error BinaryStreamReader::readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size) {
37
if (auto EC = Stream.readBytes(Offset, Size, Buffer))
38
return EC;
39
Offset += Size;
40
return Error::success();
41
}
42
43
Error BinaryStreamReader::readULEB128(uint64_t &Dest) {
44
SmallVector<uint8_t, 10> EncodedBytes;
45
ArrayRef<uint8_t> NextByte;
46
47
// Copy the encoded ULEB into the buffer.
48
do {
49
if (auto Err = readBytes(NextByte, 1))
50
return Err;
51
EncodedBytes.push_back(NextByte[0]);
52
} while (NextByte[0] & 0x80);
53
54
Dest = decodeULEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
55
return Error::success();
56
}
57
58
Error BinaryStreamReader::readSLEB128(int64_t &Dest) {
59
SmallVector<uint8_t, 10> EncodedBytes;
60
ArrayRef<uint8_t> NextByte;
61
62
// Copy the encoded ULEB into the buffer.
63
do {
64
if (auto Err = readBytes(NextByte, 1))
65
return Err;
66
EncodedBytes.push_back(NextByte[0]);
67
} while (NextByte[0] & 0x80);
68
69
Dest = decodeSLEB128(EncodedBytes.begin(), nullptr, EncodedBytes.end());
70
return Error::success();
71
}
72
73
Error BinaryStreamReader::readCString(StringRef &Dest) {
74
uint64_t OriginalOffset = getOffset();
75
uint64_t FoundOffset = 0;
76
while (true) {
77
uint64_t ThisOffset = getOffset();
78
ArrayRef<uint8_t> Buffer;
79
if (auto EC = readLongestContiguousChunk(Buffer))
80
return EC;
81
StringRef S(reinterpret_cast<const char *>(Buffer.begin()), Buffer.size());
82
size_t Pos = S.find_first_of('\0');
83
if (LLVM_LIKELY(Pos != StringRef::npos)) {
84
FoundOffset = Pos + ThisOffset;
85
break;
86
}
87
}
88
assert(FoundOffset >= OriginalOffset);
89
90
setOffset(OriginalOffset);
91
size_t Length = FoundOffset - OriginalOffset;
92
93
if (auto EC = readFixedString(Dest, Length))
94
return EC;
95
96
// Now set the offset back to after the null terminator.
97
setOffset(FoundOffset + 1);
98
return Error::success();
99
}
100
101
Error BinaryStreamReader::readWideString(ArrayRef<UTF16> &Dest) {
102
uint64_t Length = 0;
103
uint64_t OriginalOffset = getOffset();
104
const UTF16 *C;
105
while (true) {
106
if (auto EC = readObject(C))
107
return EC;
108
if (*C == 0x0000)
109
break;
110
++Length;
111
}
112
uint64_t NewOffset = getOffset();
113
setOffset(OriginalOffset);
114
115
if (auto EC = readArray(Dest, Length))
116
return EC;
117
setOffset(NewOffset);
118
return Error::success();
119
}
120
121
Error BinaryStreamReader::readFixedString(StringRef &Dest, uint32_t Length) {
122
ArrayRef<uint8_t> Bytes;
123
if (auto EC = readBytes(Bytes, Length))
124
return EC;
125
Dest = StringRef(reinterpret_cast<const char *>(Bytes.begin()), Bytes.size());
126
return Error::success();
127
}
128
129
Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref) {
130
return readStreamRef(Ref, bytesRemaining());
131
}
132
133
Error BinaryStreamReader::readStreamRef(BinaryStreamRef &Ref, uint32_t Length) {
134
if (bytesRemaining() < Length)
135
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
136
Ref = Stream.slice(Offset, Length);
137
Offset += Length;
138
return Error::success();
139
}
140
141
Error BinaryStreamReader::readSubstream(BinarySubstreamRef &Ref,
142
uint32_t Length) {
143
Ref.Offset = getOffset();
144
return readStreamRef(Ref.StreamData, Length);
145
}
146
147
Error BinaryStreamReader::skip(uint64_t Amount) {
148
if (Amount > bytesRemaining())
149
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
150
Offset += Amount;
151
return Error::success();
152
}
153
154
Error BinaryStreamReader::padToAlignment(uint32_t Align) {
155
uint32_t NewOffset = alignTo(Offset, Align);
156
return skip(NewOffset - Offset);
157
}
158
159
uint8_t BinaryStreamReader::peek() const {
160
ArrayRef<uint8_t> Buffer;
161
auto EC = Stream.readBytes(Offset, 1, Buffer);
162
assert(!EC && "Cannot peek an empty buffer!");
163
llvm::consumeError(std::move(EC));
164
return Buffer[0];
165
}
166
167
std::pair<BinaryStreamReader, BinaryStreamReader>
168
BinaryStreamReader::split(uint64_t Off) const {
169
assert(getLength() >= Off);
170
171
BinaryStreamRef First = Stream.drop_front(Offset);
172
173
BinaryStreamRef Second = First.drop_front(Off);
174
First = First.keep_front(Off);
175
BinaryStreamReader W1{First};
176
BinaryStreamReader W2{Second};
177
return std::make_pair(W1, W2);
178
}
179
180