diff options
| -rw-r--r-- | llvm/include/llvm/ADT/ArrayRef.h | 77 | ||||
| -rw-r--r-- | llvm/include/llvm/ADT/STLExtras.h | 5 | ||||
| -rw-r--r-- | llvm/unittests/ADT/ArrayRefTest.cpp | 44 | 
3 files changed, 112 insertions, 14 deletions
diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h index 0349623e5f8..c12688e6dd4 100644 --- a/llvm/include/llvm/ADT/ArrayRef.h +++ b/llvm/include/llvm/ADT/ArrayRef.h @@ -12,6 +12,7 @@  #include "llvm/ADT/Hashing.h"  #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallVector.h"  #include <array>  #include <vector> @@ -165,12 +166,6 @@ namespace llvm {        return std::equal(begin(), end(), RHS.begin());      } -    /// slice(n) - Chop off the first N elements of the array. -    ArrayRef<T> slice(size_t N) const { -      assert(N <= size() && "Invalid specifier"); -      return ArrayRef<T>(data()+N, size()-N); -    } -      /// slice(n, m) - Chop off the first N elements of the array, and keep M      /// elements in the array.      ArrayRef<T> slice(size_t N, size_t M) const { @@ -178,6 +173,9 @@ namespace llvm {        return ArrayRef<T>(data()+N, M);      } +    /// slice(n) - Chop off the first N elements of the array. +    ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); } +      /// \brief Drop the first \p N elements of the array.      ArrayRef<T> drop_front(size_t N = 1) const {        assert(size() >= N && "Dropping more elements than exist"); @@ -190,6 +188,18 @@ namespace llvm {        return slice(0, size() - N);      } +    /// \brief Return a copy of *this with the first N elements satisfying the +    /// given predicate removed. +    template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const { +      return ArrayRef<T>(find_if_not(*this, Pred), end()); +    } + +    /// \brief Return a copy of *this with the first N elements not satisfying +    /// the given predicate removed. +    template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const { +      return ArrayRef<T>(find_if(*this, Pred), end()); +    } +      /// \brief Return a copy of *this with only the first \p N elements.      ArrayRef<T> take_front(size_t N = 1) const {        if (N >= size()) @@ -204,6 +214,18 @@ namespace llvm {        return drop_front(size() - N);      } +    /// \brief Return the first N elements of this Array that satisfy the given +    /// predicate. +    template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const { +      return ArrayRef<T>(begin(), find_if_not(*this, Pred)); +    } + +    /// \brief Return the first N elements of this Array that don't satisfy the +    /// given predicate. +    template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const { +      return ArrayRef<T>(begin(), find_if(*this, Pred)); +    } +      /// @}      /// @name Operator Overloads      /// @{ @@ -317,17 +339,16 @@ namespace llvm {        return data()[this->size()-1];      } -    /// slice(n) - Chop off the first N elements of the array. -    MutableArrayRef<T> slice(size_t N) const { -      assert(N <= this->size() && "Invalid specifier"); -      return MutableArrayRef<T>(data()+N, this->size()-N); -    } -      /// slice(n, m) - Chop off the first N elements of the array, and keep M      /// elements in the array.      MutableArrayRef<T> slice(size_t N, size_t M) const { -      assert(N+M <= this->size() && "Invalid specifier"); -      return MutableArrayRef<T>(data()+N, M); +      assert(N + M <= this->size() && "Invalid specifier"); +      return MutableArrayRef<T>(this->data() + N, M); +    } + +    /// slice(n) - Chop off the first N elements of the array. +    MutableArrayRef<T> slice(size_t N) const { +      return slice(N, this->size() - N);      }      /// \brief Drop the first \p N elements of the array. @@ -341,6 +362,20 @@ namespace llvm {        return slice(0, this->size() - N);      } +    /// \brief Return a copy of *this with the first N elements satisfying the +    /// given predicate removed. +    template <class PredicateT> +    MutableArrayRef<T> drop_while(PredicateT Pred) const { +      return MutableArrayRef<T>(find_if_not(*this, Pred), end()); +    } + +    /// \brief Return a copy of *this with the first N elements not satisfying +    /// the given predicate removed. +    template <class PredicateT> +    MutableArrayRef<T> drop_until(PredicateT Pred) const { +      return MutableArrayRef<T>(find_if(*this, Pred), end()); +    } +      /// \brief Return a copy of *this with only the first \p N elements.      MutableArrayRef<T> take_front(size_t N = 1) const {        if (N >= this->size()) @@ -355,6 +390,20 @@ namespace llvm {        return drop_front(this->size() - N);      } +    /// \brief Return the first N elements of this Array that satisfy the given +    /// predicate. +    template <class PredicateT> +    MutableArrayRef<T> take_while(PredicateT Pred) const { +      return MutableArrayRef<T>(begin(), find_if_not(*this, Pred)); +    } + +    /// \brief Return the first N elements of this Array that don't satisfy the +    /// given predicate. +    template <class PredicateT> +    MutableArrayRef<T> take_until(PredicateT Pred) const { +      return MutableArrayRef<T>(begin(), find_if(*this, Pred)); +    } +      /// @}      /// @name Operator Overloads      /// @{ diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 1d3242dfb07..f11a2fc5943 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -622,6 +622,11 @@ auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {    return std::find_if(Range.begin(), Range.end(), Pred);  } +template <typename R, class PredicateT> +auto find_if_not(R &&Range, PredicateT Pred) -> decltype(Range.begin()) { +  return std::find_if_not(Range.begin(), Range.end(), Pred); +} +  /// Provide wrappers to std::remove_if which take ranges instead of having to  /// pass begin/end explicitly.  template<typename R, class UnaryPredicate> diff --git a/llvm/unittests/ADT/ArrayRefTest.cpp b/llvm/unittests/ADT/ArrayRefTest.cpp index ca75800f092..65b4cbcd668 100644 --- a/llvm/unittests/ADT/ArrayRefTest.cpp +++ b/llvm/unittests/ADT/ArrayRefTest.cpp @@ -102,6 +102,28 @@ TEST(ArrayRefTest, DropFront) {    EXPECT_EQ(1U, AR3.drop_front(AR3.size() - 1).size());  } +TEST(ArrayRefTest, DropWhile) { +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; +  ArrayRef<int> AR1(TheNumbers); +  ArrayRef<int> Expected = AR1.drop_front(3); +  EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 == 1; })); + +  EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; })); +  EXPECT_EQ(ArrayRef<int>(), +            AR1.drop_while([](const int &N) { return N > 0; })); +} + +TEST(ArrayRefTest, DropUntil) { +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; +  ArrayRef<int> AR1(TheNumbers); +  ArrayRef<int> Expected = AR1.drop_front(3); +  EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 == 0; })); + +  EXPECT_EQ(ArrayRef<int>(), +            AR1.drop_until([](const int &N) { return N < 0; })); +  EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; })); +} +  TEST(ArrayRefTest, TakeBack) {    static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};    ArrayRef<int> AR1(TheNumbers); @@ -116,6 +138,28 @@ TEST(ArrayRefTest, TakeFront) {    EXPECT_TRUE(AR1.take_front(2).equals(AR2));  } +TEST(ArrayRefTest, TakeWhile) { +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; +  ArrayRef<int> AR1(TheNumbers); +  ArrayRef<int> Expected = AR1.take_front(3); +  EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 == 1; })); + +  EXPECT_EQ(ArrayRef<int>(), +            AR1.take_while([](const int &N) { return N < 0; })); +  EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; })); +} + +TEST(ArrayRefTest, TakeUntil) { +  static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; +  ArrayRef<int> AR1(TheNumbers); +  ArrayRef<int> Expected = AR1.take_front(3); +  EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 == 0; })); + +  EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; })); +  EXPECT_EQ(ArrayRef<int>(), +            AR1.take_until([](const int &N) { return N > 0; })); +} +  TEST(ArrayRefTest, Equals) {    static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};    ArrayRef<int> AR1(A1);  | 

