Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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

  1. //===- BinaryStreamRef.h - A copyable reference to a stream -----*- 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. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
  10. #define LLVM_SUPPORT_BINARYSTREAMREF_H
  11.  
  12. #include "llvm/ADT/ArrayRef.h"
  13. #include "llvm/Support/BinaryStream.h"
  14. #include "llvm/Support/BinaryStreamError.h"
  15. #include "llvm/Support/Error.h"
  16. #include <cstdint>
  17. #include <memory>
  18. #include <optional>
  19.  
  20. namespace llvm {
  21.  
  22. /// Common stuff for mutable and immutable StreamRefs.
  23. template <class RefType, class StreamType> class BinaryStreamRefBase {
  24. protected:
  25.   BinaryStreamRefBase() = default;
  26.   explicit BinaryStreamRefBase(StreamType &BorrowedImpl)
  27.       : BorrowedImpl(&BorrowedImpl), ViewOffset(0) {
  28.     if (!(BorrowedImpl.getFlags() & BSF_Append))
  29.       Length = BorrowedImpl.getLength();
  30.   }
  31.  
  32.   BinaryStreamRefBase(std::shared_ptr<StreamType> SharedImpl, uint64_t Offset,
  33.                       std::optional<uint64_t> Length)
  34.       : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
  35.         ViewOffset(Offset), Length(Length) {}
  36.   BinaryStreamRefBase(StreamType &BorrowedImpl, uint64_t Offset,
  37.                       std::optional<uint64_t> Length)
  38.       : BorrowedImpl(&BorrowedImpl), ViewOffset(Offset), Length(Length) {}
  39.   BinaryStreamRefBase(const BinaryStreamRefBase &Other) = default;
  40.   BinaryStreamRefBase &operator=(const BinaryStreamRefBase &Other) = default;
  41.  
  42.   BinaryStreamRefBase &operator=(BinaryStreamRefBase &&Other) = default;
  43.   BinaryStreamRefBase(BinaryStreamRefBase &&Other) = default;
  44.  
  45. public:
  46.   llvm::support::endianness getEndian() const {
  47.     return BorrowedImpl->getEndian();
  48.   }
  49.  
  50.   uint64_t getLength() const {
  51.     if (Length)
  52.       return *Length;
  53.  
  54.     return BorrowedImpl ? (BorrowedImpl->getLength() - ViewOffset) : 0;
  55.   }
  56.  
  57.   /// Return a new BinaryStreamRef with the first \p N elements removed.  If
  58.   /// this BinaryStreamRef is length-tracking, then the resulting one will be
  59.   /// too.
  60.   RefType drop_front(uint64_t N) const {
  61.     if (!BorrowedImpl)
  62.       return RefType();
  63.  
  64.     N = std::min(N, getLength());
  65.     RefType Result(static_cast<const RefType &>(*this));
  66.     if (N == 0)
  67.       return Result;
  68.  
  69.     Result.ViewOffset += N;
  70.     if (Result.Length)
  71.       *Result.Length -= N;
  72.     return Result;
  73.   }
  74.  
  75.   /// Return a new BinaryStreamRef with the last \p N elements removed.  If
  76.   /// this BinaryStreamRef is length-tracking and \p N is greater than 0, then
  77.   /// this BinaryStreamRef will no longer length-track.
  78.   RefType drop_back(uint64_t N) const {
  79.     if (!BorrowedImpl)
  80.       return RefType();
  81.  
  82.     RefType Result(static_cast<const RefType &>(*this));
  83.     N = std::min(N, getLength());
  84.  
  85.     if (N == 0)
  86.       return Result;
  87.  
  88.     // Since we're dropping non-zero bytes from the end, stop length-tracking
  89.     // by setting the length of the resulting StreamRef to an explicit value.
  90.     if (!Result.Length)
  91.       Result.Length = getLength();
  92.  
  93.     *Result.Length -= N;
  94.     return Result;
  95.   }
  96.  
  97.   /// Return a new BinaryStreamRef with only the first \p N elements remaining.
  98.   RefType keep_front(uint64_t N) const {
  99.     assert(N <= getLength());
  100.     return drop_back(getLength() - N);
  101.   }
  102.  
  103.   /// Return a new BinaryStreamRef with only the last \p N elements remaining.
  104.   RefType keep_back(uint64_t N) const {
  105.     assert(N <= getLength());
  106.     return drop_front(getLength() - N);
  107.   }
  108.  
  109.   /// Return a new BinaryStreamRef with the first and last \p N elements
  110.   /// removed.
  111.   RefType drop_symmetric(uint64_t N) const {
  112.     return drop_front(N).drop_back(N);
  113.   }
  114.  
  115.   /// Return a new BinaryStreamRef with the first \p Offset elements removed,
  116.   /// and retaining exactly \p Len elements.
  117.   RefType slice(uint64_t Offset, uint64_t Len) const {
  118.     return drop_front(Offset).keep_front(Len);
  119.   }
  120.  
  121.   bool valid() const { return BorrowedImpl != nullptr; }
  122.  
  123.   friend bool operator==(const RefType &LHS, const RefType &RHS) {
  124.     if (LHS.BorrowedImpl != RHS.BorrowedImpl)
  125.       return false;
  126.     if (LHS.ViewOffset != RHS.ViewOffset)
  127.       return false;
  128.     if (LHS.Length != RHS.Length)
  129.       return false;
  130.     return true;
  131.   }
  132.  
  133. protected:
  134.   Error checkOffsetForRead(uint64_t Offset, uint64_t DataSize) const {
  135.     if (Offset > getLength())
  136.       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
  137.     if (getLength() < DataSize + Offset)
  138.       return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
  139.     return Error::success();
  140.   }
  141.  
  142.   std::shared_ptr<StreamType> SharedImpl;
  143.   StreamType *BorrowedImpl = nullptr;
  144.   uint64_t ViewOffset = 0;
  145.   std::optional<uint64_t> Length;
  146. };
  147.  
  148. /// BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.  It
  149. /// provides copy-semantics and read only access to a "window" of the underlying
  150. /// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream.  That is to
  151. /// say, it does not inherit and override the methods of BinaryStream.  In
  152. /// general, you should not pass around pointers or references to BinaryStreams
  153. /// and use inheritance to achieve polymorphism.  Instead, you should pass
  154. /// around BinaryStreamRefs by value and achieve polymorphism that way.
  155. class BinaryStreamRef
  156.     : public BinaryStreamRefBase<BinaryStreamRef, BinaryStream> {
  157.   friend BinaryStreamRefBase<BinaryStreamRef, BinaryStream>;
  158.   friend class WritableBinaryStreamRef;
  159.   BinaryStreamRef(std::shared_ptr<BinaryStream> Impl, uint64_t ViewOffset,
  160.                   std::optional<uint64_t> Length)
  161.       : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
  162.  
  163. public:
  164.   BinaryStreamRef() = default;
  165.   BinaryStreamRef(BinaryStream &Stream);
  166.   BinaryStreamRef(BinaryStream &Stream, uint64_t Offset,
  167.                   std::optional<uint64_t> Length);
  168.   explicit BinaryStreamRef(ArrayRef<uint8_t> Data,
  169.                            llvm::support::endianness Endian);
  170.   explicit BinaryStreamRef(StringRef Data, llvm::support::endianness Endian);
  171.  
  172.   BinaryStreamRef(const BinaryStreamRef &Other) = default;
  173.   BinaryStreamRef &operator=(const BinaryStreamRef &Other) = default;
  174.   BinaryStreamRef(BinaryStreamRef &&Other) = default;
  175.   BinaryStreamRef &operator=(BinaryStreamRef &&Other) = default;
  176.  
  177.   // Use BinaryStreamRef.slice() instead.
  178.   BinaryStreamRef(BinaryStreamRef &S, uint64_t Offset,
  179.                   uint64_t Length) = delete;
  180.  
  181.   /// Given an Offset into this StreamRef and a Size, return a reference to a
  182.   /// buffer owned by the stream.
  183.   ///
  184.   /// \returns a success error code if the entire range of data is within the
  185.   /// bounds of this BinaryStreamRef's view and the implementation could read
  186.   /// the data, and an appropriate error code otherwise.
  187.   Error readBytes(uint64_t Offset, uint64_t Size,
  188.                   ArrayRef<uint8_t> &Buffer) const;
  189.  
  190.   /// Given an Offset into this BinaryStreamRef, return a reference to the
  191.   /// largest buffer the stream could support without necessitating a copy.
  192.   ///
  193.   /// \returns a success error code if implementation could read the data,
  194.   /// and an appropriate error code otherwise.
  195.   Error readLongestContiguousChunk(uint64_t Offset,
  196.                                    ArrayRef<uint8_t> &Buffer) const;
  197. };
  198.  
  199. struct BinarySubstreamRef {
  200.   uint64_t Offset = 0;        // Offset in the parent stream
  201.   BinaryStreamRef StreamData; // Stream Data
  202.  
  203.   BinarySubstreamRef slice(uint64_t Off, uint64_t Size) const {
  204.     BinaryStreamRef SubSub = StreamData.slice(Off, Size);
  205.     return {Off + Offset, SubSub};
  206.   }
  207.   BinarySubstreamRef drop_front(uint64_t N) const {
  208.     return slice(N, size() - N);
  209.   }
  210.   BinarySubstreamRef keep_front(uint64_t N) const { return slice(0, N); }
  211.  
  212.   std::pair<BinarySubstreamRef, BinarySubstreamRef> split(uint64_t Off) const {
  213.     return std::make_pair(keep_front(Off), drop_front(Off));
  214.   }
  215.  
  216.   uint64_t size() const { return StreamData.getLength(); }
  217.   bool empty() const { return size() == 0; }
  218. };
  219.  
  220. class WritableBinaryStreamRef
  221.     : public BinaryStreamRefBase<WritableBinaryStreamRef,
  222.                                  WritableBinaryStream> {
  223.   friend BinaryStreamRefBase<WritableBinaryStreamRef, WritableBinaryStream>;
  224.   WritableBinaryStreamRef(std::shared_ptr<WritableBinaryStream> Impl,
  225.                           uint64_t ViewOffset, std::optional<uint64_t> Length)
  226.       : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
  227.  
  228.   Error checkOffsetForWrite(uint64_t Offset, uint64_t DataSize) const {
  229.     if (!(BorrowedImpl->getFlags() & BSF_Append))
  230.       return checkOffsetForRead(Offset, DataSize);
  231.  
  232.     if (Offset > getLength())
  233.       return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
  234.     return Error::success();
  235.   }
  236.  
  237. public:
  238.   WritableBinaryStreamRef() = default;
  239.   WritableBinaryStreamRef(WritableBinaryStream &Stream);
  240.   WritableBinaryStreamRef(WritableBinaryStream &Stream, uint64_t Offset,
  241.                           std::optional<uint64_t> Length);
  242.   explicit WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
  243.                                    llvm::support::endianness Endian);
  244.   WritableBinaryStreamRef(const WritableBinaryStreamRef &Other) = default;
  245.   WritableBinaryStreamRef &
  246.   operator=(const WritableBinaryStreamRef &Other) = default;
  247.  
  248.   WritableBinaryStreamRef(WritableBinaryStreamRef &&Other) = default;
  249.   WritableBinaryStreamRef &operator=(WritableBinaryStreamRef &&Other) = default;
  250.  
  251.   // Use WritableBinaryStreamRef.slice() instead.
  252.   WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint64_t Offset,
  253.                           uint64_t Length) = delete;
  254.  
  255.   /// Given an Offset into this WritableBinaryStreamRef and some input data,
  256.   /// writes the data to the underlying stream.
  257.   ///
  258.   /// \returns a success error code if the data could fit within the underlying
  259.   /// stream at the specified location and the implementation could write the
  260.   /// data, and an appropriate error code otherwise.
  261.   Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) const;
  262.  
  263.   /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
  264.   operator BinaryStreamRef() const;
  265.  
  266.   /// For buffered streams, commits changes to the backing store.
  267.   Error commit();
  268. };
  269.  
  270. } // end namespace llvm
  271.  
  272. #endif // LLVM_SUPPORT_BINARYSTREAMREF_H
  273.