From f6b656853644a058534bffb0708c2e95347bd233 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Thu, 15 Apr 2021 15:31:15 +0000 Subject: [PATCH] [libc] Add slice/take/drop methods to ArrayRef Add various methods from llvm::ArrayRef. Refactor implementation to remove code duplication. Differential Revision: https://reviews.llvm.org/D100569 --- libc/utils/CPP/ArrayRef.h | 102 +++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/libc/utils/CPP/ArrayRef.h b/libc/utils/CPP/ArrayRef.h index bad415e..7a2ea09 100644 --- a/libc/utils/CPP/ArrayRef.h +++ b/libc/utils/CPP/ArrayRef.h @@ -20,74 +20,82 @@ namespace cpp { // on the implementations of the types with the same names in // llvm/ADT/ArrayRef.h. The implementations in this file are of a limited // functionality, but can be extended in an as needed basis. - -template class ArrayRef { +namespace internal { +template class ArrayRefBase { public: - using iterator = const T *; - -private: - const T *Data = nullptr; - size_t Length = 0; + using iterator = T *; + using pointer = T *; + using reference = T &; -public: - ArrayRef() = default; + ArrayRefBase() = default; // From Array. template - ArrayRef(const Array &Arr) : Data(Arr.Data), Length(N) {} + ArrayRefBase(Array &Arr) : Data(Arr.Data), Length(N) {} - // Construct an ArrayRef from a single element. - explicit ArrayRef(const T &OneElt) : Data(&OneElt), Length(1) {} + // Construct an ArrayRefBase from a single element. + explicit ArrayRefBase(T &OneElt) : Data(&OneElt), Length(1) {} - // Construct an ArrayRef from a pointer and length. - ArrayRef(const T *data, size_t length) : Data(data), Length(length) {} + // Construct an ArrayRefBase from a pointer and length. + ArrayRefBase(pointer Data, size_t Length) : Data(Data), Length(Length) {} - // Construct an ArrayRef from a range. - ArrayRef(const T *begin, const T *end) : Data(begin), Length(end - begin) {} + // Construct an ArrayRefBase from a range. + ArrayRefBase(iterator Begin, iterator End) + : Data(Begin), Length(End - Begin) {} - // Construct an ArrayRef from a C array. + // Construct an ArrayRefBase from a C array. template - constexpr ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} + constexpr ArrayRefBase(T (&Arr)[N]) : Data(Arr), Length(N) {} iterator begin() const { return Data; } iterator end() const { return Data + Length; } bool empty() const { return Length == 0; } - const T *data() const { return Data; } + pointer data() const { return Data; } size_t size() const { return Length; } - const T &operator[](size_t Index) const { return Data[Index]; } -}; - -template class MutableArrayRef : public ArrayRef { -public: - using iterator = T *; - - // From Array. - template MutableArrayRef(Array &Arr) : ArrayRef(Arr) {} - - // Construct from a single element. - explicit MutableArrayRef(T &OneElt) : ArrayRef(OneElt) {} - - // Construct from a pointer and length. - MutableArrayRef(T *data, size_t length) : ArrayRef(data, length) {} - - // Construct from a range. - MutableArrayRef(T *begin, T *end) : ArrayRef(begin, end) {} - - // Construct from a C array. - template - constexpr MutableArrayRef(T (&Arr)[N]) : ArrayRef(Arr) {} + reference operator[](size_t Index) const { return Data[Index]; } + + // slice(n, m) - Chop off the first N elements of the array, and keep M + // elements in the array. + ArrayRefBase slice(size_t N, size_t M) const { + return ArrayRefBase(data() + N, M); + } + // slice(n) - Chop off the first N elements of the array. + ArrayRefBase slice(size_t N) const { return slice(N, size() - N); } + + // Drop the first \p N elements of the array. + ArrayRefBase drop_front(size_t N = 1) const { + return slice(N, size() - N); + } + + // Drop the last \p N elements of the array. + ArrayRefBase drop_back(size_t N = 1) const { return slice(0, size() - N); } + + // Return a copy of *this with only the first \p N elements. + ArrayRefBase take_front(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_back(size() - N); + } + + // Return a copy of *this with only the last \p N elements. + ArrayRefBase take_back(size_t N = 1) const { + if (N >= size()) + return *this; + return drop_front(size() - N); + } - T *data() const { return const_cast(ArrayRef::data()); } - - iterator begin() const { return data(); } - iterator end() const { return data() + this->size(); } - - T &operator[](size_t Index) const { return data()[Index]; } +private: + pointer Data = nullptr; + size_t Length = 0; }; +} // namespace internal + +template using ArrayRef = internal::ArrayRefBase; +template using MutableArrayRef = internal::ArrayRefBase; } // namespace cpp } // namespace __llvm_libc -- 2.7.4