LLVM 20.0.0git
BinaryStreamReader.h
Go to the documentation of this file.
1//===- BinaryStreamReader.h - Reads objects from a binary stream *- 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#ifndef LLVM_SUPPORT_BINARYSTREAMREADER_H
10#define LLVM_SUPPORT_BINARYSTREAMREADER_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/StringRef.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/Error.h"
20#include <type_traits>
21
22namespace llvm {
23
24/// Provides read only access to a subclass of `BinaryStream`. Provides
25/// bounds checking and helpers for writing certain common data types such as
26/// null-terminated strings, integers in various flavors of endianness, etc.
27/// Can be subclassed to provide reading of custom datatypes, although no
28/// are overridable.
30public:
31 BinaryStreamReader() = default;
33 explicit BinaryStreamReader(BinaryStream &Stream);
36
38
40
41 virtual ~BinaryStreamReader() = default;
42
43 /// Read as much as possible from the underlying string at the current offset
44 /// without invoking a copy, and set \p Buffer to the resulting data slice.
45 /// Updates the stream's offset to point after the newly read data.
46 ///
47 /// \returns a success error code if the data was successfully read, otherwise
48 /// returns an appropriate error code.
50
51 /// Read \p Size bytes from the underlying stream at the current offset and
52 /// and set \p Buffer to the resulting data slice. Whether a copy occurs
53 /// depends on the implementation of the underlying stream. Updates the
54 /// stream's offset to point after the newly read data.
55 ///
56 /// \returns a success error code if the data was successfully read, otherwise
57 /// returns an appropriate error code.
59
60 /// Read an integer of the specified endianness into \p Dest and update the
61 /// stream's offset. The data is always copied from the stream's underlying
62 /// buffer into \p Dest. Updates the stream's offset to point after the newly
63 /// read data.
64 ///
65 /// \returns a success error code if the data was successfully read, otherwise
66 /// returns an appropriate error code.
67 template <typename T> Error readInteger(T &Dest) {
68 static_assert(std::is_integral_v<T>,
69 "Cannot call readInteger with non-integral value!");
70
72 if (auto EC = readBytes(Bytes, sizeof(T)))
73 return EC;
74
75 Dest = llvm::support::endian::read<T>(Bytes.data(), Stream.getEndian());
76 return Error::success();
77 }
78
79 /// Similar to readInteger.
80 template <typename T> Error readEnum(T &Dest) {
81 static_assert(std::is_enum<T>::value,
82 "Cannot call readEnum with non-enum value!");
83 std::underlying_type_t<T> N;
84 if (auto EC = readInteger(N))
85 return EC;
86 Dest = static_cast<T>(N);
87 return Error::success();
88 }
89
90 /// Read an unsigned LEB128 encoded value.
91 ///
92 /// \returns a success error code if the data was successfully read, otherwise
93 /// returns an appropriate error code.
95
96 /// Read a signed LEB128 encoded value.
97 ///
98 /// \returns a success error code if the data was successfully read, otherwise
99 /// returns an appropriate error code.
100 Error readSLEB128(int64_t &Dest);
101
102 /// Read a null terminated string from \p Dest. Whether a copy occurs depends
103 /// on the implementation of the underlying stream. Updates the stream's
104 /// offset to point after the newly read data.
105 ///
106 /// \returns a success error code if the data was successfully read, otherwise
107 /// returns an appropriate error code.
109
110 /// Similar to readCString, however read a null-terminated UTF16 string
111 /// instead.
112 ///
113 /// \returns a success error code if the data was successfully read, otherwise
114 /// returns an appropriate error code.
116
117 /// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
118 /// on the implementation of the underlying stream. Updates the stream's
119 /// offset to point after the newly read data.
120 ///
121 /// \returns a success error code if the data was successfully read, otherwise
122 /// returns an appropriate error code.
124
125 /// Read the entire remainder of the underlying stream into \p Ref. This is
126 /// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
127 /// stream's offset to point to the end of the stream. Never causes a copy.
128 ///
129 /// \returns a success error code if the data was successfully read, otherwise
130 /// returns an appropriate error code.
132
133 /// Read \p Length bytes from the underlying stream into \p Ref. This is
134 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
135 /// Updates the stream's offset to point after the newly read object. Never
136 /// causes a copy.
137 ///
138 /// \returns a success error code if the data was successfully read, otherwise
139 /// returns an appropriate error code.
141
142 /// Read \p Length bytes from the underlying stream into \p Ref. This is
143 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
144 /// Updates the stream's offset to point after the newly read object. Never
145 /// causes a copy.
146 ///
147 /// \returns a success error code if the data was successfully read, otherwise
148 /// returns an appropriate error code.
150
151 /// Get a pointer to an object of type T from the underlying stream, as if by
152 /// memcpy, and store the result into \p Dest. It is up to the caller to
153 /// ensure that objects of type T can be safely treated in this manner.
154 /// Updates the stream's offset to point after the newly read object. Whether
155 /// a copy occurs depends upon the implementation of the underlying
156 /// stream.
157 ///
158 /// \returns a success error code if the data was successfully read, otherwise
159 /// returns an appropriate error code.
160 template <typename T> Error readObject(const T *&Dest) {
161 ArrayRef<uint8_t> Buffer;
162 if (auto EC = readBytes(Buffer, sizeof(T)))
163 return EC;
164 Dest = reinterpret_cast<const T *>(Buffer.data());
165 return Error::success();
166 }
167
168 /// Get a reference to a \p NumElements element array of objects of type T
169 /// from the underlying stream as if by memcpy, and store the resulting array
170 /// slice into \p array. It is up to the caller to ensure that objects of
171 /// type T can be safely treated in this manner. Updates the stream's offset
172 /// to point after the newly read object. Whether a copy occurs depends upon
173 /// the implementation of the underlying stream.
174 ///
175 /// \returns a success error code if the data was successfully read, otherwise
176 /// returns an appropriate error code.
177 template <typename T>
178 Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
179 ArrayRef<uint8_t> Bytes;
180 if (NumElements == 0) {
181 Array = ArrayRef<T>();
182 return Error::success();
183 }
184
185 if (NumElements > UINT32_MAX / sizeof(T))
186 return make_error<BinaryStreamError>(
188
189 if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
190 return EC;
191
192 assert(isAddrAligned(Align::Of<T>(), Bytes.data()) &&
193 "Reading at invalid alignment!");
194
195 Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
196 return Error::success();
197 }
198
199 /// Read a VarStreamArray of size \p Size bytes and store the result into
200 /// \p Array. Updates the stream's offset to point after the newly read
201 /// array. Never causes a copy (although iterating the elements of the
202 /// VarStreamArray may, depending upon the implementation of the underlying
203 /// stream).
204 ///
205 /// \returns a success error code if the data was successfully read, otherwise
206 /// returns an appropriate error code.
207 template <typename T, typename U>
209 uint32_t Skew = 0) {
211 if (auto EC = readStreamRef(S, Size))
212 return EC;
213 Array.setUnderlyingStream(S, Skew);
214 return Error::success();
215 }
216
217 /// Read a FixedStreamArray of \p NumItems elements and store the result into
218 /// \p Array. Updates the stream's offset to point after the newly read
219 /// array. Never causes a copy (although iterating the elements of the
220 /// FixedStreamArray may, depending upon the implementation of the underlying
221 /// stream).
222 ///
223 /// \returns a success error code if the data was successfully read, otherwise
224 /// returns an appropriate error code.
225 template <typename T>
227 if (NumItems == 0) {
228 Array = FixedStreamArray<T>();
229 return Error::success();
230 }
231
232 if (NumItems > UINT32_MAX / sizeof(T))
233 return make_error<BinaryStreamError>(
235
236 BinaryStreamRef View;
237 if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
238 return EC;
239
240 Array = FixedStreamArray<T>(View);
241 return Error::success();
242 }
243
244 bool empty() const { return bytesRemaining() == 0; }
245 void setOffset(uint64_t Off) { Offset = Off; }
246 uint64_t getOffset() const { return Offset; }
247 uint64_t getLength() const { return Stream.getLength(); }
248 uint64_t bytesRemaining() const { return getLength() - getOffset(); }
249
250 /// Advance the stream's offset by \p Amount bytes.
251 ///
252 /// \returns a success error code if at least \p Amount bytes remain in the
253 /// stream, otherwise returns an appropriate error code.
254 Error skip(uint64_t Amount);
255
256 /// Examine the next byte of the underlying stream without advancing the
257 /// stream's offset. If the stream is empty the behavior is undefined.
258 ///
259 /// \returns the next byte in the stream.
260 uint8_t peek() const;
261
263
264 std::pair<BinaryStreamReader, BinaryStreamReader>
265 split(uint64_t Offset) const;
266
267private:
268 BinaryStreamRef Stream;
269 uint64_t Offset = 0;
270};
271} // namespace llvm
272
273#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H
Lightweight arrays that are backed by an arbitrary BinaryStream.
uint64_t Size
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
endianness Endian
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
const T * data() const
Definition: ArrayRef.h:162
Provides read only access to a subclass of BinaryStream.
Error readStreamRef(BinaryStreamRef &Ref)
Read the entire remainder of the underlying stream into Ref.
BinaryStreamReader & operator=(const BinaryStreamReader &Other)=default
Error readObject(const T *&Dest)
Get a pointer to an object of type T from the underlying stream, as if by memcpy, and store the resul...
Error readCString(StringRef &Dest)
Read a null terminated string from Dest.
Error readArray(FixedStreamArray< T > &Array, uint32_t NumItems)
Read a FixedStreamArray of NumItems elements and store the result into Array.
Error readBytes(ArrayRef< uint8_t > &Buffer, uint32_t Size)
Read Size bytes from the underlying stream at the current offset and and set Buffer to the resulting ...
uint8_t peek() const
Examine the next byte of the underlying stream without advancing the stream's offset.
Error readWideString(ArrayRef< UTF16 > &Dest)
Similar to readCString, however read a null-terminated UTF16 string instead.
Error readSubstream(BinarySubstreamRef &Ref, uint32_t Length)
Read Length bytes from the underlying stream into Ref.
Error readEnum(T &Dest)
Similar to readInteger.
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
uint64_t bytesRemaining() const
Error readSLEB128(int64_t &Dest)
Read a signed LEB128 encoded value.
Error readLongestContiguousChunk(ArrayRef< uint8_t > &Buffer)
Read as much as possible from the underlying string at the current offset without invoking a copy,...
Error padToAlignment(uint32_t Align)
Error readFixedString(StringRef &Dest, uint32_t Length)
Read a Length byte string into Dest.
std::pair< BinaryStreamReader, BinaryStreamReader > split(uint64_t Offset) const
void setOffset(uint64_t Off)
Error readArray(ArrayRef< T > &Array, uint32_t NumElements)
Get a reference to a NumElements element array of objects of type T from the underlying stream as if ...
Error readULEB128(uint64_t &Dest)
Read an unsigned LEB128 encoded value.
Error skip(uint64_t Amount)
Advance the stream's offset by Amount bytes.
BinaryStreamReader(const BinaryStreamReader &Other)=default
Error readArray(VarStreamArray< T, U > &Array, uint32_t Size, uint32_t Skew=0)
Read a VarStreamArray of size Size bytes and store the result into Array.
virtual ~BinaryStreamReader()=default
llvm::endianness getEndian() const
uint64_t getLength() const
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:34
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:480
@ Ref
The access may reference the value stored in memory.
@ Other
Any other memory.
endianness
Definition: bit.h:70
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
Definition: Alignment.h:150
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39