[llvm] r282346 - Add some predicated searching functions to StringRef.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 24 21:10:27 PDT 2016


On Sat, Sep 24, 2016 at 8:27 PM, Zachary Turner via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: zturner
> Date: Sat Sep 24 22:27:29 2016
> New Revision: 282346
>
> URL: http://llvm.org/viewvc/llvm-project?rev=282346&view=rev
> Log:
> Add some predicated searching functions to StringRef.
>
> This adds 4 new functions to StringRef, which can be used to
> take or drop characters while a certain condition is met, or
> until a certain condition is met.  They are:
>
> take_while - Return characters until a condition is not met.
> take_until - Return characters until a condition is met.
> drop_while - Remove characters until a condition is not met.
> drop_until - Remove characters until a condition is met.
>
> Internally, all of these functions delegate to two additional
> helper functions which can be used to search for the position
> of a character meeting or not meeting a condition, which are:
>
> find_if - Find the first character matching a predicate.
> find_if_not - Find the first character not matching a predicate.
>
> Differential Revision: https://reviews.llvm.org/D24842
>
> Modified:
>     llvm/trunk/include/llvm/ADT/StringRef.h
>     llvm/trunk/unittests/ADT/StringRefTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/StringRef.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/StringRef.h?rev=282346&r1=282345&r2=282346&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/StringRef.h (original)
> +++ llvm/trunk/include/llvm/ADT/StringRef.h Sat Sep 24 22:27:29 2016
> @@ -10,6 +10,7 @@
>  #ifndef LLVM_ADT_STRINGREF_H
>  #define LLVM_ADT_STRINGREF_H
>
> +#include "llvm/ADT/STLExtras.h"
>  #include "llvm/ADT/iterator_range.h"
>  #include "llvm/Support/Compiler.h"
>  #include <algorithm>
> @@ -276,6 +277,32 @@ namespace llvm {
>        return npos;
>      }
>
> +    /// Search for the first character satisfying the predicate \p F
> +    ///
> +    /// \returns The index of the first character satisfying \p F starting from
> +    /// \p From, or npos if not found.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    size_t find_if(function_ref<bool(char)> F, size_t From = 0) const {
> +      StringRef S = drop_front(From);
> +      while (!S.empty()) {
> +        if (F(S.front()))
> +          return size() - S.size();
> +        S = S.drop_front();
> +      }
> +      return npos;
> +    }
> +
> +    /// Search for the first character not satisfying the predicate \p F
> +    ///
> +    /// \returns The index of the first character not satisfying \p F starting
> +    /// from \p From, or npos if not found.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const {
> +      return find_if([F](char c) { return !F(c); }, From);
> +    }
> +
>      /// Search for the first string \p Str in the string.
>      ///
>      /// \returns The index of the first occurrence of \p Str, or npos if not
> @@ -352,6 +379,9 @@ namespace llvm {
>      LLVM_ATTRIBUTE_ALWAYS_INLINE
>      bool contains(StringRef Other) const { return find(Other) != npos; }
>
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    bool contains(char C) const { return find_first_of(C) != npos; }
> +

I think you forgot to add a comment for this one.

>      /// @}
>      /// @name Helpful Algorithms
>      /// @{
> @@ -496,6 +526,22 @@ namespace llvm {
>        return drop_front(size() - N);
>      }
>
> +    /// Return the longest prefix of 'this' such that every character
> +    /// in the prefix satisfies the given predicate.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    StringRef take_while(function_ref<bool(char)> F) const {
> +      return substr(0, find_if_not(F));
> +    }
> +
> +    /// Return the longest prefix of 'this' such that no character in
> +    /// the prefix satisfies the given predicate.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    StringRef take_until(function_ref<bool(char)> F) const {
> +      return substr(0, find_if(F));
> +    }
> +
>      /// Return a StringRef equal to 'this' but with the first \p N elements
>      /// dropped.
>      LLVM_ATTRIBUTE_ALWAYS_INLINE
> @@ -514,6 +560,22 @@ namespace llvm {
>        return substr(0, size()-N);
>      }
>
> +    /// Return a StringRef equal to 'this', but with all characters satisfying
> +    /// the given predicate dropped from the beginning of the string.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    StringRef drop_while(function_ref<bool(char)> F) const {
> +      return substr(find_if_not(F));
> +    }
> +
> +    /// Return a StringRef equal to 'this', but with all characters not
> +    /// satisfying the given predicate dropped from the beginning of the string.
> +    LLVM_ATTRIBUTE_ALWAYS_INLINE
> +    LLVM_ATTRIBUTE_UNUSED_RESULT
> +    StringRef drop_until(function_ref<bool(char)> F) const {
> +      return substr(find_if(F));
> +    }
> +
>      /// Returns true if this StringRef has the given prefix and removes that
>      /// prefix.
>      LLVM_ATTRIBUTE_ALWAYS_INLINE
>
> Modified: llvm/trunk/unittests/ADT/StringRefTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/StringRefTest.cpp?rev=282346&r1=282345&r2=282346&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ADT/StringRefTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/StringRefTest.cpp Sat Sep 24 22:27:29 2016
> @@ -864,4 +864,60 @@ TEST(StringRefTest, Take) {
>    EXPECT_TRUE(Taken.empty());
>  }
>
> +TEST(StringRefTest, FindIf) {
> +  StringRef Punct("Test.String");
> +  StringRef NoPunct("ABCDEFG");
> +  StringRef Empty;
> +
> +  auto IsPunct = [](char c) { return ::ispunct(c); };
> +  auto IsAlpha = [](char c) { return ::isalpha(c); };
> +  EXPECT_EQ(4, Punct.find_if(IsPunct));
> +  EXPECT_EQ(StringRef::npos, NoPunct.find_if(IsPunct));
> +  EXPECT_EQ(StringRef::npos, Empty.find_if(IsPunct));
> +
> +  EXPECT_EQ(4, Punct.find_if_not(IsAlpha));
> +  EXPECT_EQ(StringRef::npos, NoPunct.find_if_not(IsAlpha));
> +  EXPECT_EQ(StringRef::npos, Empty.find_if_not(IsAlpha));
> +}
> +
> +TEST(StringRefTest, TakeWhileUntil) {
> +  StringRef Test("String With 1 Number");
> +
> +  StringRef Taken = Test.take_while([](char c) { return ::isdigit(c); });
> +  EXPECT_EQ("", Taken);
> +
> +  Taken = Test.take_until([](char c) { return ::isdigit(c); });
> +  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([](char c) { return ::isdigit(c); });
> +  EXPECT_EQ(Test, Taken);
> +
> +  Taken = Test.drop_until([](char c) { return ::isdigit(c); });
> +  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);
> +
> +  StringRef EmptyString = "";
> +  Taken = EmptyString.drop_while([](char c) { return true; });
> +  EXPECT_EQ("", Taken);
> +}
> +
>  } // end anonymous namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits

-- 
Davide

"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare


More information about the llvm-commits mailing list