LCOV - code coverage report
Current view: top level - include/llvm/Support - BinaryStreamRef.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 119 129 92.2 %
Date: 2018-10-20 13:21:21 Functions: 21 24 87.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13