Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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"
  15. #include "llvm/Support/BinaryStream.h"
  16. #include "llvm/Support/BinaryStreamError.h"
  17. #include "llvm/Support/Error.h"
  18. #include "llvm/Support/FileOutputBuffer.h"
  19. #include "llvm/Support/MemoryBuffer.h"
  20. #include <cstdint>
  21. #include <cstring>
  22. #include <memory>
  23.  
  24. namespace 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.
  30. class BinaryByteStream : public BinaryStream {
  31. public:
  32.   BinaryByteStream() = default;
  33.   BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
  34.       : Endian(Endian), Data(Data) {}
  35.   BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
  36.       : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
  37.  
  38.   llvm::support::endianness getEndian() const override { return Endian; }
  39.  
  40.   Error readBytes(uint64_t Offset, uint64_t Size,
  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.  
  48.   Error readLongestContiguousChunk(uint64_t Offset,
  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.  
  65. protected:
  66.   llvm::support::endianness Endian;
  67.   ArrayRef<uint8_t> Data;
  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.
  74. class MemoryBufferByteStream : public BinaryByteStream {
  75. public:
  76.   MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
  77.                          llvm::support::endianness Endian)
  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.
  88. class MutableBinaryByteStream : public WritableBinaryStream {
  89. public:
  90.   MutableBinaryByteStream() = default;
  91.   MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
  92.                           llvm::support::endianness Endian)
  93.       : Data(Data), ImmutableStream(Data, Endian) {}
  94.  
  95.   llvm::support::endianness getEndian() const override {
  96.     return ImmutableStream.getEndian();
  97.   }
  98.  
  99.   Error readBytes(uint64_t Offset, uint64_t Size,
  100.                   ArrayRef<uint8_t> &Buffer) override {
  101.     return ImmutableStream.readBytes(Offset, Size, Buffer);
  102.   }
  103.  
  104.   Error readLongestContiguousChunk(uint64_t Offset,
  105.                                    ArrayRef<uint8_t> &Buffer) override {
  106.     return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
  107.   }
  108.  
  109.   uint64_t getLength() override { return ImmutableStream.getLength(); }
  110.  
  111.   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
  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.  
  127. private:
  128.   MutableArrayRef<uint8_t> Data;
  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.
  134. class AppendingBinaryByteStream : public WritableBinaryStream {
  135.   std::vector<uint8_t> Data;
  136.   llvm::support::endianness Endian = llvm::support::little;
  137.  
  138. public:
  139.   AppendingBinaryByteStream() = default;
  140.   AppendingBinaryByteStream(llvm::support::endianness Endian)
  141.       : Endian(Endian) {}
  142.  
  143.   void clear() { Data.clear(); }
  144.  
  145.   llvm::support::endianness getEndian() const override { return Endian; }
  146.  
  147.   Error readBytes(uint64_t Offset, uint64_t Size,
  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.  
  156.   void insert(uint64_t Offset, ArrayRef<uint8_t> Bytes) {
  157.     Data.insert(Data.begin() + Offset, Bytes.begin(), Bytes.end());
  158.   }
  159.  
  160.   Error readLongestContiguousChunk(uint64_t Offset,
  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.  
  171.   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override {
  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.  
  197.   MutableArrayRef<uint8_t> data() { return Data; }
  198. };
  199.  
  200. /// An implementation of WritableBinaryStream backed by an llvm
  201. /// FileOutputBuffer.
  202. class FileBufferByteStream : public WritableBinaryStream {
  203. private:
  204.   class StreamImpl : public MutableBinaryByteStream {
  205.   public:
  206.     StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
  207.                llvm::support::endianness Endian)
  208.         : MutableBinaryByteStream(
  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>(
  217.             stream_error_code::filesystem_error);
  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.  
  231. public:
  232.   FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
  233.                        llvm::support::endianness Endian)
  234.       : Impl(std::move(Buffer), Endian) {}
  235.  
  236.   llvm::support::endianness getEndian() const override {
  237.     return Impl.getEndian();
  238.   }
  239.  
  240.   Error readBytes(uint64_t Offset, uint64_t Size,
  241.                   ArrayRef<uint8_t> &Buffer) override {
  242.     return Impl.readBytes(Offset, Size, Buffer);
  243.   }
  244.  
  245.   Error readLongestContiguousChunk(uint64_t Offset,
  246.                                    ArrayRef<uint8_t> &Buffer) override {
  247.     return Impl.readLongestContiguousChunk(Offset, Buffer);
  248.   }
  249.  
  250.   uint64_t getLength() override { return Impl.getLength(); }
  251.  
  252.   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) override {
  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.  
  264. private:
  265.   StreamImpl Impl;
  266. };
  267.  
  268. } // end namespace llvm
  269.  
  270. #endif // LLVM_SUPPORT_BINARYBYTESTREAM_H
  271.