1 //===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_ADT_ARRAYREF_H
10 #define LLVM_ADT_ARRAYREF_H
12 #include "llvm/ADT/Hashing.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Support/Compiler.h"
21 #include <initializer_list>
24 #include <type_traits>
29 /// ArrayRef - Represent a constant reference to an array (0 or more elements
30 /// consecutively in memory), i.e. a start pointer and a length. It allows
31 /// various APIs to take consecutive elements easily and conveniently.
33 /// This class does not own the underlying data, it is expected to be used in
34 /// situations where the data resides in some other buffer, whose lifetime
35 /// extends past that of the ArrayRef. For this reason, it is not in general
36 /// safe to store an ArrayRef.
38 /// This is intended to be trivially copyable, so it should be passed by
41 class LLVM_NODISCARD ArrayRef
{
43 using iterator
= const T
*;
44 using const_iterator
= const T
*;
45 using size_type
= size_t;
46 using reverse_iterator
= std::reverse_iterator
<iterator
>;
49 /// The start of the array, in an external buffer.
50 const T
*Data
= nullptr;
52 /// The number of elements.
56 /// @name Constructors
59 /// Construct an empty ArrayRef.
60 /*implicit*/ ArrayRef() = default;
62 /// Construct an empty ArrayRef from None.
63 /*implicit*/ ArrayRef(NoneType
) {}
65 /// Construct an ArrayRef from a single element.
66 /*implicit*/ ArrayRef(const T
&OneElt
)
67 : Data(&OneElt
), Length(1) {}
69 /// Construct an ArrayRef from a pointer and length.
70 /*implicit*/ ArrayRef(const T
*data
, size_t length
)
71 : Data(data
), Length(length
) {}
73 /// Construct an ArrayRef from a range.
74 ArrayRef(const T
*begin
, const T
*end
)
75 : Data(begin
), Length(end
- begin
) {}
77 /// Construct an ArrayRef from a SmallVector. This is templated in order to
78 /// avoid instantiating SmallVectorTemplateCommon<T> whenever we
79 /// copy-construct an ArrayRef.
81 /*implicit*/ ArrayRef(const SmallVectorTemplateCommon
<T
, U
> &Vec
)
82 : Data(Vec
.data()), Length(Vec
.size()) {
85 /// Construct an ArrayRef from a std::vector.
87 /*implicit*/ ArrayRef(const std::vector
<T
, A
> &Vec
)
88 : Data(Vec
.data()), Length(Vec
.size()) {}
90 /// Construct an ArrayRef from a std::array
92 /*implicit*/ constexpr ArrayRef(const std::array
<T
, N
> &Arr
)
93 : Data(Arr
.data()), Length(N
) {}
95 /// Construct an ArrayRef from a C array.
97 /*implicit*/ constexpr ArrayRef(const T (&Arr
)[N
]) : Data(Arr
), Length(N
) {}
99 /// Construct an ArrayRef from a std::initializer_list.
100 /*implicit*/ ArrayRef(const std::initializer_list
<T
> &Vec
)
101 : Data(Vec
.begin() == Vec
.end() ? (T
*)nullptr : Vec
.begin()),
102 Length(Vec
.size()) {}
104 /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
105 /// ensure that only ArrayRefs of pointers can be converted.
106 template <typename U
>
108 const ArrayRef
<U
*> &A
,
109 typename
std::enable_if
<
110 std::is_convertible
<U
*const *, T
const *>::value
>::type
* = nullptr)
111 : Data(A
.data()), Length(A
.size()) {}
113 /// Construct an ArrayRef<const T*> from a SmallVector<T*>. This is
114 /// templated in order to avoid instantiating SmallVectorTemplateCommon<T>
115 /// whenever we copy-construct an ArrayRef.
116 template<typename U
, typename DummyT
>
117 /*implicit*/ ArrayRef(
118 const SmallVectorTemplateCommon
<U
*, DummyT
> &Vec
,
119 typename
std::enable_if
<
120 std::is_convertible
<U
*const *, T
const *>::value
>::type
* = nullptr)
121 : Data(Vec
.data()), Length(Vec
.size()) {
124 /// Construct an ArrayRef<const T*> from std::vector<T*>. This uses SFINAE
125 /// to ensure that only vectors of pointers can be converted.
126 template<typename U
, typename A
>
127 ArrayRef(const std::vector
<U
*, A
> &Vec
,
128 typename
std::enable_if
<
129 std::is_convertible
<U
*const *, T
const *>::value
>::type
* = 0)
130 : Data(Vec
.data()), Length(Vec
.size()) {}
133 /// @name Simple Operations
136 iterator
begin() const { return Data
; }
137 iterator
end() const { return Data
+ Length
; }
139 reverse_iterator
rbegin() const { return reverse_iterator(end()); }
140 reverse_iterator
rend() const { return reverse_iterator(begin()); }
142 /// empty - Check if the array is empty.
143 bool empty() const { return Length
== 0; }
145 const T
*data() const { return Data
; }
147 /// size - Get the array size.
148 size_t size() const { return Length
; }
150 /// front - Get the first element.
151 const T
&front() const {
156 /// back - Get the last element.
157 const T
&back() const {
159 return Data
[Length
-1];
162 // copy - Allocate copy in Allocator and return ArrayRef<T> to it.
163 template <typename Allocator
> ArrayRef
<T
> copy(Allocator
&A
) {
164 T
*Buff
= A
.template Allocate
<T
>(Length
);
165 std::uninitialized_copy(begin(), end(), Buff
);
166 return ArrayRef
<T
>(Buff
, Length
);
169 /// equals - Check for element-wise equality.
170 bool equals(ArrayRef RHS
) const {
171 if (Length
!= RHS
.Length
)
173 return std::equal(begin(), end(), RHS
.begin());
176 /// slice(n, m) - Chop off the first N elements of the array, and keep M
177 /// elements in the array.
178 ArrayRef
<T
> slice(size_t N
, size_t M
) const {
179 assert(N
+M
<= size() && "Invalid specifier");
180 return ArrayRef
<T
>(data()+N
, M
);
183 /// slice(n) - Chop off the first N elements of the array.
184 ArrayRef
<T
> slice(size_t N
) const { return slice(N
, size() - N
); }
186 /// Drop the first \p N elements of the array.
187 ArrayRef
<T
> drop_front(size_t N
= 1) const {
188 assert(size() >= N
&& "Dropping more elements than exist");
189 return slice(N
, size() - N
);
192 /// Drop the last \p N elements of the array.
193 ArrayRef
<T
> drop_back(size_t N
= 1) const {
194 assert(size() >= N
&& "Dropping more elements than exist");
195 return slice(0, size() - N
);
198 /// Return a copy of *this with the first N elements satisfying the
199 /// given predicate removed.
200 template <class PredicateT
> ArrayRef
<T
> drop_while(PredicateT Pred
) const {
201 return ArrayRef
<T
>(find_if_not(*this, Pred
), end());
204 /// Return a copy of *this with the first N elements not satisfying
205 /// the given predicate removed.
206 template <class PredicateT
> ArrayRef
<T
> drop_until(PredicateT Pred
) const {
207 return ArrayRef
<T
>(find_if(*this, Pred
), end());
210 /// Return a copy of *this with only the first \p N elements.
211 ArrayRef
<T
> take_front(size_t N
= 1) const {
214 return drop_back(size() - N
);
217 /// Return a copy of *this with only the last \p N elements.
218 ArrayRef
<T
> take_back(size_t N
= 1) const {
221 return drop_front(size() - N
);
224 /// Return the first N elements of this Array that satisfy the given
226 template <class PredicateT
> ArrayRef
<T
> take_while(PredicateT Pred
) const {
227 return ArrayRef
<T
>(begin(), find_if_not(*this, Pred
));
230 /// Return the first N elements of this Array that don't satisfy the
232 template <class PredicateT
> ArrayRef
<T
> take_until(PredicateT Pred
) const {
233 return ArrayRef
<T
>(begin(), find_if(*this, Pred
));
237 /// @name Operator Overloads
239 const T
&operator[](size_t Index
) const {
240 assert(Index
< Length
&& "Invalid index!");
244 /// Disallow accidental assignment from a temporary.
246 /// The declaration here is extra complicated so that "arrayRef = {}"
247 /// continues to select the move assignment operator.
248 template <typename U
>
249 typename
std::enable_if
<std::is_same
<U
, T
>::value
, ArrayRef
<T
>>::type
&
250 operator=(U
&&Temporary
) = delete;
252 /// Disallow accidental assignment from a temporary.
254 /// The declaration here is extra complicated so that "arrayRef = {}"
255 /// continues to select the move assignment operator.
256 template <typename U
>
257 typename
std::enable_if
<std::is_same
<U
, T
>::value
, ArrayRef
<T
>>::type
&
258 operator=(std::initializer_list
<U
>) = delete;
261 /// @name Expensive Operations
263 std::vector
<T
> vec() const {
264 return std::vector
<T
>(Data
, Data
+Length
);
268 /// @name Conversion operators
270 operator std::vector
<T
>() const {
271 return std::vector
<T
>(Data
, Data
+Length
);
277 /// MutableArrayRef - Represent a mutable reference to an array (0 or more
278 /// elements consecutively in memory), i.e. a start pointer and a length. It
279 /// allows various APIs to take and modify consecutive elements easily and
282 /// This class does not own the underlying data, it is expected to be used in
283 /// situations where the data resides in some other buffer, whose lifetime
284 /// extends past that of the MutableArrayRef. For this reason, it is not in
285 /// general safe to store a MutableArrayRef.
287 /// This is intended to be trivially copyable, so it should be passed by
290 class LLVM_NODISCARD MutableArrayRef
: public ArrayRef
<T
> {
292 using iterator
= T
*;
293 using reverse_iterator
= std::reverse_iterator
<iterator
>;
295 /// Construct an empty MutableArrayRef.
296 /*implicit*/ MutableArrayRef() = default;
298 /// Construct an empty MutableArrayRef from None.
299 /*implicit*/ MutableArrayRef(NoneType
) : ArrayRef
<T
>() {}
301 /// Construct an MutableArrayRef from a single element.
302 /*implicit*/ MutableArrayRef(T
&OneElt
) : ArrayRef
<T
>(OneElt
) {}
304 /// Construct an MutableArrayRef from a pointer and length.
305 /*implicit*/ MutableArrayRef(T
*data
, size_t length
)
306 : ArrayRef
<T
>(data
, length
) {}
308 /// Construct an MutableArrayRef from a range.
309 MutableArrayRef(T
*begin
, T
*end
) : ArrayRef
<T
>(begin
, end
) {}
311 /// Construct an MutableArrayRef from a SmallVector.
312 /*implicit*/ MutableArrayRef(SmallVectorImpl
<T
> &Vec
)
313 : ArrayRef
<T
>(Vec
) {}
315 /// Construct a MutableArrayRef from a std::vector.
316 /*implicit*/ MutableArrayRef(std::vector
<T
> &Vec
)
317 : ArrayRef
<T
>(Vec
) {}
319 /// Construct an ArrayRef from a std::array
321 /*implicit*/ constexpr MutableArrayRef(std::array
<T
, N
> &Arr
)
322 : ArrayRef
<T
>(Arr
) {}
324 /// Construct an MutableArrayRef from a C array.
326 /*implicit*/ constexpr MutableArrayRef(T (&Arr
)[N
]) : ArrayRef
<T
>(Arr
) {}
328 T
*data() const { return const_cast<T
*>(ArrayRef
<T
>::data()); }
330 iterator
begin() const { return data(); }
331 iterator
end() const { return data() + this->size(); }
333 reverse_iterator
rbegin() const { return reverse_iterator(end()); }
334 reverse_iterator
rend() const { return reverse_iterator(begin()); }
336 /// front - Get the first element.
338 assert(!this->empty());
342 /// back - Get the last element.
344 assert(!this->empty());
345 return data()[this->size()-1];
348 /// slice(n, m) - Chop off the first N elements of the array, and keep M
349 /// elements in the array.
350 MutableArrayRef
<T
> slice(size_t N
, size_t M
) const {
351 assert(N
+ M
<= this->size() && "Invalid specifier");
352 return MutableArrayRef
<T
>(this->data() + N
, M
);
355 /// slice(n) - Chop off the first N elements of the array.
356 MutableArrayRef
<T
> slice(size_t N
) const {
357 return slice(N
, this->size() - N
);
360 /// Drop the first \p N elements of the array.
361 MutableArrayRef
<T
> drop_front(size_t N
= 1) const {
362 assert(this->size() >= N
&& "Dropping more elements than exist");
363 return slice(N
, this->size() - N
);
366 MutableArrayRef
<T
> drop_back(size_t N
= 1) const {
367 assert(this->size() >= N
&& "Dropping more elements than exist");
368 return slice(0, this->size() - N
);
371 /// Return a copy of *this with the first N elements satisfying the
372 /// given predicate removed.
373 template <class PredicateT
>
374 MutableArrayRef
<T
> drop_while(PredicateT Pred
) const {
375 return MutableArrayRef
<T
>(find_if_not(*this, Pred
), end());
378 /// Return a copy of *this with the first N elements not satisfying
379 /// the given predicate removed.
380 template <class PredicateT
>
381 MutableArrayRef
<T
> drop_until(PredicateT Pred
) const {
382 return MutableArrayRef
<T
>(find_if(*this, Pred
), end());
385 /// Return a copy of *this with only the first \p N elements.
386 MutableArrayRef
<T
> take_front(size_t N
= 1) const {
387 if (N
>= this->size())
389 return drop_back(this->size() - N
);
392 /// Return a copy of *this with only the last \p N elements.
393 MutableArrayRef
<T
> take_back(size_t N
= 1) const {
394 if (N
>= this->size())
396 return drop_front(this->size() - N
);
399 /// Return the first N elements of this Array that satisfy the given
401 template <class PredicateT
>
402 MutableArrayRef
<T
> take_while(PredicateT Pred
) const {
403 return MutableArrayRef
<T
>(begin(), find_if_not(*this, Pred
));
406 /// Return the first N elements of this Array that don't satisfy the
408 template <class PredicateT
>
409 MutableArrayRef
<T
> take_until(PredicateT Pred
) const {
410 return MutableArrayRef
<T
>(begin(), find_if(*this, Pred
));
414 /// @name Operator Overloads
416 T
&operator[](size_t Index
) const {
417 assert(Index
< this->size() && "Invalid index!");
418 return data()[Index
];
422 /// This is a MutableArrayRef that owns its array.
423 template <typename T
> class OwningArrayRef
: public MutableArrayRef
<T
> {
425 OwningArrayRef() = default;
426 OwningArrayRef(size_t Size
) : MutableArrayRef
<T
>(new T
[Size
], Size
) {}
428 OwningArrayRef(ArrayRef
<T
> Data
)
429 : MutableArrayRef
<T
>(new T
[Data
.size()], Data
.size()) {
430 std::copy(Data
.begin(), Data
.end(), this->begin());
433 OwningArrayRef(OwningArrayRef
&&Other
) { *this = std::move(Other
); }
435 OwningArrayRef
&operator=(OwningArrayRef
&&Other
) {
436 delete[] this->data();
437 this->MutableArrayRef
<T
>::operator=(Other
);
438 Other
.MutableArrayRef
<T
>::operator=(MutableArrayRef
<T
>());
442 ~OwningArrayRef() { delete[] this->data(); }
445 /// @name ArrayRef Convenience constructors
448 /// Construct an ArrayRef from a single element.
450 ArrayRef
<T
> makeArrayRef(const T
&OneElt
) {
454 /// Construct an ArrayRef from a pointer and length.
456 ArrayRef
<T
> makeArrayRef(const T
*data
, size_t length
) {
457 return ArrayRef
<T
>(data
, length
);
460 /// Construct an ArrayRef from a range.
462 ArrayRef
<T
> makeArrayRef(const T
*begin
, const T
*end
) {
463 return ArrayRef
<T
>(begin
, end
);
466 /// Construct an ArrayRef from a SmallVector.
467 template <typename T
>
468 ArrayRef
<T
> makeArrayRef(const SmallVectorImpl
<T
> &Vec
) {
472 /// Construct an ArrayRef from a SmallVector.
473 template <typename T
, unsigned N
>
474 ArrayRef
<T
> makeArrayRef(const SmallVector
<T
, N
> &Vec
) {
478 /// Construct an ArrayRef from a std::vector.
480 ArrayRef
<T
> makeArrayRef(const std::vector
<T
> &Vec
) {
484 /// Construct an ArrayRef from a std::array.
485 template <typename T
, std::size_t N
>
486 ArrayRef
<T
> makeArrayRef(const std::array
<T
, N
> &Arr
) {
490 /// Construct an ArrayRef from an ArrayRef (no-op) (const)
491 template <typename T
> ArrayRef
<T
> makeArrayRef(const ArrayRef
<T
> &Vec
) {
495 /// Construct an ArrayRef from an ArrayRef (no-op)
496 template <typename T
> ArrayRef
<T
> &makeArrayRef(ArrayRef
<T
> &Vec
) {
500 /// Construct an ArrayRef from a C array.
501 template<typename T
, size_t N
>
502 ArrayRef
<T
> makeArrayRef(const T (&Arr
)[N
]) {
503 return ArrayRef
<T
>(Arr
);
506 /// Construct a MutableArrayRef from a single element.
508 MutableArrayRef
<T
> makeMutableArrayRef(T
&OneElt
) {
512 /// Construct a MutableArrayRef from a pointer and length.
514 MutableArrayRef
<T
> makeMutableArrayRef(T
*data
, size_t length
) {
515 return MutableArrayRef
<T
>(data
, length
);
519 /// @name ArrayRef Comparison Operators
523 inline bool operator==(ArrayRef
<T
> LHS
, ArrayRef
<T
> RHS
) {
524 return LHS
.equals(RHS
);
528 inline bool operator!=(ArrayRef
<T
> LHS
, ArrayRef
<T
> RHS
) {
529 return !(LHS
== RHS
);
534 template <typename T
> hash_code
hash_value(ArrayRef
<T
> S
) {
535 return hash_combine_range(S
.begin(), S
.end());
538 } // end namespace llvm
540 #endif // LLVM_ADT_ARRAYREF_H