Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Support/BinaryStreamReader.h
Line
Count
Source (jump to first uncovered line)
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/STLExtras.h"
14
#include "llvm/Support/BinaryStreamArray.h"
15
#include "llvm/Support/BinaryStreamRef.h"
16
#include "llvm/Support/ConvertUTF.h"
17
#include "llvm/Support/Endian.h"
18
#include "llvm/Support/Error.h"
19
#include "llvm/Support/type_traits.h"
20
21
#include <string>
22
#include <type_traits>
23
24
namespace llvm {
25
26
/// Provides read only access to a subclass of `BinaryStream`.  Provides
27
/// bounds checking and helpers for writing certain common data types such as
28
/// null-terminated strings, integers in various flavors of endianness, etc.
29
/// Can be subclassed to provide reading of custom datatypes, although no
30
/// are overridable.
31
class BinaryStreamReader {
32
public:
33
  BinaryStreamReader() = default;
34
  explicit BinaryStreamReader(BinaryStreamRef Ref);
35
  explicit BinaryStreamReader(BinaryStream &Stream);
36
  explicit BinaryStreamReader(ArrayRef<uint8_t> Data,
37
                              llvm::support::endianness Endian);
38
  explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
39
40
  BinaryStreamReader(const BinaryStreamReader &Other)
41
5.00k
      : Stream(Other.Stream), Offset(Other.Offset) {}
42
43
  BinaryStreamReader &operator=(const BinaryStreamReader &Other) {
44
    Stream = Other.Stream;
45
    Offset = Other.Offset;
46
    return *this;
47
  }
48
49
74.4k
  virtual ~BinaryStreamReader() {}
50
51
  /// Read as much as possible from the underlying string at the current offset
52
  /// without invoking a copy, and set \p Buffer to the resulting data slice.
53
  /// Updates the stream's offset to point after the newly read data.
54
  ///
55
  /// \returns a success error code if the data was successfully read, otherwise
56
  /// returns an appropriate error code.
57
  Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
58
59
  /// Read \p Size bytes from the underlying stream at the current offset and
60
  /// and set \p Buffer to the resulting data slice.  Whether a copy occurs
61
  /// depends on the implementation of the underlying stream.  Updates the
62
  /// stream's offset to point after the newly read data.
63
  ///
64
  /// \returns a success error code if the data was successfully read, otherwise
65
  /// returns an appropriate error code.
66
  Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
67
68
  /// Read an integer of the specified endianness into \p Dest and update the
69
  /// stream's offset.  The data is always copied from the stream's underlying
70
  /// buffer into \p Dest. Updates the stream's offset to point after the newly
71
  /// read data.
72
  ///
73
  /// \returns a success error code if the data was successfully read, otherwise
74
  /// returns an appropriate error code.
75
218k
  template <typename T> Error readInteger(T &Dest) {
76
218k
    static_assert(std::is_integral<T>::value,
77
218k
                  "Cannot call readInteger with non-integral value!");
78
218k
79
218k
    ArrayRef<uint8_t> Bytes;
80
218k
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
218k
83
218k
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
218k
        Bytes.data(), Stream.getEndian());
85
218k
    return Error::success();
86
218k
  }
llvm::Error llvm::BinaryStreamReader::readInteger<unsigned short>(unsigned short&)
Line
Count
Source
75
134k
  template <typename T> Error readInteger(T &Dest) {
76
134k
    static_assert(std::is_integral<T>::value,
77
134k
                  "Cannot call readInteger with non-integral value!");
78
134k
79
134k
    ArrayRef<uint8_t> Bytes;
80
134k
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
134k
83
134k
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
134k
        Bytes.data(), Stream.getEndian());
85
134k
    return Error::success();
86
134k
  }
llvm::Error llvm::BinaryStreamReader::readInteger<unsigned int>(unsigned int&)
Line
Count
Source
75
74.6k
  template <typename T> Error readInteger(T &Dest) {
76
74.6k
    static_assert(std::is_integral<T>::value,
77
74.6k
                  "Cannot call readInteger with non-integral value!");
78
74.6k
79
74.6k
    ArrayRef<uint8_t> Bytes;
80
74.6k
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
74.6k
83
74.6k
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
74.6k
        Bytes.data(), Stream.getEndian());
85
74.6k
    return Error::success();
86
74.6k
  }
llvm::Error llvm::BinaryStreamReader::readInteger<unsigned char>(unsigned char&)
Line
Count
Source
75
7.15k
  template <typename T> Error readInteger(T &Dest) {
76
7.15k
    static_assert(std::is_integral<T>::value,
77
7.15k
                  "Cannot call readInteger with non-integral value!");
78
7.15k
79
7.15k
    ArrayRef<uint8_t> Bytes;
80
7.15k
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
7.15k
83
7.15k
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
7.15k
        Bytes.data(), Stream.getEndian());
85
7.15k
    return Error::success();
86
7.15k
  }
llvm::Error llvm::BinaryStreamReader::readInteger<signed char>(signed char&)
Line
Count
Source
75
4
  template <typename T> Error readInteger(T &Dest) {
76
4
    static_assert(std::is_integral<T>::value,
77
4
                  "Cannot call readInteger with non-integral value!");
78
4
79
4
    ArrayRef<uint8_t> Bytes;
80
4
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
4
83
4
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
4
        Bytes.data(), Stream.getEndian());
85
4
    return Error::success();
86
4
  }
llvm::Error llvm::BinaryStreamReader::readInteger<short>(short&)
Line
Count
Source
75
8
  template <typename T> Error readInteger(T &Dest) {
76
8
    static_assert(std::is_integral<T>::value,
77
8
                  "Cannot call readInteger with non-integral value!");
78
8
79
8
    ArrayRef<uint8_t> Bytes;
80
8
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
8
83
8
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
8
        Bytes.data(), Stream.getEndian());
85
8
    return Error::success();
86
8
  }
llvm::Error llvm::BinaryStreamReader::readInteger<int>(int&)
Line
Count
Source
75
2.66k
  template <typename T> Error readInteger(T &Dest) {
76
2.66k
    static_assert(std::is_integral<T>::value,
77
2.66k
                  "Cannot call readInteger with non-integral value!");
78
2.66k
79
2.66k
    ArrayRef<uint8_t> Bytes;
80
2.66k
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
2.66k
83
2.66k
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
2.66k
        Bytes.data(), Stream.getEndian());
85
2.66k
    return Error::success();
86
2.66k
  }
llvm::Error llvm::BinaryStreamReader::readInteger<long long>(long long&)
Line
Count
Source
75
20
  template <typename T> Error readInteger(T &Dest) {
76
20
    static_assert(std::is_integral<T>::value,
77
20
                  "Cannot call readInteger with non-integral value!");
78
20
79
20
    ArrayRef<uint8_t> Bytes;
80
20
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
20
83
20
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
20
        Bytes.data(), Stream.getEndian());
85
20
    return Error::success();
86
20
  }
llvm::Error llvm::BinaryStreamReader::readInteger<unsigned long long>(unsigned long long&)
Line
Count
Source
75
11
  template <typename T> Error readInteger(T &Dest) {
76
11
    static_assert(std::is_integral<T>::value,
77
11
                  "Cannot call readInteger with non-integral value!");
78
11
79
11
    ArrayRef<uint8_t> Bytes;
80
11
    if (auto EC = readBytes(Bytes, sizeof(T)))
81
0
      return EC;
82
11
83
11
    Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
84
11
        Bytes.data(), Stream.getEndian());
85
11
    return Error::success();
86
11
  }
87
88
  /// Similar to readInteger.
89
34.0k
  template <typename T> Error readEnum(T &Dest) {
90
34.0k
    static_assert(std::is_enum<T>::value,
91
34.0k
                  "Cannot call readEnum with non-enum value!");
92
34.0k
    typename std::underlying_type<T>::type N;
93
34.0k
    if (auto EC = readInteger(N))
94
0
      return EC;
95
34.0k
    Dest = static_cast<T>(N);
96
34.0k
    return Error::success();
97
34.0k
  }
98
99
  /// Read an unsigned LEB128 encoded value.
100
  ///
101
  /// \returns a success error code if the data was successfully read, otherwise
102
  /// returns an appropriate error code.
103
  Error readULEB128(uint64_t &Dest);
104
105
  /// Read a signed LEB128 encoded value.
106
  ///
107
  /// \returns a success error code if the data was successfully read, otherwise
108
  /// returns an appropriate error code.
109
  Error readSLEB128(int64_t &Dest);
110
111
  /// Read a null terminated string from \p Dest.  Whether a copy occurs depends
112
  /// on the implementation of the underlying stream.  Updates the stream's
113
  /// offset to point after the newly read data.
114
  ///
115
  /// \returns a success error code if the data was successfully read, otherwise
116
  /// returns an appropriate error code.
117
  Error readCString(StringRef &Dest);
118
119
  /// Similar to readCString, however read a null-terminated UTF16 string
120
  /// instead.
121
  ///
122
  /// \returns a success error code if the data was successfully read, otherwise
123
  /// returns an appropriate error code.
124
  Error readWideString(ArrayRef<UTF16> &Dest);
125
126
  /// Read a \p Length byte string into \p Dest.  Whether a copy occurs depends
127
  /// on the implementation of the underlying stream.  Updates the stream's
128
  /// offset to point after the newly read data.
129
  ///
130
  /// \returns a success error code if the data was successfully read, otherwise
131
  /// returns an appropriate error code.
132
  Error readFixedString(StringRef &Dest, uint32_t Length);
133
134
  /// Read the entire remainder of the underlying stream into \p Ref.  This is
135
  /// equivalent to calling getUnderlyingStream().slice(Offset).  Updates the
136
  /// stream's offset to point to the end of the stream.  Never causes a copy.
137
  ///
138
  /// \returns a success error code if the data was successfully read, otherwise
139
  /// returns an appropriate error code.
140
  Error readStreamRef(BinaryStreamRef &Ref);
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.
149
  Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
150
151
  /// Read \p Length bytes from the underlying stream into \p Stream.  This is
152
  /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
153
  /// Updates the stream's offset to point after the newly read object.  Never
154
  /// causes a copy.
155
  ///
156
  /// \returns a success error code if the data was successfully read, otherwise
157
  /// returns an appropriate error code.
158
  Error readSubstream(BinarySubstreamRef &Stream, uint32_t Size);
159
160
  /// Get a pointer to an object of type T from the underlying stream, as if by
161
  /// memcpy, and store the result into \p Dest.  It is up to the caller to
162
  /// ensure that objects of type T can be safely treated in this manner.
163
  /// Updates the stream's offset to point after the newly read object.  Whether
164
  /// a copy occurs depends upon the implementation of the underlying
165
  /// stream.
166
  ///
167
  /// \returns a success error code if the data was successfully read, otherwise
168
  /// returns an appropriate error code.
169
23.9k
  template <typename T> Error readObject(const T *&Dest) {
170
23.9k
    ArrayRef<uint8_t> Buffer;
171
23.9k
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
100
      return EC;
173
23.8k
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
23.8k
    return Error::success();
175
23.8k
  }
llvm::Error llvm::BinaryStreamReader::readObject<unsigned short>(unsigned short const*&)
Line
Count
Source
169
1.45k
  template <typename T> Error readObject(const T *&Dest) {
170
1.45k
    ArrayRef<uint8_t> Buffer;
171
1.45k
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
1.45k
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
1.45k
    return Error::success();
175
1.45k
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::object::coff_resource_dir_table>(llvm::object::coff_resource_dir_table const*&)
Line
Count
Source
169
131
  template <typename T> Error readObject(const T *&Dest) {
170
131
    ArrayRef<uint8_t> Buffer;
171
131
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
131
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
131
    return Error::success();
175
131
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::object::WinResHeaderPrefix>(llvm::object::WinResHeaderPrefix const*&)
Line
Count
Source
169
342
  template <typename T> Error readObject(const T *&Dest) {
170
342
    ArrayRef<uint8_t> Buffer;
171
342
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
342
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
342
    return Error::success();
175
342
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::object::WinResHeaderSuffix>(llvm::object::WinResHeaderSuffix const*&)
Line
Count
Source
169
342
  template <typename T> Error readObject(const T *&Dest) {
170
342
    ArrayRef<uint8_t> Buffer;
171
342
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
342
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
342
    return Error::success();
175
342
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::codeview::RecordPrefix>(llvm::codeview::RecordPrefix const*&)
Line
Count
Source
169
20.9k
  template <typename T> Error readObject(const T *&Dest) {
170
20.9k
    ArrayRef<uint8_t> Buffer;
171
20.9k
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
100
      return EC;
173
20.8k
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
20.8k
    return Error::success();
175
20.8k
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<unsigned short, (llvm::support::endianness)1, 1ul> const*&)
Line
Count
Source
169
166
  template <typename T> Error readObject(const T *&Dest) {
170
166
    ArrayRef<uint8_t> Buffer;
171
166
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
166
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
166
    return Error::success();
175
166
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<int, (llvm::support::endianness)1, 1ul> const*&)
Line
Count
Source
169
29
  template <typename T> Error readObject(const T *&Dest) {
170
29
    ArrayRef<uint8_t> Buffer;
171
29
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
29
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
29
    return Error::success();
175
29
  }
llvm::Error llvm::BinaryStreamReader::readObject<llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> >(llvm::support::detail::packed_endian_specific_integral<unsigned int, (llvm::support::endianness)1, 1ul> const*&)
Line
Count
Source
169
570
  template <typename T> Error readObject(const T *&Dest) {
170
570
    ArrayRef<uint8_t> Buffer;
171
570
    if (auto EC = readBytes(Buffer, sizeof(T)))
172
0
      return EC;
173
570
    Dest = reinterpret_cast<const T *>(Buffer.data());
174
570
    return Error::success();
175
570
  }
176
177
  /// Get a reference to a \p NumElements element array of objects of type T
178
  /// from the underlying stream as if by memcpy, and store the resulting array
179
  /// slice into \p array.  It is up to the caller to ensure that objects of
180
  /// type T can be safely treated in this manner.  Updates the stream's offset
181
  /// to point after the newly read object.  Whether a copy occurs depends upon
182
  /// the implementation of the underlying stream.
183
  ///
184
  /// \returns a success error code if the data was successfully read, otherwise
185
  /// returns an appropriate error code.
186
  template <typename T>
187
582
  Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
188
582
    ArrayRef<uint8_t> Bytes;
189
582
    if (NumElements == 0) {
190
1
      Array = ArrayRef<T>();
191
1
      return Error::success();
192
1
    }
193
581
194
581
    if (NumElements > UINT32_MAX / sizeof(T))
195
0
      return make_error<BinaryStreamError>(
196
0
          stream_error_code::invalid_array_size);
197
581
198
581
    if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
199
0
      return EC;
200
581
201
581
    assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
202
581
           "Reading at invalid alignment!");
203
581
204
581
    Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
205
581
    return Error::success();
206
581
  }
llvm::Error llvm::BinaryStreamReader::readArray<unsigned short>(llvm::ArrayRef<unsigned short>&, unsigned int)
Line
Count
Source
187
182
  Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
188
182
    ArrayRef<uint8_t> Bytes;
189
182
    if (NumElements == 0) {
190
0
      Array = ArrayRef<T>();
191
0
      return Error::success();
192
0
    }
193
182
194
182
    if (NumElements > UINT32_MAX / sizeof(T))
195
0
      return make_error<BinaryStreamError>(
196
0
          stream_error_code::invalid_array_size);
197
182
198
182
    if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
199
0
      return EC;
200
182
201
182
    assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
202
182
           "Reading at invalid alignment!");
203
182
204
182
    Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
205
182
    return Error::success();
206
182
  }
llvm::Error llvm::BinaryStreamReader::readArray<unsigned char>(llvm::ArrayRef<unsigned char>&, unsigned int)
Line
Count
Source
187
400
  Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
188
400
    ArrayRef<uint8_t> Bytes;
189
400
    if (NumElements == 0) {
190
1
      Array = ArrayRef<T>();
191
1
      return Error::success();
192
1
    }
193
399
194
399
    if (NumElements > UINT32_MAX / sizeof(T))
195
0
      return make_error<BinaryStreamError>(
196
0
          stream_error_code::invalid_array_size);
197
399
198
399
    if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
199
0
      return EC;
200
399
201
399
    assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
202
399
           "Reading at invalid alignment!");
203
399
204
399
    Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
205
399
    return Error::success();
206
399
  }
207
208
  /// Read a VarStreamArray of size \p Size bytes and store the result into
209
  /// \p Array.  Updates the stream's offset to point after the newly read
210
  /// array.  Never causes a copy (although iterating the elements of the
211
  /// VarStreamArray may, depending upon the implementation of the underlying
212
  /// stream).
213
  ///
214
  /// \returns a success error code if the data was successfully read, otherwise
215
  /// returns an appropriate error code.
216
  template <typename T, typename U>
217
  Error readArray(VarStreamArray<T, U> &Array, uint32_t Size,
218
                  uint32_t Skew = 0) {
219
    BinaryStreamRef S;
220
    if (auto EC = readStreamRef(S, Size))
221
      return EC;
222
    Array.setUnderlyingStream(S, Skew);
223
    return Error::success();
224
  }
225
226
  /// Read a FixedStreamArray of \p NumItems elements and store the result into
227
  /// \p Array.  Updates the stream's offset to point after the newly read
228
  /// array.  Never causes a copy (although iterating the elements of the
229
  /// FixedStreamArray may, depending upon the implementation of the underlying
230
  /// stream).
231
  ///
232
  /// \returns a success error code if the data was successfully read, otherwise
233
  /// returns an appropriate error code.
234
  template <typename T>
235
452
  Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
236
452
    if (NumItems == 0) {
237
0
      Array = FixedStreamArray<T>();
238
0
      return Error::success();
239
0
    }
240
452
241
452
    if (NumItems > UINT32_MAX / sizeof(T))
242
0
      return make_error<BinaryStreamError>(
243
0
          stream_error_code::invalid_array_size);
244
452
245
452
    BinaryStreamRef View;
246
452
    if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
247
0
      return EC;
248
452
249
452
    Array = FixedStreamArray<T>(View);
250
452
    return Error::success();
251
452
  }
252
253
37.9k
  bool empty() const { return bytesRemaining() == 0; }
254
198k
  void setOffset(uint32_t Off) { Offset = Off; }
255
378k
  uint32_t getOffset() const { return Offset; }
256
111k
  uint32_t getLength() const { return Stream.getLength(); }
257
110k
  uint32_t bytesRemaining() const { return getLength() - getOffset(); }
258
259
  /// Advance the stream's offset by \p Amount bytes.
260
  ///
261
  /// \returns a success error code if at least \p Amount bytes remain in the
262
  /// stream, otherwise returns an appropriate error code.
263
  Error skip(uint32_t Amount);
264
265
  /// Examine the next byte of the underlying stream without advancing the
266
  /// stream's offset.  If the stream is empty the behavior is undefined.
267
  ///
268
  /// \returns the next byte in the stream.
269
  uint8_t peek() const;
270
271
  Error padToAlignment(uint32_t Align);
272
273
  std::pair<BinaryStreamReader, BinaryStreamReader>
274
  split(uint32_t Offset) const;
275
276
private:
277
  BinaryStreamRef Stream;
278
  uint32_t Offset = 0;
279
};
280
} // namespace llvm
281
282
#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H