1 //===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
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 //===----------------------------------------------------------------------===//
11 #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
12 #define LLVM_SUPPORT_BINARYBYTESTREAM_H
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/BinaryStream.h"
17 #include "llvm/Support/BinaryStreamError.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/FileOutputBuffer.h"
20 #include "llvm/Support/MemoryBuffer.h"
28 /// \brief 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.
32 class BinaryByteStream : public BinaryStream {
34 BinaryByteStream() = default;
35 BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
36 : Endian(Endian), Data(Data) {}
37 BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
38 : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
40 llvm::support::endianness getEndian() const override { return Endian; }
42 Error readBytes(uint32_t Offset, uint32_t Size,
43 ArrayRef<uint8_t> &Buffer) override {
44 if (auto EC = checkOffset(Offset, Size))
46 Buffer = Data.slice(Offset, Size);
47 return Error::success();
50 Error readLongestContiguousChunk(uint32_t Offset,
51 ArrayRef<uint8_t> &Buffer) override {
52 if (auto EC = checkOffset(Offset, 1))
54 Buffer = Data.slice(Offset);
55 return Error::success();
58 uint32_t getLength() override { return Data.size(); }
60 ArrayRef<uint8_t> data() const { return Data; }
62 StringRef str() const {
63 const char *CharData = reinterpret_cast<const char *>(Data.data());
64 return StringRef(CharData, Data.size());
68 llvm::support::endianness Endian;
69 ArrayRef<uint8_t> Data;
72 /// \brief 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.
76 class MemoryBufferByteStream : public BinaryByteStream {
78 MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
79 llvm::support::endianness Endian)
80 : BinaryByteStream(Buffer->getBuffer(), Endian),
81 MemBuffer(std::move(Buffer)) {}
83 std::unique_ptr<MemoryBuffer> MemBuffer;
86 /// \brief 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.
90 class MutableBinaryByteStream : public WritableBinaryStream {
92 MutableBinaryByteStream() = default;
93 MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
94 llvm::support::endianness Endian)
95 : Data(Data), ImmutableStream(Data, Endian) {}
97 llvm::support::endianness getEndian() const override {
98 return ImmutableStream.getEndian();
101 Error readBytes(uint32_t Offset, uint32_t Size,
102 ArrayRef<uint8_t> &Buffer) override {
103 return ImmutableStream.readBytes(Offset, Size, Buffer);
106 Error readLongestContiguousChunk(uint32_t Offset,
107 ArrayRef<uint8_t> &Buffer) override {
108 return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
111 uint32_t getLength() override { return ImmutableStream.getLength(); }
113 Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
115 return Error::success();
117 if (auto EC = checkOffset(Offset, Buffer.size()))
120 uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
121 ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
122 return Error::success();
125 Error commit() override { return Error::success(); }
127 MutableArrayRef<uint8_t> data() const { return Data; }
130 MutableArrayRef<uint8_t> Data;
131 BinaryByteStream ImmutableStream;
134 /// \brief An implementation of WritableBinaryStream backed by an llvm
135 /// FileOutputBuffer.
136 class FileBufferByteStream : public WritableBinaryStream {
138 class StreamImpl : public MutableBinaryByteStream {
140 StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
141 llvm::support::endianness Endian)
142 : MutableBinaryByteStream(
143 MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
144 Buffer->getBufferEnd()),
146 FileBuffer(std::move(Buffer)) {}
148 Error commit() override {
149 if (FileBuffer->commit())
150 return make_error<BinaryStreamError>(
151 stream_error_code::filesystem_error);
152 return Error::success();
156 std::unique_ptr<FileOutputBuffer> FileBuffer;
160 FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
161 llvm::support::endianness Endian)
162 : Impl(std::move(Buffer), Endian) {}
164 llvm::support::endianness getEndian() const override {
165 return Impl.getEndian();
168 Error readBytes(uint32_t Offset, uint32_t Size,
169 ArrayRef<uint8_t> &Buffer) override {
170 return Impl.readBytes(Offset, Size, Buffer);
173 Error readLongestContiguousChunk(uint32_t Offset,
174 ArrayRef<uint8_t> &Buffer) override {
175 return Impl.readLongestContiguousChunk(Offset, Buffer);
178 uint32_t getLength() override { return Impl.getLength(); }
180 Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
181 return Impl.writeBytes(Offset, Data);
184 Error commit() override { return Impl.commit(); }
190 } // end namespace llvm
192 #endif // LLVM_SUPPORT_BYTESTREAM_H