1 //===- BinaryStreamRef.h - A copyable reference to a stream -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
11 #define LLVM_SUPPORT_BINARYSTREAMREF_H
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/Support/BinaryStream.h"
15 #include "llvm/Support/BinaryStreamError.h"
16 #include "llvm/Support/Error.h"
23 /// Common stuff for mutable and immutable StreamRefs.
24 template <class RefType, class StreamType> class BinaryStreamRefBase {
26 BinaryStreamRefBase() = default;
27 BinaryStreamRefBase(std::shared_ptr<StreamType> SharedImpl, uint32_t Offset,
29 : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
30 ViewOffset(Offset), Length(Length) {}
31 BinaryStreamRefBase(StreamType &BorrowedImpl, uint32_t Offset,
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;
42 llvm::support::endianness getEndian() const {
43 return BorrowedImpl->getEndian();
46 uint32_t getLength() const { return Length; }
48 /// Return a new BinaryStreamRef with the first \p N elements removed.
49 RefType drop_front(uint32_t N) const {
53 N = std::min(N, Length);
54 RefType Result(static_cast<const RefType &>(*this));
55 Result.ViewOffset += N;
60 /// Return a new BinaryStreamRef with the first \p N elements removed.
61 RefType drop_back(uint32_t N) const {
65 N = std::min(N, Length);
66 RefType Result(static_cast<const RefType &>(*this));
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);
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);
83 /// Return a new BinaryStreamRef with the first and last \p N elements
85 RefType drop_symmetric(uint32_t N) const {
86 return drop_front(N).drop_back(N);
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);
95 bool valid() const { return BorrowedImpl != nullptr; }
97 bool operator==(const RefType &Other) const {
98 if (BorrowedImpl != Other.BorrowedImpl)
100 if (ViewOffset != Other.ViewOffset)
102 if (Length != Other.Length)
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();
116 std::shared_ptr<StreamType> SharedImpl;
117 StreamType *BorrowedImpl = nullptr;
118 uint32_t ViewOffset = 0;
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.
129 class 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,
135 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
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);
145 BinaryStreamRef(const BinaryStreamRef &Other);
147 // Use BinaryStreamRef.slice() instead.
148 BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
149 uint32_t Length) = delete;
151 /// Given an Offset into this StreamRef and a Size, return a reference to a
152 /// buffer owned by the stream.
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;
160 /// Given an Offset into this BinaryStreamRef, return a reference to the
161 /// largest buffer the stream could support without necessitating a copy.
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;
169 class WritableBinaryStreamRef
170 : public BinaryStreamRefBase<WritableBinaryStreamRef,
171 WritableBinaryStream> {
172 friend BinaryStreamRefBase<WritableBinaryStreamRef, WritableBinaryStream>;
173 WritableBinaryStreamRef(std::shared_ptr<WritableBinaryStream> Impl,
174 uint32_t ViewOffset, uint32_t Length)
175 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
178 WritableBinaryStreamRef() = default;
179 WritableBinaryStreamRef(WritableBinaryStream &Stream);
180 WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
182 explicit WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
183 llvm::support::endianness Endian);
184 WritableBinaryStreamRef(const WritableBinaryStreamRef &Other);
186 // Use WritableBinaryStreamRef.slice() instead.
187 WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
188 uint32_t Length) = delete;
190 /// Given an Offset into this WritableBinaryStreamRef and some input data,
191 /// writes the data to the underlying stream.
193 /// \returns a success error code if the data could fit within the underlying
194 /// stream at the specified location and the implementation could write the
195 /// data, and an appropriate error code otherwise.
196 Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const;
198 /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
199 operator BinaryStreamRef() const;
201 /// \brief For buffered streams, commits changes to the backing store.
205 } // end namespace llvm
207 #endif // LLVM_SUPPORT_BINARYSTREAMREF_H