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