Index: include/llvm/ADT/StringRef.h =================================================================== --- include/llvm/ADT/StringRef.h +++ include/llvm/ADT/StringRef.h @@ -496,6 +496,28 @@ return drop_front(size() - N); } + template + LLVM_ATTRIBUTE_UNUSED_RESULT StringRef take_while(Func F) const { + StringRef S(*this); + while (!S.empty()) { + if (!F(S.front())) + break; + S = S.drop_front(); + } + return drop_back(S.size()); + } + + template + LLVM_ATTRIBUTE_UNUSED_RESULT StringRef take_until(Func F) const { + StringRef S(*this); + while (!S.empty()) { + if (F(S.front())) + break; + S = S.drop_front(); + } + return drop_back(S.size()); + } + /// Return a StringRef equal to 'this' but with the first \p N elements /// dropped. LLVM_ATTRIBUTE_ALWAYS_INLINE @@ -514,6 +536,28 @@ return substr(0, size()-N); } + template + LLVM_ATTRIBUTE_UNUSED_RESULT StringRef drop_while(Func F) const { + StringRef S(*this); + while (!S.empty()) { + if (!F(S.front())) + break; + S = S.drop_front(); + } + return S; + } + + template + LLVM_ATTRIBUTE_UNUSED_RESULT StringRef drop_until(Func F) const { + StringRef S(*this); + while (!S.empty()) { + if (F(S.front())) + break; + S = S.drop_front(); + } + return S; + } + /// Returns true if this StringRef has the given prefix and removes that /// prefix. LLVM_ATTRIBUTE_ALWAYS_INLINE Index: unittests/ADT/StringRefTest.cpp =================================================================== --- unittests/ADT/StringRefTest.cpp +++ unittests/ADT/StringRefTest.cpp @@ -864,4 +864,44 @@ EXPECT_TRUE(Taken.empty()); } +TEST(StringRefTest, TakeWhileUntil) { + StringRef Test("String With 1 Number"); + + StringRef Taken = Test.take_while(::isdigit); + EXPECT_EQ("", Taken); + + Taken = Test.take_until(::isdigit); + EXPECT_EQ("String With ", Taken); + + Taken = Test.take_while([](char c) { return true; }); + EXPECT_EQ(Test, Taken); + + Taken = Test.take_until([](char c) { return true; }); + EXPECT_EQ("", Taken); + + Test = ""; + Taken = Test.take_while([](char c) { return true; }); + EXPECT_EQ("", Taken); +} + +TEST(StringRefTest, DropWhileUntil) { + StringRef Test("String With 1 Number"); + + StringRef Taken = Test.drop_while(::isdigit); + EXPECT_EQ(Test, Taken); + + Taken = Test.drop_until(::isdigit); + EXPECT_EQ("1 Number", Taken); + + Taken = Test.drop_while([](char c) { return true; }); + EXPECT_EQ("", Taken); + + Taken = Test.drop_until([](char c) { return true; }); + EXPECT_EQ(Test, Taken); + + Test = ""; + Taken = Test.drop_while([](char c) { return true; }); + EXPECT_EQ("", Taken); +} + } // end anonymous namespace