LLVM 20.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::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
95 llvm::endianness getEndian() const override {
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
142 void clear() { Data.clear(); }
143
144 llvm::endianness getEndian() const override { return Endian; }
145
147 ArrayRef<uint8_t> &Buffer) override {
148 if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
149 return EC;
150
151 Buffer = ArrayRef(Data).slice(Offset, Size);
152 return Error::success();
153 }
154
156 Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
157 }
158
160 ArrayRef<uint8_t> &Buffer) override {
161 if (auto EC = checkOffsetForWrite(Offset, 1))
162 return EC;
163
164 Buffer = ArrayRef(Data).slice(Offset);
165 return Error::success();
166 }
167
168 uint64_t getLength() override { return Data.size(); }
169
171 if (Buffer.empty())
172 return Error::success();
173
174 // This is well-defined for any case except where offset is strictly
175 // greater than the current length. If offset is equal to the current
176 // length, we can still grow. If offset is beyond the current length, we
177 // would have to decide how to deal with the intermediate uninitialized
178 // bytes. So we punt on that case for simplicity and just say it's an
179 // error.
180 if (Offset > getLength())
181 return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
182
183 uint64_t RequiredSize = Offset + Buffer.size();
184 if (RequiredSize > Data.size())
185 Data.resize(RequiredSize);
186
187 ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
188 return Error::success();
189 }
190
191 Error commit() override { return Error::success(); }
192
193 /// Return the properties of this stream.
194 BinaryStreamFlags getFlags() const override { return BSF_Write | BSF_Append; }
195
197};
198
199/// An implementation of WritableBinaryStream backed by an llvm
200/// FileOutputBuffer.
202private:
203 class StreamImpl : public MutableBinaryByteStream {
204 public:
205 StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
208 MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
209 Buffer->getBufferEnd()),
210 Endian),
211 FileBuffer(std::move(Buffer)) {}
212
213 Error commit() override {
214 if (FileBuffer->commit())
215 return make_error<BinaryStreamError>(
217 return Error::success();
218 }
219
220 /// Returns a pointer to the start of the buffer.
221 uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
222
223 /// Returns a pointer to the end of the buffer.
224 uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
225
226 private:
227 std::unique_ptr<FileOutputBuffer> FileBuffer;
228 };
229
230public:
231 FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
233 : Impl(std::move(Buffer), Endian) {}
234
235 llvm::endianness getEndian() const override { return Impl.getEndian(); }
236
238 ArrayRef<uint8_t> &Buffer) override {
239 return Impl.readBytes(Offset, Size, Buffer);
240 }
241
243 ArrayRef<uint8_t> &Buffer) override {
244 return Impl.readLongestContiguousChunk(Offset, Buffer);
245 }
246
247 uint64_t getLength() override { return Impl.getLength(); }
248
250 return Impl.writeBytes(Offset, Data);
251 }
252
253 Error commit() override { return Impl.commit(); }
254
255 /// Returns a pointer to the start of the buffer.
256 uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
257
258 /// Returns a pointer to the end of the buffer.
259 uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
260
261private:
262 StreamImpl Impl;
263};
264
265} // end namespace llvm
266
267#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.
Error writeBytes(uint64_t Offset, ArrayRef< uint8_t > Buffer) override
Attempt to write the given bytes into the stream at the desired offset.
llvm::endianness getEndian() const override
AppendingBinaryByteStream(llvm::endianness Endian)
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
BinaryByteStream(ArrayRef< uint8_t > Data, llvm::endianness Endian)
ArrayRef< uint8_t > Data
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::endianness Endian
StringRef str() const
uint64_t getLength() override
Return the number of bytes of data in this stream.
llvm::endianness getEndian() const override
BinaryByteStream(StringRef Data, llvm::endianness Endian)
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:34
Error checkOffsetForRead(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:58
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
FileBufferByteStream(std::unique_ptr< FileOutputBuffer > Buffer, llvm::endianness Endian)
uint64_t getLength() override
Return the number of bytes of data in this stream.
llvm::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.
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::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::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.
MutableBinaryByteStream(MutableArrayRef< uint8_t > Data, llvm::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...
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:72
Error checkOffsetForWrite(uint64_t Offset, uint64_t DataSize)
Definition: BinaryStream.h:88
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
BinaryStreamFlags
Definition: BinaryStream.h:20
@ BSF_Append
Definition: BinaryStream.h:23
@ BSF_Write
Definition: BinaryStream.h:22
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:1856
endianness
Definition: bit.h:70
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858