Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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"
14
#include "llvm/Support/Alignment.h"
15
#include "llvm/Support/BinaryStreamArray.h"
16
#include "llvm/Support/BinaryStreamRef.h"
17
#include "llvm/Support/ConvertUTF.h"
18
#include "llvm/Support/Endian.h"
19
#include "llvm/Support/Error.h"
20
#include <type_traits>
21
 
22
namespace 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.
29
class BinaryStreamReader {
30
public:
31
  BinaryStreamReader() = default;
32
  explicit BinaryStreamReader(BinaryStreamRef Ref);
33
  explicit BinaryStreamReader(BinaryStream &Stream);
34
  explicit BinaryStreamReader(ArrayRef<uint8_t> Data,
35
                              llvm::support::endianness Endian);
36
  explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
37
 
38
  BinaryStreamReader(const BinaryStreamReader &Other) = default;
39
 
40
  BinaryStreamReader &operator=(const BinaryStreamReader &Other) = default;
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.
50
  Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
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.
59
  Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
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
 
72
    ArrayRef<uint8_t> Bytes;
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.
96
  Error readULEB128(uint64_t &Dest);
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.
110
  Error readCString(StringRef &Dest);
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.
117
  Error readWideString(ArrayRef<UTF16> &Dest);
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.
125
  Error readFixedString(StringRef &Dest, uint32_t Length);
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.
133
  Error readStreamRef(BinaryStreamRef &Ref);
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.
142
  Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
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.
151
  Error readSubstream(BinarySubstreamRef &Ref, uint32_t Length);
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>(
189
          stream_error_code::invalid_array_size);
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>
210
  Error readArray(VarStreamArray<T, U> &Array, uint32_t Size,
211
                  uint32_t Skew = 0) {
212
    BinaryStreamRef S;
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>
228
  Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
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>(
236
          stream_error_code::invalid_array_size);
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
 
264
  Error padToAlignment(uint32_t Align);
265
 
266
  std::pair<BinaryStreamReader, BinaryStreamReader>
267
  split(uint64_t Offset) const;
268
 
269
private:
270
  BinaryStreamRef Stream;
271
  uint64_t Offset = 0;
272
};
273
} // namespace llvm
274
 
275
#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H