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