LLVM 17.0.0git
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 <cstdint>
21#include <cstring>
22#include <memory>
23
24namespace llvm {
25
26/// An implementation of BinaryStream which holds its entire data set
27/// in a single contiguous buffer. BinaryByteStream guarantees that no read
28/// operation will ever incur a copy. Note that BinaryByteStream does not
29/// own the underlying buffer.
31public:
32 BinaryByteStream() = default;
34 : Endian(Endian), Data(Data) {}
36 : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
37
38 llvm::support::endianness getEndian() const override { return Endian; }
39
41 ArrayRef<uint8_t> &Buffer) override {
42 if (auto EC = checkOffsetForRead(Offset, Size))
43 return EC;
44 Buffer = Data.slice(Offset, Size);
45 return Error::success();
46 }
47
49 ArrayRef<uint8_t> &Buffer) override {
50 if (auto EC = checkOffsetForRead(Offset, 1))
51 return EC;
52 Buffer = Data.slice(Offset);
53 return Error::success();
54 }
55
56 uint64_t getLength() override { return Data.size(); }
57
58 ArrayRef<uint8_t> data() const { return Data; }
59
60 StringRef str() const {
61 const char *CharData = reinterpret_cast<const char *>(Data.data());
62 return StringRef(CharData, Data.size());
63 }
64
65protected:
68};
69
70/// An implementation of BinaryStream whose data is backed by an llvm
71/// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
72/// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
73/// will never cause a copy.
75public:
76 MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
78 : BinaryByteStream(Buffer->getBuffer(), Endian),
79 MemBuffer(std::move(Buffer)) {}
80
81 std::unique_ptr<MemoryBuffer> MemBuffer;
82};
83
84/// An implementation of BinaryStream which holds its entire data set
85/// in a single contiguous buffer. As with BinaryByteStream, the mutable
86/// version also guarantees that no read operation will ever incur a copy,
87/// and similarly it does not own the underlying buffer.
89public:
93 : Data(Data), ImmutableStream(Data, Endian) {}
94
96 return ImmutableStream.getEndian();
97 }
98
100 ArrayRef<uint8_t> &Buffer) override {
101 return ImmutableStream.readBytes(Offset, Size, Buffer);
102 }
103
105 ArrayRef<uint8_t> &Buffer) override {
106 return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
107 }
108
109 uint64_t getLength() override { return ImmutableStream.getLength(); }
110
112 if (Buffer.empty())
113 return Error::success();
114
115 if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
116 return EC;
117
118 uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
119 ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
120 return Error::success();
121 }
122
123 Error commit() override { return Error::success(); }
124
125 MutableArrayRef<uint8_t> data() const { return Data; }
126
127private:
129 BinaryByteStream ImmutableStream;
130};
131
132/// An implementation of WritableBinaryStream which can write at its end
133/// causing the underlying data to grow. This class owns the underlying data.
135 std::vector<uint8_t> Data;
137
138public:
141 : Endian(Endian) {}
142
143 void clear() { Data.clear(); }
144
145 llvm::support::endianness getEndian() const override { return Endian; }
146
148 ArrayRef<uint8_t> &Buffer) override {
149 if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
150 return EC;
151
152 Buffer = ArrayRef(Data).slice(Offset, Size);
153 return Error::success();
154 }
155
157 Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
158 }
159
161 ArrayRef<uint8_t> &Buffer) override {
162 if (auto EC = checkOffsetForWrite(Offset, 1))
163 return EC;
164
165 Buffer = ArrayRef(Data).slice(Offset);
166 return Error::success();
167 }
168
169 uint64_t getLength() override { return Data.size(); }
170
172 if (Buffer.empty())
173 return Error::success();
174
175 // This is well-defined for any case except where offset is strictly
176 // greater than the current length. If offset is equal to the current
177 // length, we can still grow. If offset is beyond the current length, we
178 // would have to decide how to deal with the intermediate uninitialized
179 // bytes. So we punt on that case for simplicity and just say it's an
180 // error.
181 if (Offset > getLength())
182 return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
183
184 uint64_t RequiredSize = Offset + Buffer.size();
185 if (RequiredSize > Data.size())
186 Data.resize(RequiredSize);
187
188 ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
189 return Error::success();
190 }
191
192 Error commit() override { return Error::success(); }
193
194 /// Return the properties of this stream.
195 BinaryStreamFlags getFlags() const override { return BSF_Write | BSF_Append; }
196
198};
199
200/// An implementation of WritableBinaryStream backed by an llvm
201/// FileOutputBuffer.
203private:
204 class StreamImpl : public MutableBinaryByteStream {
205 public:
206 StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
209 MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
210 Buffer->getBufferEnd()),
211 Endian),
212 FileBuffer(std::move(Buffer)) {}
213
214 Error commit() override {
215 if (FileBuffer->commit())
216 return make_error<BinaryStreamError>(
218 return Error::success();
219 }
220
221 /// Returns a pointer to the start of the buffer.
222 uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
223
224 /// Returns a pointer to the end of the buffer.
225 uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
226
227 private:
228 std::unique_ptr<FileOutputBuffer> FileBuffer;
229 };
230
231public:
232 FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
234 : Impl(std::move(Buffer), Endian) {}
235
237 return Impl.getEndian();
238 }
239
241 ArrayRef<uint8_t> &Buffer) override {
242 return Impl.readBytes(Offset, Size, Buffer);
243 }
244
246 ArrayRef<uint8_t> &Buffer) override {
247 return Impl.readLongestContiguousChunk(Offset, Buffer);
248 }
249
250 uint64_t getLength() override { return Impl.getLength(); }
251
253 return Impl.writeBytes(Offset, Data);
254 }
255
256 Error commit() override { return Impl.commit(); }
257
258 /// Returns a pointer to the start of the buffer.
259 uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
260
261 /// Returns a pointer to the end of the buffer.
262 uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
263
264private:
265 StreamImpl Impl;
266};
267
268} // end namespace llvm
269
270#endif // LLVM_SUPPORT_BINARYBYTESTREAM_H
uint64_t Size
An implementation of WritableBinaryStream which can write at its end causing the underlying data to g...
BinaryStreamFlags getFlags() const override
Return the properties of this stream.
llvm::support::endianness getEndian() const override
AppendingBinaryByteStream(llvm::support::endianness Endian)
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Error commit() override
For buffered streams, commits changes to the backing store.
MutableArrayRef< uint8_t > data()
uint64_t getLength() override
Return the number of bytes of data in this stream.
Error readBytes(uint64_t Offset, uint64_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 readLongestContiguousChunk(uint64_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
void insert(uint64_t Offset, ArrayRef< uint8_t > Bytes)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:152
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
iterator begin() const
Definition: ArrayRef.h:151
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
const T * data() const
Definition: ArrayRef.h:160
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:193
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
ArrayRef< uint8_t > data() const
ArrayRef< uint8_t > Data
BinaryByteStream(ArrayRef< uint8_t > Data, llvm::support::endianness Endian)
Error readLongestContiguousChunk(uint64_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Error readBytes(uint64_t Offset, uint64_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...
llvm::support::endianness getEndian() const override
StringRef str() const
uint64_t getLength() override
Return the number of bytes of data in this stream.
BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
llvm::support::endianness Endian
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:35
Error checkOffsetForRead(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:59
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
uint64_t getLength() override
Return the number of bytes of data in this stream.
llvm::support::endianness getEndian() const override
Error commit() override
For buffered streams, commits changes to the backing store.
Error readLongestContiguousChunk(uint64_t Offset, ArrayRef< uint8_t > &Buffer) override
Given an offset into the stream, read as much as possible without copying any data.
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Data) override
Attempt to write the given bytes into the stream at the desired offset.
uint8_t * getBufferEnd() const
Returns a pointer to the end of the buffer.
FileBufferByteStream(std::unique_ptr< FileOutputBuffer > Buffer, llvm::support::endianness Endian)
uint8_t * getBufferStart() const
Returns a pointer to the start of the buffer.
Error readBytes(uint64_t Offset, uint64_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...
An implementation of BinaryStream whose data is backed by an llvm MemoryBuffer object.
std::unique_ptr< MemoryBuffer > MemBuffer
MemoryBufferByteStream(std::unique_ptr< MemoryBuffer > Buffer, llvm::support::endianness Endian)
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:305
T * data() const
Definition: ArrayRef.h:352
An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.
MutableArrayRef< uint8_t > data() const
uint64_t getLength() override
Return the number of bytes of data in this stream.
Error commit() override
For buffered streams, commits changes to the backing store.
llvm::support::endianness getEndian() const override
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
Error readLongestContiguousChunk(uint64_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 readBytes(uint64_t Offset, uint64_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...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73
Error checkOffsetForWrite(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:89
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
BinaryStreamFlags
Definition: BinaryStream.h:21
@ BSF_Append
Definition: BinaryStream.h:24
@ BSF_Write
Definition: BinaryStream.h:23
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1862
Definition: BitVector.h:851