1 //===-- Self contained ArrayRef type ----------------------------*- 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_LIBC_UTILS_CPP_ARRAYREF_H 10 #define LLVM_LIBC_UTILS_CPP_ARRAYREF_H 11 12 #include "Array.h" 13 #include "TypeTraits.h" //RemoveCVType 14 15 #include <stddef.h> // For size_t. 16 17 namespace __llvm_libc { 18 namespace cpp { 19 20 // The implementations of ArrayRef and MutableArrayRef in this file are based 21 // on the implementations of the types with the same names in 22 // llvm/ADT/ArrayRef.h. The implementations in this file are of a limited 23 // functionality, but can be extended in an as needed basis. 24 namespace internal { 25 template <typename QualifiedT> class ArrayRefBase { 26 public: 27 using value_type = RemoveCVType<QualifiedT>; 28 using pointer = value_type *; 29 using const_pointer = const value_type *; 30 using reference = value_type &; 31 using const_reference = const value_type &; 32 using iterator = const_pointer; 33 using const_iterator = const_pointer; 34 using size_type = size_t; 35 using difference_type = ptrdiff_t; 36 37 ArrayRefBase() = default; 38 39 // Construct an ArrayRefBase from a single element. ArrayRefBase(QualifiedT & OneElt)40 explicit ArrayRefBase(QualifiedT &OneElt) : Data(&OneElt), Length(1) {} 41 42 // Construct an ArrayRefBase from a pointer and length. ArrayRefBase(QualifiedT * Data,size_t Length)43 ArrayRefBase(QualifiedT *Data, size_t Length) : Data(Data), Length(Length) {} 44 45 // Construct an ArrayRefBase from a range. ArrayRefBase(QualifiedT * Begin,QualifiedT * End)46 ArrayRefBase(QualifiedT *Begin, QualifiedT *End) 47 : Data(Begin), Length(End - Begin) {} 48 49 // Construct an ArrayRefBase from a C array. 50 template <size_t N> ArrayRefBase(QualifiedT (& Arr)[N])51 constexpr ArrayRefBase(QualifiedT (&Arr)[N]) : Data(Arr), Length(N) {} 52 data()53 QualifiedT *data() const { return Data; } size()54 size_t size() const { return Length; } 55 begin()56 auto begin() const { return data(); } end()57 auto end() const { return data() + size(); } 58 empty()59 bool empty() const { return size() == 0; } 60 61 auto operator[](size_t Index) const { return data()[Index]; } 62 63 // slice(n, m) - Chop off the first N elements of the array, and keep M 64 // elements in the array. slice(size_t N,size_t M)65 auto slice(size_t N, size_t M) const { return ArrayRefBase(data() + N, M); } 66 // slice(n) - Chop off the first N elements of the array. slice(size_t N)67 auto slice(size_t N) const { return slice(N, size() - N); } 68 69 // Drop the first \p N elements of the array. 70 auto drop_front(size_t N = 1) const { return slice(N, size() - N); } 71 72 // Drop the last \p N elements of the array. 73 auto drop_back(size_t N = 1) const { return slice(0, size() - N); } 74 75 // Return a copy of *this with only the first \p N elements. 76 auto take_front(size_t N = 1) const { 77 if (N >= size()) 78 return *this; 79 return drop_back(size() - N); 80 } 81 82 // Return a copy of *this with only the last \p N elements. 83 auto take_back(size_t N = 1) const { 84 if (N >= size()) 85 return *this; 86 return drop_front(size() - N); 87 } 88 89 // equals - Check for element-wise equality. equals(ArrayRefBase<QualifiedT> RHS)90 bool equals(ArrayRefBase<QualifiedT> RHS) const { 91 if (Length != RHS.Length) 92 return false; 93 auto First1 = begin(); 94 auto Last1 = end(); 95 auto First2 = RHS.begin(); 96 for (; First1 != Last1; ++First1, ++First2) { 97 if (!(*First1 == *First2)) { 98 return false; 99 } 100 } 101 return true; 102 } 103 104 private: 105 QualifiedT *Data = nullptr; 106 size_t Length = 0; 107 }; 108 } // namespace internal 109 110 template <typename T> struct ArrayRef : public internal::ArrayRefBase<const T> { 111 private: 112 static_assert(IsSameV<T, RemoveCVType<T>>, 113 "ArrayRef must have a non-const, non-volatile value_type"); 114 using Impl = internal::ArrayRefBase<const T>; 115 using Impl::Impl; 116 117 public: 118 // From Array. ArrayRefArrayRef119 template <size_t N> ArrayRef(const Array<T, N> &Arr) : Impl(Arr.Data, N) {} 120 }; 121 122 template <typename T> 123 struct MutableArrayRef : public internal::ArrayRefBase<T> { 124 private: 125 static_assert( 126 IsSameV<T, RemoveCVType<T>>, 127 "MutableArrayRef must have a non-const, non-volatile value_type"); 128 using Impl = internal::ArrayRefBase<T>; 129 using Impl::Impl; 130 131 public: 132 // From Array. MutableArrayRefMutableArrayRef133 template <size_t N> MutableArrayRef(Array<T, N> &Arr) : Impl(Arr.Data, N) {} 134 }; 135 136 } // namespace cpp 137 } // namespace __llvm_libc 138 139 #endif // LLVM_LIBC_UTILS_CPP_ARRAYREF_H 140