LLVM 18.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);
37
39
41
42 virtual ~BinaryStreamReader() = default;
43
44 /// Read as much as possible from the underlying string at the current offset
45 /// without invoking a copy, and set \p Buffer to the resulting data slice.
46 /// Updates the stream's offset to point after the newly read data.
47 ///
48 /// \returns a success error code if the data was successfully read, otherwise
49 /// returns an appropriate error code.
51
52 /// Read \p Size bytes from the underlying stream at the current offset and
53 /// and set \p Buffer to the resulting data slice. Whether a copy occurs
54 /// depends on the implementation of the underlying stream. Updates the
55 /// stream's offset to point after the newly read data.
56 ///
57 /// \returns a success error code if the data was successfully read, otherwise
58 /// returns an appropriate error code.
60
61 /// Read an integer of the specified endianness into \p Dest and update the
62 /// stream's offset. The data is always copied from the stream's underlying
63 /// buffer into \p Dest. Updates the stream's offset to point after the newly
64 /// read data.
65 ///
66 /// \returns a success error code if the data was successfully read, otherwise
67 /// returns an appropriate error code.
68 template <typename T> Error readInteger(T &Dest) {
69 static_assert(std::is_integral_v<T>,
70 "Cannot call readInteger with non-integral value!");
71
73 if (auto EC = readBytes(Bytes, sizeof(T)))
74 return EC;
75
76 Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
77 Bytes.data(), Stream.getEndian());
78 return Error::success();
79 }
80
81 /// Similar to readInteger.
82 template <typename T> Error readEnum(T &Dest) {
83 static_assert(std::is_enum<T>::value,
84 "Cannot call readEnum with non-enum value!");
85 std::underlying_type_t<T> N;
86 if (auto EC = readInteger(N))
87 return EC;
88 Dest = static_cast<T>(N);
89 return Error::success();
90 }
91
92 /// Read an unsigned LEB128 encoded value.
93 ///
94 /// \returns a success error code if the data was successfully read, otherwise
95 /// returns an appropriate error code.
97
98 /// Read a signed LEB128 encoded value.
99 ///
100 /// \returns a success error code if the data was successfully read, otherwise
101 /// returns an appropriate error code.
102 Error readSLEB128(int64_t &Dest);
103
104 /// Read a null terminated string from \p Dest. Whether a copy occurs depends
105 /// on the implementation of the underlying stream. Updates the stream's
106 /// offset to point after the newly read data.
107 ///
108 /// \returns a success error code if the data was successfully read, otherwise
109 /// returns an appropriate error code.
111
112 /// Similar to readCString, however read a null-terminated UTF16 string
113 /// instead.
114 ///
115 /// \returns a success error code if the data was successfully read, otherwise
116 /// returns an appropriate error code.
118
119 /// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
120 /// on the implementation of the underlying stream. Updates the stream's
121 /// offset to point after the newly read data.
122 ///
123 /// \returns a success error code if the data was successfully read, otherwise
124 /// returns an appropriate error code.
126
127 /// Read the entire remainder of the underlying stream into \p Ref. This is
128 /// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
129 /// stream's offset to point to the end of the stream. Never causes a copy.
130 ///
131 /// \returns a success error code if the data was successfully read, otherwise
132 /// returns an appropriate error code.
134
135 /// Read \p Length bytes from the underlying stream into \p Ref. This is
136 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
137 /// Updates the stream's offset to point after the newly read object. Never
138 /// causes a copy.
139 ///
140 /// \returns a success error code if the data was successfully read, otherwise
141 /// returns an appropriate error code.
143
144 /// Read \p Length bytes from the underlying stream into \p Ref. This is
145 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
146 /// Updates the stream's offset to point after the newly read object. Never
147 /// causes a copy.
148 ///
149 /// \returns a success error code if the data was successfully read, otherwise
150 /// returns an appropriate error code.
152
153 /// Get a pointer to an object of type T from the underlying stream, as if by
154 /// memcpy, and store the result into \p Dest. It is up to the caller to
155 /// ensure that objects of type T can be safely treated in this manner.
156 /// Updates the stream's offset to point after the newly read object. Whether
157 /// a copy occurs depends upon the implementation of the underlying
158 /// stream.
159 ///
160 /// \returns a success error code if the data was successfully read, otherwise
161 /// returns an appropriate error code.
162 template <typename T> Error readObject(const T *&Dest) {
163 ArrayRef<uint8_t> Buffer;
164 if (auto EC = readBytes(Buffer, sizeof(T)))
165 return EC;
166 Dest = reinterpret_cast<const T *>(Buffer.data());
167 return Error::success();
168 }
169
170 /// Get a reference to a \p NumElements element array of objects of type T
171 /// from the underlying stream as if by memcpy, and store the resulting array
172 /// slice into \p array. It is up to the caller to ensure that objects of
173 /// type T can be safely treated in this manner. Updates the stream's offset
174 /// to point after the newly read object. Whether a copy occurs depends upon
175 /// the implementation of the underlying stream.
176 ///
177 /// \returns a success error code if the data was successfully read, otherwise
178 /// returns an appropriate error code.
179 template <typename T>
180 Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
181 ArrayRef<uint8_t> Bytes;
182 if (NumElements == 0) {
183 Array = ArrayRef<T>();
184 return Error::success();
185 }
186
187 if (NumElements > UINT32_MAX / sizeof(T))
188 return make_error<BinaryStreamError>(
190
191 if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
192 return EC;
193
194 assert(isAddrAligned(Align::Of<T>(), Bytes.data()) &&
195 "Reading at invalid alignment!");
196
197 Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
198 return Error::success();
199 }
200
201 /// Read a VarStreamArray of size \p Size bytes and store the result into
202 /// \p Array. Updates the stream's offset to point after the newly read
203 /// array. Never causes a copy (although iterating the elements of the
204 /// VarStreamArray may, depending upon the implementation of the underlying
205 /// stream).
206 ///
207 /// \returns a success error code if the data was successfully read, otherwise
208 /// returns an appropriate error code.
209 template <typename T, typename U>
211 uint32_t Skew = 0) {
213 if (auto EC = readStreamRef(S, Size))
214 return EC;
215 Array.setUnderlyingStream(S, Skew);
216 return Error::success();
217 }
218
219 /// Read a FixedStreamArray of \p NumItems elements and store the result into
220 /// \p Array. Updates the stream's offset to point after the newly read
221 /// array. Never causes a copy (although iterating the elements of the
222 /// FixedStreamArray may, depending upon the implementation of the underlying
223 /// stream).
224 ///
225 /// \returns a success error code if the data was successfully read, otherwise
226 /// returns an appropriate error code.
227 template <typename T>
229 if (NumItems == 0) {
230 Array = FixedStreamArray<T>();
231 return Error::success();
232 }
233
234 if (NumItems > UINT32_MAX / sizeof(T))
235 return make_error<BinaryStreamError>(
237
238 BinaryStreamRef View;
239 if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
240 return EC;
241
242 Array = FixedStreamArray<T>(View);
243 return Error::success();
244 }
245
246 bool empty() const { return bytesRemaining() == 0; }
247 void setOffset(uint64_t Off) { Offset = Off; }
248 uint64_t getOffset() const { return Offset; }
249 uint64_t getLength() const { return Stream.getLength(); }
250 uint64_t bytesRemaining() const { return getLength() - getOffset(); }
251
252 /// Advance the stream's offset by \p Amount bytes.
253 ///
254 /// \returns a success error code if at least \p Amount bytes remain in the
255 /// stream, otherwise returns an appropriate error code.
256 Error skip(uint64_t Amount);
257
258 /// Examine the next byte of the underlying stream without advancing the
259 /// stream's offset. If the stream is empty the behavior is undefined.
260 ///
261 /// \returns the next byte in the stream.
262 uint8_t peek() const;
263
265
266 std::pair<BinaryStreamReader, BinaryStreamReader>
267 split(uint64_t Offset) const;
268
269private:
270 BinaryStreamRef Stream;
271 uint64_t Offset = 0;
272};
273} // namespace llvm
274
275#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::support::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:35
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
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:440
@ Ref
The access may reference the value stored in memory.
@ Other
Any other memory.
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