]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/BinaryStreamRef.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r303571, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Support / BinaryStreamRef.h
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
21 namespace llvm {
22
23 /// Common stuff for mutable and immutable StreamRefs.
24 template <class RefType, class StreamType> class BinaryStreamRefBase {
25 protected:
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
41 public:
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
107 protected:
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.
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,
134                   uint32_t Length)
135       : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
136
137 public:
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
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) {}
176
177 public:
178   WritableBinaryStreamRef() = default;
179   WritableBinaryStreamRef(WritableBinaryStream &Stream);
180   WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
181                           uint32_t Length);
182   explicit WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
183                                    llvm::support::endianness Endian);
184   WritableBinaryStreamRef(const WritableBinaryStreamRef &Other);
185
186   // Use WritableBinaryStreamRef.slice() instead.
187   WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
188                           uint32_t Length) = delete;
189
190   /// Given an Offset into this WritableBinaryStreamRef and some input data,
191   /// writes the data to the underlying stream.
192   ///
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;
197
198   /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
199   operator BinaryStreamRef() const;
200
201   /// \brief For buffered streams, commits changes to the backing store.
202   Error commit();
203 };
204
205 } // end namespace llvm
206
207 #endif // LLVM_SUPPORT_BINARYSTREAMREF_H