LLVM 18.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
endianness Endian
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:154
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
iterator begin() const
Definition: ArrayRef.h:153
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
const T * data() const
Definition: ArrayRef.h:162
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:195
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:154
static ErrorSuccess success()
Create a success value.
Definition: Error.h:328
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:307
T * data() const
Definition: ArrayRef.h:354
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:440
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:1854
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858