Skip to content

Commit eaf0ada

Browse files
author
Zachary Turner
committedNov 22, 2016
Add some searching functions for ArrayRef<T>.
Differential Revision: https://reviews.llvm.org/D26999 llvm-svn: 287722
1 parent 6c0f25a commit eaf0ada

File tree

3 files changed

+112
-14
lines changed

3 files changed

+112
-14
lines changed
 

‎llvm/include/llvm/ADT/ArrayRef.h

+63-14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "llvm/ADT/Hashing.h"
1414
#include "llvm/ADT/None.h"
15+
#include "llvm/ADT/STLExtras.h"
1516
#include "llvm/ADT/SmallVector.h"
1617
#include <array>
1718
#include <vector>
@@ -165,19 +166,16 @@ namespace llvm {
165166
return std::equal(begin(), end(), RHS.begin());
166167
}
167168

168-
/// slice(n) - Chop off the first N elements of the array.
169-
ArrayRef<T> slice(size_t N) const {
170-
assert(N <= size() && "Invalid specifier");
171-
return ArrayRef<T>(data()+N, size()-N);
172-
}
173-
174169
/// slice(n, m) - Chop off the first N elements of the array, and keep M
175170
/// elements in the array.
176171
ArrayRef<T> slice(size_t N, size_t M) const {
177172
assert(N+M <= size() && "Invalid specifier");
178173
return ArrayRef<T>(data()+N, M);
179174
}
180175

176+
/// slice(n) - Chop off the first N elements of the array.
177+
ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); }
178+
181179
/// \brief Drop the first \p N elements of the array.
182180
ArrayRef<T> drop_front(size_t N = 1) const {
183181
assert(size() >= N && "Dropping more elements than exist");
@@ -190,6 +188,18 @@ namespace llvm {
190188
return slice(0, size() - N);
191189
}
192190

191+
/// \brief Return a copy of *this with the first N elements satisfying the
192+
/// given predicate removed.
193+
template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const {
194+
return ArrayRef<T>(find_if_not(*this, Pred), end());
195+
}
196+
197+
/// \brief Return a copy of *this with the first N elements not satisfying
198+
/// the given predicate removed.
199+
template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const {
200+
return ArrayRef<T>(find_if(*this, Pred), end());
201+
}
202+
193203
/// \brief Return a copy of *this with only the first \p N elements.
194204
ArrayRef<T> take_front(size_t N = 1) const {
195205
if (N >= size())
@@ -204,6 +214,18 @@ namespace llvm {
204214
return drop_front(size() - N);
205215
}
206216

217+
/// \brief Return the first N elements of this Array that satisfy the given
218+
/// predicate.
219+
template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const {
220+
return ArrayRef<T>(begin(), find_if_not(*this, Pred));
221+
}
222+
223+
/// \brief Return the first N elements of this Array that don't satisfy the
224+
/// given predicate.
225+
template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const {
226+
return ArrayRef<T>(begin(), find_if(*this, Pred));
227+
}
228+
207229
/// @}
208230
/// @name Operator Overloads
209231
/// @{
@@ -317,17 +339,16 @@ namespace llvm {
317339
return data()[this->size()-1];
318340
}
319341

320-
/// slice(n) - Chop off the first N elements of the array.
321-
MutableArrayRef<T> slice(size_t N) const {
322-
assert(N <= this->size() && "Invalid specifier");
323-
return MutableArrayRef<T>(data()+N, this->size()-N);
324-
}
325-
326342
/// slice(n, m) - Chop off the first N elements of the array, and keep M
327343
/// elements in the array.
328344
MutableArrayRef<T> slice(size_t N, size_t M) const {
329-
assert(N+M <= this->size() && "Invalid specifier");
330-
return MutableArrayRef<T>(data()+N, M);
345+
assert(N + M <= this->size() && "Invalid specifier");
346+
return MutableArrayRef<T>(this->data() + N, M);
347+
}
348+
349+
/// slice(n) - Chop off the first N elements of the array.
350+
MutableArrayRef<T> slice(size_t N) const {
351+
return slice(N, this->size() - N);
331352
}
332353

333354
/// \brief Drop the first \p N elements of the array.
@@ -341,6 +362,20 @@ namespace llvm {
341362
return slice(0, this->size() - N);
342363
}
343364

365+
/// \brief Return a copy of *this with the first N elements satisfying the
366+
/// given predicate removed.
367+
template <class PredicateT>
368+
MutableArrayRef<T> drop_while(PredicateT Pred) const {
369+
return MutableArrayRef<T>(find_if_not(*this, Pred), end());
370+
}
371+
372+
/// \brief Return a copy of *this with the first N elements not satisfying
373+
/// the given predicate removed.
374+
template <class PredicateT>
375+
MutableArrayRef<T> drop_until(PredicateT Pred) const {
376+
return MutableArrayRef<T>(find_if(*this, Pred), end());
377+
}
378+
344379
/// \brief Return a copy of *this with only the first \p N elements.
345380
MutableArrayRef<T> take_front(size_t N = 1) const {
346381
if (N >= this->size())
@@ -355,6 +390,20 @@ namespace llvm {
355390
return drop_front(this->size() - N);
356391
}
357392

393+
/// \brief Return the first N elements of this Array that satisfy the given
394+
/// predicate.
395+
template <class PredicateT>
396+
MutableArrayRef<T> take_while(PredicateT Pred) const {
397+
return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
398+
}
399+
400+
/// \brief Return the first N elements of this Array that don't satisfy the
401+
/// given predicate.
402+
template <class PredicateT>
403+
MutableArrayRef<T> take_until(PredicateT Pred) const {
404+
return MutableArrayRef<T>(begin(), find_if(*this, Pred));
405+
}
406+
358407
/// @}
359408
/// @name Operator Overloads
360409
/// @{

‎llvm/include/llvm/ADT/STLExtras.h

+5
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,11 @@ auto find_if(R &&Range, const T &Pred) -> decltype(Range.begin()) {
622622
return std::find_if(Range.begin(), Range.end(), Pred);
623623
}
624624

625+
template <typename R, class PredicateT>
626+
auto find_if_not(R &&Range, PredicateT Pred) -> decltype(Range.begin()) {
627+
return std::find_if_not(Range.begin(), Range.end(), Pred);
628+
}
629+
625630
/// Provide wrappers to std::remove_if which take ranges instead of having to
626631
/// pass begin/end explicitly.
627632
template<typename R, class UnaryPredicate>

‎llvm/unittests/ADT/ArrayRefTest.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ TEST(ArrayRefTest, DropFront) {
102102
EXPECT_EQ(1U, AR3.drop_front(AR3.size() - 1).size());
103103
}
104104

105+
TEST(ArrayRefTest, DropWhile) {
106+
static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
107+
ArrayRef<int> AR1(TheNumbers);
108+
ArrayRef<int> Expected = AR1.drop_front(3);
109+
EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 == 1; }));
110+
111+
EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; }));
112+
EXPECT_EQ(ArrayRef<int>(),
113+
AR1.drop_while([](const int &N) { return N > 0; }));
114+
}
115+
116+
TEST(ArrayRefTest, DropUntil) {
117+
static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
118+
ArrayRef<int> AR1(TheNumbers);
119+
ArrayRef<int> Expected = AR1.drop_front(3);
120+
EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 == 0; }));
121+
122+
EXPECT_EQ(ArrayRef<int>(),
123+
AR1.drop_until([](const int &N) { return N < 0; }));
124+
EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; }));
125+
}
126+
105127
TEST(ArrayRefTest, TakeBack) {
106128
static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
107129
ArrayRef<int> AR1(TheNumbers);
@@ -116,6 +138,28 @@ TEST(ArrayRefTest, TakeFront) {
116138
EXPECT_TRUE(AR1.take_front(2).equals(AR2));
117139
}
118140

141+
TEST(ArrayRefTest, TakeWhile) {
142+
static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
143+
ArrayRef<int> AR1(TheNumbers);
144+
ArrayRef<int> Expected = AR1.take_front(3);
145+
EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 == 1; }));
146+
147+
EXPECT_EQ(ArrayRef<int>(),
148+
AR1.take_while([](const int &N) { return N < 0; }));
149+
EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; }));
150+
}
151+
152+
TEST(ArrayRefTest, TakeUntil) {
153+
static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
154+
ArrayRef<int> AR1(TheNumbers);
155+
ArrayRef<int> Expected = AR1.take_front(3);
156+
EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 == 0; }));
157+
158+
EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; }));
159+
EXPECT_EQ(ArrayRef<int>(),
160+
AR1.take_until([](const int &N) { return N > 0; }));
161+
}
162+
119163
TEST(ArrayRefTest, Equals) {
120164
static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};
121165
ArrayRef<int> AR1(A1);

0 commit comments

Comments
 (0)
Please sign in to comment.