LLVM  10.0.0svn
BinaryByteStream.h
Go to the documentation of this file.
1 //===- BinaryByteStream.h ---------------------------------------*- 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 // A BinaryStream which stores data in a single continguous memory buffer.
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
11 #define LLVM_SUPPORT_BINARYBYTESTREAM_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Error.h"
20 #include <algorithm>
21 #include <cstdint>
22 #include <cstring>
23 #include <memory>
24 
25 namespace llvm {
26 
27 /// An implementation of BinaryStream which holds its entire data set
28 /// in a single contiguous buffer. BinaryByteStream guarantees that no read
29 /// operation will ever incur a copy. Note that BinaryByteStream does not
30 /// own the underlying buffer.
32 public:
33  BinaryByteStream() = default;
35  : Endian(Endian), Data(Data) {}
37  : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
38 
39  llvm::support::endianness getEndian() const override { return Endian; }
40 
42  ArrayRef<uint8_t> &Buffer) override {
43  if (auto EC = checkOffsetForRead(Offset, Size))
44  return EC;
45  Buffer = Data.slice(Offset, Size);
46  return Error::success();
47  }
48 
50  ArrayRef<uint8_t> &Buffer) override {
51  if (auto EC = checkOffsetForRead(Offset, 1))
52  return EC;
53  Buffer = Data.slice(Offset);
54  return Error::success();
55  }
56 
57  uint32_t getLength() override { return Data.size(); }
58 
59  ArrayRef<uint8_t> data() const { return Data; }
60 
61  StringRef str() const {
62  const char *CharData = reinterpret_cast<const char *>(Data.data());
63  return StringRef(CharData, Data.size());
64  }
65 
66 protected:
69 };
70 
71 /// An implementation of BinaryStream whose data is backed by an llvm
72 /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
73 /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
74 /// will never cause a copy.
76 public:
77  MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
79  : BinaryByteStream(Buffer->getBuffer(), Endian),
80  MemBuffer(std::move(Buffer)) {}
81 
82  std::unique_ptr<MemoryBuffer> MemBuffer;
83 };
84 
85 /// An implementation of BinaryStream which holds its entire data set
86 /// in a single contiguous buffer. As with BinaryByteStream, the mutable
87 /// version also guarantees that no read operation will ever incur a copy,
88 /// and similarly it does not own the underlying buffer.
90 public:
91  MutableBinaryByteStream() = default;
94  : Data(Data), ImmutableStream(Data, Endian) {}
95 
97  return ImmutableStream.getEndian();
98  }
99 
101  ArrayRef<uint8_t> &Buffer) override {
102  return ImmutableStream.readBytes(Offset, Size, Buffer);
103  }
104 
106  ArrayRef<uint8_t> &Buffer) override {
107  return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
108  }
109 
110  uint32_t getLength() override { return ImmutableStream.getLength(); }
111 
113  if (Buffer.empty())
114  return Error::success();
115 
116  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
117  return EC;
118 
119  uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
120  ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
121  return Error::success();
122  }
123 
124  Error commit() override { return Error::success(); }
125 
126  MutableArrayRef<uint8_t> data() const { return Data; }
127 
128 private:
130  BinaryByteStream ImmutableStream;
131 };
132 
133 /// An implementation of WritableBinaryStream which can write at its end
134 /// causing the underlying data to grow. This class owns the underlying data.
136  std::vector<uint8_t> Data;
138 
139 public:
140  AppendingBinaryByteStream() = default;
142  : Endian(Endian) {}
143 
144  void clear() { Data.clear(); }
145 
146  llvm::support::endianness getEndian() const override { return Endian; }
147 
149  ArrayRef<uint8_t> &Buffer) override {
150  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
151  return EC;
152 
153  Buffer = makeArrayRef(Data).slice(Offset, Size);
154  return Error::success();
155  }
156 
158  Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
159  }
160 
162  ArrayRef<uint8_t> &Buffer) override {
163  if (auto EC = checkOffsetForWrite(Offset, 1))
164  return EC;
165 
166  Buffer = makeArrayRef(Data).slice(Offset);
167  return Error::success();
168  }
169 
170  uint32_t getLength() override { return Data.size(); }
171 
173  if (Buffer.empty())
174  return Error::success();
175 
176  // This is well-defined for any case except where offset is strictly
177  // greater than the current length. If offset is equal to the current
178  // length, we can still grow. If offset is beyond the current length, we
179  // would have to decide how to deal with the intermediate uninitialized
180  // bytes. So we punt on that case for simplicity and just say it's an
181  // error.
182  if (Offset > getLength())
183  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
184 
185  uint32_t RequiredSize = Offset + Buffer.size();
186  if (RequiredSize > Data.size())
187  Data.resize(RequiredSize);
188 
189  ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
190  return Error::success();
191  }
192 
193  Error commit() override { return Error::success(); }
194 
195  /// Return the properties of this stream.
196  virtual BinaryStreamFlags getFlags() const override {
197  return BSF_Write | BSF_Append;
198  }
199 
201 };
202 
203 /// An implementation of WritableBinaryStream backed by an llvm
204 /// FileOutputBuffer.
206 private:
207  class StreamImpl : public MutableBinaryByteStream {
208  public:
209  StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
212  MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
213  Buffer->getBufferEnd()),
214  Endian),
215  FileBuffer(std::move(Buffer)) {}
216 
217  Error commit() override {
218  if (FileBuffer->commit())
219  return make_error<BinaryStreamError>(
221  return Error::success();
222  }
223 
224  /// Returns a pointer to the start of the buffer.
225  uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
226 
227  /// Returns a pointer to the end of the buffer.
228  uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
229 
230  private:
231  std::unique_ptr<FileOutputBuffer> FileBuffer;
232  };
233 
234 public:
235  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
237  : Impl(std::move(Buffer), Endian) {}
238 
240  return Impl.getEndian();
241  }
242 
244  ArrayRef<uint8_t> &Buffer) override {
245  return Impl.readBytes(Offset, Size, Buffer);
246  }
247 
249  ArrayRef<uint8_t> &Buffer) override {
250  return Impl.readLongestContiguousChunk(Offset, Buffer);
251  }
252 
253  uint32_t getLength() override { return Impl.getLength(); }
254 
256  return Impl.writeBytes(Offset, Data);
257  }
258 
259  Error commit() override { return Impl.commit(); }
260 
261  /// Returns a pointer to the start of the buffer.
262  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
263 
264  /// Returns a pointer to the end of the buffer.
265  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
266 
267 private:
268  StreamImpl Impl;
269 };
270 
271 } // end namespace llvm
272 
273 #endif // LLVM_SUPPORT_BYTESTREAM_H
std::unique_ptr< MemoryBuffer > MemBuffer
uint32_t getLength() override
Return the number of bytes of data in this stream.
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MutableArrayRef< uint8_t > data() const
iterator begin() const
Definition: ArrayRef.h:136
AppendingBinaryByteStream(llvm::support::endianness Endian)
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
uint8_t * getBufferEnd() const
Returns a pointer to the end of the buffer.
llvm::support::endianness getEndian() const override
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
void insert(uint32_t Offset, ArrayRef< uint8_t > Bytes)
uint32_t getLength() override
Return the number of bytes of data in this stream.
Definition: BitVector.h:937
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:450
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize)
Definition: BinaryStream.h:59
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
ArrayRef< uint8_t > data() const
llvm::support::endianness getEndian() const override
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
MutableBinaryByteStream(MutableArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Error commit() override
For buffered streams, commits changes to the backing store.
Error commit() override
For buffered streams, commits changes to the backing store.
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:35
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Data) override
Attempt to write the given bytes into the stream at the desired offset.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
ArrayRef< uint8_t > Data
uint8_t * getBufferStart() const
Returns a pointer to the start of the buffer.
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
An implementation of BinaryStream whose data is backed by an llvm MemoryBuffer object.
const T * data() const
Definition: ArrayRef.h:145
An implementation of WritableBinaryStream which can write at its end causing the underlying data to g...
llvm::support::endianness getEndian() const override
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
MutableArrayRef< uint8_t > data()
llvm::support::endianness getEndian() const override
Error commit() override
For buffered streams, commits changes to the backing store.
iterator end() const
Definition: ArrayRef.h:137
BinaryStreamFlags
Definition: BinaryStream.h:21
BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
llvm::support::endianness Endian
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array...
Definition: ArrayRef.h:178
StringRef str() const
BinaryByteStream(ArrayRef< uint8_t > Data, llvm::support::endianness Endian)
virtual BinaryStreamFlags getFlags() const override
Return the properties of this stream.
uint32_t getLength() override
Return the number of bytes of data in this stream.
uint32_t Size
Definition: Profile.cpp:46
MemoryBufferByteStream(std::unique_ptr< MemoryBuffer > Buffer, llvm::support::endianness Endian)
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream and a number of bytes, attempt to read the bytes and set the output A...
FileBufferByteStream(std::unique_ptr< FileOutputBuffer > Buffer, llvm::support::endianness Endian)
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
uint32_t getLength() override
Return the number of bytes of data in this stream.
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73