]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/BinaryStreamRef.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306325, 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 struct 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
191 class 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
199 public:
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