LLVM  8.0.1
BinaryByteStream.h
Go to the documentation of this file.
1 //===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //===----------------------------------------------------------------------===//
8 // A BinaryStream which stores data in a single continguous memory buffer.
9 //===----------------------------------------------------------------------===//
10 
11 #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
12 #define LLVM_SUPPORT_BINARYBYTESTREAM_H
13 
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Error.h"
21 #include <algorithm>
22 #include <cstdint>
23 #include <cstring>
24 #include <memory>
25 
26 namespace llvm {
27 
28 /// An implementation of BinaryStream which holds its entire data set
29 /// in a single contiguous buffer. BinaryByteStream guarantees that no read
30 /// operation will ever incur a copy. Note that BinaryByteStream does not
31 /// own the underlying buffer.
33 public:
34  BinaryByteStream() = default;
36  : Endian(Endian), Data(Data) {}
38  : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
39 
40  llvm::support::endianness getEndian() const override { return Endian; }
41 
43  ArrayRef<uint8_t> &Buffer) override {
44  if (auto EC = checkOffsetForRead(Offset, Size))
45  return EC;
46  Buffer = Data.slice(Offset, Size);
47  return Error::success();
48  }
49 
51  ArrayRef<uint8_t> &Buffer) override {
52  if (auto EC = checkOffsetForRead(Offset, 1))
53  return EC;
54  Buffer = Data.slice(Offset);
55  return Error::success();
56  }
57 
58  uint32_t getLength() override { return Data.size(); }
59 
60  ArrayRef<uint8_t> data() const { return Data; }
61 
62  StringRef str() const {
63  const char *CharData = reinterpret_cast<const char *>(Data.data());
64  return StringRef(CharData, Data.size());
65  }
66 
67 protected:
70 };
71 
72 /// An implementation of BinaryStream whose data is backed by an llvm
73 /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
74 /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
75 /// will never cause a copy.
77 public:
78  MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
80  : BinaryByteStream(Buffer->getBuffer(), Endian),
81  MemBuffer(std::move(Buffer)) {}
82 
83  std::unique_ptr<MemoryBuffer> MemBuffer;
84 };
85 
86 /// An implementation of BinaryStream which holds its entire data set
87 /// in a single contiguous buffer. As with BinaryByteStream, the mutable
88 /// version also guarantees that no read operation will ever incur a copy,
89 /// and similarly it does not own the underlying buffer.
91 public:
92  MutableBinaryByteStream() = default;
95  : Data(Data), ImmutableStream(Data, Endian) {}
96 
98  return ImmutableStream.getEndian();
99  }
100 
102  ArrayRef<uint8_t> &Buffer) override {
103  return ImmutableStream.readBytes(Offset, Size, Buffer);
104  }
105 
107  ArrayRef<uint8_t> &Buffer) override {
108  return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
109  }
110 
111  uint32_t getLength() override { return ImmutableStream.getLength(); }
112 
114  if (Buffer.empty())
115  return Error::success();
116 
117  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
118  return EC;
119 
120  uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
121  ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
122  return Error::success();
123  }
124 
125  Error commit() override { return Error::success(); }
126 
127  MutableArrayRef<uint8_t> data() const { return Data; }
128 
129 private:
131  BinaryByteStream ImmutableStream;
132 };
133 
134 /// An implementation of WritableBinaryStream which can write at its end
135 /// causing the underlying data to grow. This class owns the underlying data.
137  std::vector<uint8_t> Data;
139 
140 public:
141  AppendingBinaryByteStream() = default;
143  : Endian(Endian) {}
144 
145  void clear() { Data.clear(); }
146 
147  llvm::support::endianness getEndian() const override { return Endian; }
148 
150  ArrayRef<uint8_t> &Buffer) override {
151  if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
152  return EC;
153 
154  Buffer = makeArrayRef(Data).slice(Offset, Size);
155  return Error::success();
156  }
157 
159  Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
160  }
161 
163  ArrayRef<uint8_t> &Buffer) override {
164  if (auto EC = checkOffsetForWrite(Offset, 1))
165  return EC;
166 
167  Buffer = makeArrayRef(Data).slice(Offset);
168  return Error::success();
169  }
170 
171  uint32_t getLength() override { return Data.size(); }
172 
174  if (Buffer.empty())
175  return Error::success();
176 
177  // This is well-defined for any case except where offset is strictly
178  // greater than the current length. If offset is equal to the current
179  // length, we can still grow. If offset is beyond the current length, we
180  // would have to decide how to deal with the intermediate uninitialized
181  // bytes. So we punt on that case for simplicity and just say it's an
182  // error.
183  if (Offset > getLength())
184  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
185 
186  uint32_t RequiredSize = Offset + Buffer.size();
187  if (RequiredSize > Data.size())
188  Data.resize(RequiredSize);
189 
190  ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
191  return Error::success();
192  }
193 
194  Error commit() override { return Error::success(); }
195 
196  /// Return the properties of this stream.
197  virtual BinaryStreamFlags getFlags() const override {
198  return BSF_Write | BSF_Append;
199  }
200 
202 };
203 
204 /// An implementation of WritableBinaryStream backed by an llvm
205 /// FileOutputBuffer.
207 private:
208  class StreamImpl : public MutableBinaryByteStream {
209  public:
210  StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
213  MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
214  Buffer->getBufferEnd()),
215  Endian),
216  FileBuffer(std::move(Buffer)) {}
217 
218  Error commit() override {
219  if (FileBuffer->commit())
220  return make_error<BinaryStreamError>(
222  return Error::success();
223  }
224 
225  /// Returns a pointer to the start of the buffer.
226  uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
227 
228  /// Returns a pointer to the end of the buffer.
229  uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
230 
231  private:
232  std::unique_ptr<FileOutputBuffer> FileBuffer;
233  };
234 
235 public:
236  FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
238  : Impl(std::move(Buffer), Endian) {}
239 
241  return Impl.getEndian();
242  }
243 
245  ArrayRef<uint8_t> &Buffer) override {
246  return Impl.readBytes(Offset, Size, Buffer);
247  }
248 
250  ArrayRef<uint8_t> &Buffer) override {
251  return Impl.readLongestContiguousChunk(Offset, Buffer);
252  }
253 
254  uint32_t getLength() override { return Impl.getLength(); }
255 
257  return Impl.writeBytes(Offset, Data);
258  }
259 
260  Error commit() override { return Impl.commit(); }
261 
262  /// Returns a pointer to the start of the buffer.
263  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
264 
265  /// Returns a pointer to the end of the buffer.
266  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
267 
268 private:
269  StreamImpl Impl;
270 };
271 
272 } // end namespace llvm
273 
274 #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:24
MutableArrayRef< uint8_t > data() const
iterator begin() const
Definition: ArrayRef.h:137
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:938
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:451
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:60
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:36
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:149
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:146
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:327
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:138
BinaryStreamFlags
Definition: BinaryStream.h:22
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:179
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:47
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:158
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
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:144
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:74