BinaryByteStream.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. #ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
  10. #define LLVM_SUPPORT_BINARYBYTESTREAM_H
  11. #include "llvm/ADT/ArrayRef.h"
  12. #include "llvm/ADT/StringRef.h"
  13. #include "llvm/Support/BinaryStream.h"
  14. #include "llvm/Support/BinaryStreamError.h"
  15. #include "llvm/Support/Error.h"
  16. #include "llvm/Support/FileOutputBuffer.h"
  17. #include "llvm/Support/MemoryBuffer.h"
  18. #include <algorithm>
  19. #include <cstdint>
  20. #include <cstring>
  21. #include <memory>
  22. namespace llvm {
  23. /// An implementation of BinaryStream which holds its entire data set
  24. /// in a single contiguous buffer. BinaryByteStream guarantees that no read
  25. /// operation will ever incur a copy. Note that BinaryByteStream does not
  26. /// own the underlying buffer.
  27. class BinaryByteStream : public BinaryStream {
  28. public:
  29. BinaryByteStream() = default;
  30. BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
  31. : Endian(Endian), Data(Data) {}
  32. BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
  33. : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
  34. llvm::support::endianness getEndian() const override { return Endian; }
  35. Error readBytes(uint32_t Offset, uint32_t Size,
  36. ArrayRef<uint8_t> &Buffer) override {
  37. if (auto EC = checkOffsetForRead(Offset, Size))
  38. return EC;
  39. Buffer = Data.slice(Offset, Size);
  40. return Error::success();
  41. }
  42. Error readLongestContiguousChunk(uint32_t Offset,
  43. ArrayRef<uint8_t> &Buffer) override {
  44. if (auto EC = checkOffsetForRead(Offset, 1))
  45. return EC;
  46. Buffer = Data.slice(Offset);
  47. return Error::success();
  48. }
  49. uint32_t getLength() override { return Data.size(); }
  50. ArrayRef<uint8_t> data() const { return Data; }
  51. StringRef str() const {
  52. const char *CharData = reinterpret_cast<const char *>(Data.data());
  53. return StringRef(CharData, Data.size());
  54. }
  55. protected:
  56. llvm::support::endianness Endian;
  57. ArrayRef<uint8_t> Data;
  58. };
  59. /// An implementation of BinaryStream whose data is backed by an llvm
  60. /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
  61. /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
  62. /// will never cause a copy.
  63. class MemoryBufferByteStream : public BinaryByteStream {
  64. public:
  65. MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
  66. llvm::support::endianness Endian)
  67. : BinaryByteStream(Buffer->getBuffer(), Endian),
  68. MemBuffer(std::move(Buffer)) {}
  69. std::unique_ptr<MemoryBuffer> MemBuffer;
  70. };
  71. /// An implementation of BinaryStream which holds its entire data set
  72. /// in a single contiguous buffer. As with BinaryByteStream, the mutable
  73. /// version also guarantees that no read operation will ever incur a copy,
  74. /// and similarly it does not own the underlying buffer.
  75. class MutableBinaryByteStream : public WritableBinaryStream {
  76. public:
  77. MutableBinaryByteStream() = default;
  78. MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
  79. llvm::support::endianness Endian)
  80. : Data(Data), ImmutableStream(Data, Endian) {}
  81. llvm::support::endianness getEndian() const override {
  82. return ImmutableStream.getEndian();
  83. }
  84. Error readBytes(uint32_t Offset, uint32_t Size,
  85. ArrayRef<uint8_t> &Buffer) override {
  86. return ImmutableStream.readBytes(Offset, Size, Buffer);
  87. }
  88. Error readLongestContiguousChunk(uint32_t Offset,
  89. ArrayRef<uint8_t> &Buffer) override {
  90. return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
  91. }
  92. uint32_t getLength() override { return ImmutableStream.getLength(); }
  93. Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
  94. if (Buffer.empty())
  95. return Error::success();
  96. if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
  97. return EC;
  98. uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
  99. ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
  100. return Error::success();
  101. }
  102. Error commit() override { return Error::success(); }
  103. MutableArrayRef<uint8_t> data() const { return Data; }
  104. private:
  105. MutableArrayRef<uint8_t> Data;
  106. BinaryByteStream ImmutableStream;
  107. };
  108. /// An implementation of WritableBinaryStream which can write at its end
  109. /// causing the underlying data to grow. This class owns the underlying data.
  110. class AppendingBinaryByteStream : public WritableBinaryStream {
  111. std::vector<uint8_t> Data;
  112. llvm::support::endianness Endian = llvm::support::little;
  113. public:
  114. AppendingBinaryByteStream() = default;
  115. AppendingBinaryByteStream(llvm::support::endianness Endian)
  116. : Endian(Endian) {}
  117. void clear() { Data.clear(); }
  118. llvm::support::endianness getEndian() const override { return Endian; }
  119. Error readBytes(uint32_t Offset, uint32_t Size,
  120. ArrayRef<uint8_t> &Buffer) override {
  121. if (auto EC = checkOffsetForWrite(Offset, Buffer.size()))
  122. return EC;
  123. Buffer = makeArrayRef(Data).slice(Offset, Size);
  124. return Error::success();
  125. }
  126. void insert(uint32_t Offset, ArrayRef<uint8_t> Bytes) {
  127. Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
  128. }
  129. Error readLongestContiguousChunk(uint32_t Offset,
  130. ArrayRef<uint8_t> &Buffer) override {
  131. if (auto EC = checkOffsetForWrite(Offset, 1))
  132. return EC;
  133. Buffer = makeArrayRef(Data).slice(Offset);
  134. return Error::success();
  135. }
  136. uint32_t getLength() override { return Data.size(); }
  137. Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
  138. if (Buffer.empty())
  139. return Error::success();
  140. // This is well-defined for any case except where offset is strictly
  141. // greater than the current length. If offset is equal to the current
  142. // length, we can still grow. If offset is beyond the current length, we
  143. // would have to decide how to deal with the intermediate uninitialized
  144. // bytes. So we punt on that case for simplicity and just say it's an
  145. // error.
  146. if (Offset > getLength())
  147. return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
  148. uint32_t RequiredSize = Offset + Buffer.size();
  149. if (RequiredSize > Data.size())
  150. Data.resize(RequiredSize);
  151. ::memcpy(Data.data() + Offset, Buffer.data(), Buffer.size());
  152. return Error::success();
  153. }
  154. Error commit() override { return Error::success(); }
  155. /// Return the properties of this stream.
  156. virtual BinaryStreamFlags getFlags() const override {
  157. return BSF_Write | BSF_Append;
  158. }
  159. MutableArrayRef<uint8_t> data() { return Data; }
  160. };
  161. /// An implementation of WritableBinaryStream backed by an llvm
  162. /// FileOutputBuffer.
  163. class FileBufferByteStream : public WritableBinaryStream {
  164. private:
  165. class StreamImpl : public MutableBinaryByteStream {
  166. public:
  167. StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
  168. llvm::support::endianness Endian)
  169. : MutableBinaryByteStream(
  170. MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
  171. Buffer->getBufferEnd()),
  172. Endian),
  173. FileBuffer(std::move(Buffer)) {}
  174. Error commit() override {
  175. if (FileBuffer->commit())
  176. return make_error<BinaryStreamError>(
  177. stream_error_code::filesystem_error);
  178. return Error::success();
  179. }
  180. /// Returns a pointer to the start of the buffer.
  181. uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
  182. /// Returns a pointer to the end of the buffer.
  183. uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
  184. private:
  185. std::unique_ptr<FileOutputBuffer> FileBuffer;
  186. };
  187. public:
  188. FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
  189. llvm::support::endianness Endian)
  190. : Impl(std::move(Buffer), Endian) {}
  191. llvm::support::endianness getEndian() const override {
  192. return Impl.getEndian();
  193. }
  194. Error readBytes(uint32_t Offset, uint32_t Size,
  195. ArrayRef<uint8_t> &Buffer) override {
  196. return Impl.readBytes(Offset, Size, Buffer);
  197. }
  198. Error readLongestContiguousChunk(uint32_t Offset,
  199. ArrayRef<uint8_t> &Buffer) override {
  200. return Impl.readLongestContiguousChunk(Offset, Buffer);
  201. }
  202. uint32_t getLength() override { return Impl.getLength(); }
  203. Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
  204. return Impl.writeBytes(Offset, Data);
  205. }
  206. Error commit() override { return Impl.commit(); }
  207. /// Returns a pointer to the start of the buffer.
  208. uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
  209. /// Returns a pointer to the end of the buffer.
  210. uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
  211. private:
  212. StreamImpl Impl;
  213. };
  214. } // end namespace llvm
  215. #endif // LLVM_SUPPORT_BINARYBYTESTREAM_H