LLVM  10.0.0svn
BinaryStreamRef.h
Go to the documentation of this file.
1 //===- BinaryStreamRef.h - A copyable reference to a stream -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
10 #define LLVM_SUPPORT_BINARYSTREAMREF_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/Optional.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;
28  : BorrowedImpl(&BorrowedImpl), ViewOffset(0) {
29  if (!(BorrowedImpl.getFlags() & BSF_Append))
30  Length = BorrowedImpl.getLength();
31  }
32 
33  BinaryStreamRefBase(std::shared_ptr<StreamType> SharedImpl, uint32_t Offset,
35  : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
36  ViewOffset(Offset), Length(Length) {}
39  : BorrowedImpl(&BorrowedImpl), ViewOffset(Offset), Length(Length) {}
41  BinaryStreamRefBase &operator=(const BinaryStreamRefBase &Other) = default;
42 
44  BinaryStreamRefBase(BinaryStreamRefBase &&Other) = default;
45 
46 public:
48  return BorrowedImpl->getEndian();
49  }
50 
51  uint32_t getLength() const {
52  if (Length.hasValue())
53  return *Length;
54 
55  return BorrowedImpl ? (BorrowedImpl->getLength() - ViewOffset) : 0;
56  }
57 
58  /// Return a new BinaryStreamRef with the first \p N elements removed. If
59  /// this BinaryStreamRef is length-tracking, then the resulting one will be
60  /// too.
61  RefType drop_front(uint32_t N) const {
62  if (!BorrowedImpl)
63  return RefType();
64 
65  N = std::min(N, getLength());
66  RefType Result(static_cast<const RefType &>(*this));
67  if (N == 0)
68  return Result;
69 
70  Result.ViewOffset += N;
71  if (Result.Length.hasValue())
72  *Result.Length -= N;
73  return Result;
74  }
75 
76  /// Return a new BinaryStreamRef with the last \p N elements removed. If
77  /// this BinaryStreamRef is length-tracking and \p N is greater than 0, then
78  /// this BinaryStreamRef will no longer length-track.
79  RefType drop_back(uint32_t N) const {
80  if (!BorrowedImpl)
81  return RefType();
82 
83  RefType Result(static_cast<const RefType &>(*this));
84  N = std::min(N, getLength());
85 
86  if (N == 0)
87  return Result;
88 
89  // Since we're dropping non-zero bytes from the end, stop length-tracking
90  // by setting the length of the resulting StreamRef to an explicit value.
91  if (!Result.Length.hasValue())
92  Result.Length = getLength();
93 
94  *Result.Length -= N;
95  return Result;
96  }
97 
98  /// Return a new BinaryStreamRef with only the first \p N elements remaining.
99  RefType keep_front(uint32_t N) const {
100  assert(N <= getLength());
101  return drop_back(getLength() - N);
102  }
103 
104  /// Return a new BinaryStreamRef with only the last \p N elements remaining.
105  RefType keep_back(uint32_t N) const {
106  assert(N <= getLength());
107  return drop_front(getLength() - N);
108  }
109 
110  /// Return a new BinaryStreamRef with the first and last \p N elements
111  /// removed.
112  RefType drop_symmetric(uint32_t N) const {
113  return drop_front(N).drop_back(N);
114  }
115 
116  /// Return a new BinaryStreamRef with the first \p Offset elements removed,
117  /// and retaining exactly \p Len elements.
118  RefType slice(uint32_t Offset, uint32_t Len) const {
119  return drop_front(Offset).keep_front(Len);
120  }
121 
122  bool valid() const { return BorrowedImpl != nullptr; }
123 
124  bool operator==(const RefType &Other) const {
125  if (BorrowedImpl != Other.BorrowedImpl)
126  return false;
127  if (ViewOffset != Other.ViewOffset)
128  return false;
129  if (Length != Other.Length)
130  return false;
131  return true;
132  }
133 
134 protected:
136  if (Offset > getLength())
137  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
138  if (getLength() < DataSize + Offset)
139  return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
140  return Error::success();
141  }
142 
143  std::shared_ptr<StreamType> SharedImpl;
147 };
148 
149 /// BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
150 /// provides copy-semantics and read only access to a "window" of the underlying
151 /// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream. That is to
152 /// say, it does not inherit and override the methods of BinaryStream. In
153 /// general, you should not pass around pointers or references to BinaryStreams
154 /// and use inheritance to achieve polymorphism. Instead, you should pass
155 /// around BinaryStreamRefs by value and achieve polymorphism that way.
157  : public BinaryStreamRefBase<BinaryStreamRef, BinaryStream> {
160  BinaryStreamRef(std::shared_ptr<BinaryStream> Impl, uint32_t ViewOffset,
162  : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
163 
164 public:
165  BinaryStreamRef() = default;
166  BinaryStreamRef(BinaryStream &Stream);
172 
173  BinaryStreamRef(const BinaryStreamRef &Other) = default;
174  BinaryStreamRef &operator=(const BinaryStreamRef &Other) = default;
177 
178  // Use BinaryStreamRef.slice() instead.
180  uint32_t Length) = delete;
181 
182  /// Given an Offset into this StreamRef and a Size, return a reference to a
183  /// buffer owned by the stream.
184  ///
185  /// \returns a success error code if the entire range of data is within the
186  /// bounds of this BinaryStreamRef's view and the implementation could read
187  /// the data, and an appropriate error code otherwise.
188  Error readBytes(uint32_t Offset, uint32_t Size,
189  ArrayRef<uint8_t> &Buffer) const;
190 
191  /// Given an Offset into this BinaryStreamRef, return a reference to the
192  /// largest buffer the stream could support without necessitating a copy.
193  ///
194  /// \returns a success error code if implementation could read the data,
195  /// and an appropriate error code otherwise.
196  Error readLongestContiguousChunk(uint32_t Offset,
197  ArrayRef<uint8_t> &Buffer) const;
198 };
199 
201  uint32_t Offset; // Offset in the parent stream
202  BinaryStreamRef StreamData; // Stream Data
203 
205  BinaryStreamRef SubSub = StreamData.slice(Off, Size);
206  return {Off + Offset, SubSub};
207  }
209  return slice(N, size() - N);
210  }
211  BinarySubstreamRef keep_front(uint32_t N) const { return slice(0, N); }
212 
213  std::pair<BinarySubstreamRef, BinarySubstreamRef>
214  split(uint32_t Offset) const {
215  return std::make_pair(keep_front(Offset), drop_front(Offset));
216  }
217 
218  uint32_t size() const { return StreamData.getLength(); }
219  bool empty() const { return size() == 0; }
220 };
221 
223  : public BinaryStreamRefBase<WritableBinaryStreamRef,
224  WritableBinaryStream> {
226  WritableBinaryStreamRef(std::shared_ptr<WritableBinaryStream> Impl,
228  : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
229 
230  Error checkOffsetForWrite(uint32_t Offset, uint32_t DataSize) const {
231  if (!(BorrowedImpl->getFlags() & BSF_Append))
232  return checkOffsetForRead(Offset, DataSize);
233 
234  if (Offset > getLength())
235  return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
236  return Error::success();
237  }
238 
239 public:
240  WritableBinaryStreamRef() = default;
243  Optional<uint32_t> Length);
248  operator=(const WritableBinaryStreamRef &Other) = default;
249 
252 
253  // Use WritableBinaryStreamRef.slice() instead.
255  uint32_t Length) = delete;
256 
257  /// Given an Offset into this WritableBinaryStreamRef and some input data,
258  /// writes the data to the underlying stream.
259  ///
260  /// \returns a success error code if the data could fit within the underlying
261  /// stream at the specified location and the implementation could write the
262  /// data, and an appropriate error code otherwise.
263  Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const;
264 
265  /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef.
266  operator BinaryStreamRef() const;
267 
268  /// For buffered streams, commits changes to the backing store.
269  Error commit();
270 };
271 
272 } // end namespace llvm
273 
274 #endif // LLVM_SUPPORT_BINARYSTREAMREF_H
BinarySubstreamRef slice(uint32_t Off, uint32_t Size) const
bool operator==(const RefType &Other) const
RefType slice(uint32_t Offset, uint32_t Len) const
Return a new BinaryStreamRef with the first Offset elements removed, and retaining exactly Len elemen...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
BinaryStreamRefBase & operator=(const BinaryStreamRefBase &Other)=default
BinaryStreamRefBase(std::shared_ptr< StreamType > SharedImpl, uint32_t Offset, Optional< uint32_t > Length)
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:953
std::shared_ptr< StreamType > SharedImpl
llvm::support::endianness getEndian() const
Common stuff for mutable and immutable StreamRefs.
RefType keep_back(uint32_t N) const
Return a new BinaryStreamRef with only the last N elements remaining.
StreamType
The type of a minidump stream identifies its contents.
Definition: Minidump.h:47
BinaryStreamRefBase(StreamType &BorrowedImpl, uint32_t Offset, Optional< uint32_t > Length)
Optional< uint32_t > Length
An interface for accessing data in a stream-like format, but which discourages copying.
Definition: BinaryStream.h:35
RefType drop_back(uint32_t N) const
Return a new BinaryStreamRef with the last N elements removed.
BinarySubstreamRef drop_front(uint32_t N) const
RefType drop_front(uint32_t N) const
Return a new BinaryStreamRef with the first N elements removed.
BinaryStreamRef StreamData
uint32_t getLength() const
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1146
std::pair< BinarySubstreamRef, BinarySubstreamRef > split(uint32_t Offset) const
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
bool hasValue() const
Definition: Optional.h:259
#define N
uint32_t Size
Definition: Profile.cpp:46
RefType drop_symmetric(uint32_t N) const
Return a new BinaryStreamRef with the first and last N elements removed.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
BinarySubstreamRef keep_front(uint32_t N) const
RefType keep_front(uint32_t N) const
Return a new BinaryStreamRef with only the first N elements remaining.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
BinaryStreamRefBase(StreamType &BorrowedImpl)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Error checkOffsetForRead(uint32_t Offset, uint32_t DataSize) const
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:73