[llvm] r287722 - Add some searching functions for ArrayRef<T>.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 22 15:22:19 PST 2016


Author: zturner
Date: Tue Nov 22 17:22:19 2016
New Revision: 287722

URL: http://llvm.org/viewvc/llvm-project?rev=287722&view=rev
Log:
Add some searching functions for ArrayRef<T>.

Differential Revision: https://reviews.llvm.org/D26999

Modified:
    llvm/trunk/include/llvm/ADT/ArrayRef.h
    llvm/trunk/include/llvm/ADT/STLExtras.h
    llvm/trunk/unittests/ADT/ArrayRefTest.cpp

Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ArrayRef.h?rev=287722&r1=287721&r2=287722&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/ArrayRef.h (original)
+++ llvm/trunk/include/llvm/ADT/ArrayRef.h Tue Nov 22 17:22:19 2016
@@ -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
     /// @{

Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=287722&r1=287721&r2=287722&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
+++ llvm/trunk/include/llvm/ADT/STLExtras.h Tue Nov 22 17:22:19 2016
@@ -622,6 +622,11 @@ auto find_if(R &&Range, const T &Pred) -
   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>

Modified: llvm/trunk/unittests/ADT/ArrayRefTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ArrayRefTest.cpp?rev=287722&r1=287721&r2=287722&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/ArrayRefTest.cpp (original)
+++ llvm/trunk/unittests/ADT/ArrayRefTest.cpp Tue Nov 22 17:22:19 2016
@@ -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);




More information about the llvm-commits mailing list