<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Nov 12, 2016 at 9:17 AM, Zachary Turner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: zturner<br>
Date: Sat Nov 12 11:17:12 2016<br>
New Revision: 286724<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=286724&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=286724&view=rev</a><br>
Log:<br>
[Support] Add StringRef::find_lower and contains_lower.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D25299" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D25299</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/ADT/<wbr>StringRef.h<br>
    llvm/trunk/lib/Support/<wbr>StringRef.cpp<br>
    llvm/trunk/unittests/ADT/<wbr>StringRefTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/ADT/<wbr>StringRef.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/StringRef.h?rev=286724&r1=286723&r2=286724&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/include/<wbr>llvm/ADT/StringRef.h?rev=<wbr>286724&r1=286723&r2=286724&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/ADT/<wbr>StringRef.h (original)<br>
+++ llvm/trunk/include/llvm/ADT/<wbr>StringRef.h Sat Nov 12 11:17:12 2016<br>
@@ -286,6 +286,12 @@ namespace llvm {<br>
       return npos;<br>
     }<br>
<br>
+    /// Search for the first character \p C in the string, ignoring case.<br>
+    ///<br>
+    /// \returns The index of the first occurrence of \p C, or npos if not<br>
+    /// found.<br>
+    size_t find_lower(char C, size_t From = 0) const;<br>
+<br>
     /// Search for the first character satisfying the predicate \p F<br>
     ///<br>
     /// \returns The index of the first character satisfying \p F starting from<br>
@@ -318,6 +324,12 @@ namespace llvm {<br>
     /// found.<br>
     size_t find(StringRef Str, size_t From = 0) const;<br>
<br>
+    /// Search for the first string \p Str in the string, ignoring case.<br>
+    ///<br>
+    /// \returns The index of the first occurrence of \p Str, or npos if not<br>
+    /// found.<br>
+    size_t find_lower(StringRef Str, size_t From = 0) const;<br>
+<br>
     /// Search for the last character \p C in the string.<br>
     ///<br>
     /// \returns The index of the last occurrence of \p C, or npos if not<br>
@@ -333,12 +345,24 @@ namespace llvm {<br>
       return npos;<br>
     }<br>
<br>
+    /// Search for the last character \p C in the string, ignoring case.<br>
+    ///<br>
+    /// \returns The index of the last occurrence of \p C, or npos if not<br>
+    /// found.<br>
+    size_t rfind_lower(char C, size_t From = npos) const;<br>
+<br>
     /// Search for the last string \p Str in the string.<br>
     ///<br>
     /// \returns The index of the last occurrence of \p Str, or npos if not<br>
     /// found.<br>
     size_t rfind(StringRef Str) const;<br>
<br>
+    /// Search for the last string \p Str in the string, ignoring case.<br>
+    ///<br>
+    /// \returns The index of the last occurrence of \p Str, or npos if not<br>
+    /// found.<br>
+    size_t rfind_lower(StringRef Str) const;<br>
+<br>
     /// Find the first character in the string that is \p C, or npos if not<br>
     /// found. Same as find.<br>
     size_t find_first_of(char C, size_t From = 0) const {<br>
@@ -393,6 +417,18 @@ namespace llvm {<br>
     LLVM_ATTRIBUTE_ALWAYS_INLINE<br>
     bool contains(char C) const { return find_first_of(C) != npos; }<br>
<br>
+    /// Return true if the given string is a substring of *this, and false<br>
+    /// otherwise.<br>
+    LLVM_ATTRIBUTE_ALWAYS_INLINE<br>
+    bool contains_lower(StringRef Other) const {<br>
+      return find_lower(Other) != npos;<br>
+    }<br>
+<br>
+    /// Return true if the given character is contained in *this, and false<br>
+    /// otherwise.<br>
+    LLVM_ATTRIBUTE_ALWAYS_INLINE<br>
+    bool contains_lower(char C) const { return find_lower(C) != npos; }<br>
+<br>
     /// @}<br>
     /// @name Helpful Algorithms<br>
     /// @{<br>
<br>
Modified: llvm/trunk/lib/Support/<wbr>StringRef.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/StringRef.cpp?rev=286724&r1=286723&r2=286724&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Support/StringRef.cpp?rev=<wbr>286724&r1=286723&r2=286724&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Support/<wbr>StringRef.cpp (original)<br>
+++ llvm/trunk/lib/Support/<wbr>StringRef.cpp Sat Nov 12 11:17:12 2016<br>
@@ -69,6 +69,11 @@ bool StringRef::endswith_lower(<wbr>StringRef<br>
       ascii_strncasecmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;<br>
 }<br>
<br>
+size_t StringRef::find_lower(char C, size_t From) const {<br>
+  char L = ascii_tolower(C);<br>
+  return find_if([L](char D) { return ascii_tolower(D) == L; }, From);<br>
+}<br>
+<br>
 /// compare_numeric - Compare strings, handle embedded numbers.<br>
 int StringRef::compare_numeric(<wbr>StringRef RHS) const {<br>
   for (size_t I = 0, E = std::min(Length, RHS.Length); I != E; ++I) {<br>
@@ -182,6 +187,28 @@ size_t StringRef::find(StringRef Str, si<br>
   return npos;<br>
 }<br>
<br>
+size_t StringRef::find_lower(<wbr>StringRef Str, size_t From) const {<br>
+  StringRef This = substr(From);<br>
+  while (This.size() >= Str.size()) {<br>
+    if (This.startswith_lower(Str))<br>
+      return From;<br>
+    This = This.drop_front();<br>
+    ++From;<br>
+  }<br>
+  return npos;<br>
+}<br></blockquote><div><br></div><div>This is a pretty naive algorithm. Isn't this too slow?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+size_t StringRef::rfind_lower(char C, size_t From) const {<br>
+  From = std::min(From, Length);<br>
+  size_t i = From;<br>
+  while (i != 0) {<br>
+    --i;<br>
+    if (ascii_tolower(Data[i]) == ascii_tolower(C))<br>
+      return i;<br>
+  }<br>
+  return npos;<br>
+}<br>
+<br>
 /// rfind - Search for the last string \arg Str in the string.<br>
 ///<br>
 /// \return - The index of the last occurrence of \arg Str, or npos if not<br>
@@ -196,6 +223,18 @@ size_t StringRef::rfind(StringRef Str) c<br>
       return i;<br>
   }<br>
   return npos;<br>
+}<br>
+<br>
+size_t StringRef::rfind_lower(<wbr>StringRef Str) const {<br>
+  size_t N = Str.size();<br>
+  if (N > Length)<br>
+    return npos;<br>
+  for (size_t i = Length - N + 1, e = 0; i != e;) {<br>
+    --i;<br>
+    if (substr(i, N).equals_lower(Str))<br>
+      return i;<br>
+  }<br>
+  return npos;<br>
 }<br>
<br>
 /// find_first_of - Find the first character in the string that is in \arg<br>
<br>
Modified: llvm/trunk/unittests/ADT/<wbr>StringRefTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/StringRefTest.cpp?rev=286724&r1=286723&r2=286724&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/unittests/<wbr>ADT/StringRefTest.cpp?rev=<wbr>286724&r1=286723&r2=286724&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/unittests/ADT/<wbr>StringRefTest.cpp (original)<br>
+++ llvm/trunk/unittests/ADT/<wbr>StringRefTest.cpp Sat Nov 12 11:17:12 2016<br>
@@ -410,21 +410,58 @@ TEST(StringRefTest, ConsumeBack) {<br>
 }<br>
<br>
 TEST(StringRefTest, Find) {<br>
-  StringRef Str("hello");<br>
-  EXPECT_EQ(2U, Str.find('l'));<br>
-  EXPECT_EQ(StringRef::npos, Str.find('z'));<br>
-  EXPECT_EQ(StringRef::npos, Str.find("helloworld"));<br>
-  EXPECT_EQ(0U, Str.find("hello"));<br>
-  EXPECT_EQ(1U, Str.find("ello"));<br>
-  EXPECT_EQ(StringRef::npos, Str.find("zz"));<br>
-  EXPECT_EQ(2U, Str.find("ll", 2));<br>
-  EXPECT_EQ(StringRef::npos, Str.find("ll", 3));<br>
-  EXPECT_EQ(0U, Str.find(""));<br>
-  StringRef LongStr("hellx xello hell ello world foo bar hello");<br>
-  EXPECT_EQ(36U, LongStr.find("hello"));<br>
-  EXPECT_EQ(28U, LongStr.find("foo"));<br>
-  EXPECT_EQ(12U, LongStr.find("hell", 2));<br>
-  EXPECT_EQ(0U, LongStr.find(""));<br>
+  StringRef Str("helloHELLO");<br>
+  StringRef LongStr("hellx xello hell ello world foo bar hello HELLO");<br>
+<br>
+  struct {<br>
+    StringRef Str;<br>
+    char C;<br>
+    std::size_t From;<br>
+    std::size_t Pos;<br>
+    std::size_t LowerPos;<br>
+  } CharExpectations[] = {<br>
+      {Str, 'h', 0U, 0U, 0U},<br>
+      {Str, 'e', 0U, 1U, 1U},<br>
+      {Str, 'l', 0U, 2U, 2U},<br>
+      {Str, 'l', 3U, 3U, 3U},<br>
+      {Str, 'o', 0U, 4U, 4U},<br>
+      {Str, 'L', 0U, 7U, 2U},<br>
+      {Str, 'z', 0U, StringRef::npos, StringRef::npos},<br>
+  };<br>
+<br>
+  struct {<br>
+    StringRef Str;<br>
+    llvm::StringRef S;<br>
+    std::size_t From;<br>
+    std::size_t Pos;<br>
+    std::size_t LowerPos;<br>
+  } StrExpectations[] = {<br>
+      {Str, "helloword", 0, StringRef::npos, StringRef::npos},<br>
+      {Str, "hello", 0, 0U, 0U},<br>
+      {Str, "ello", 0, 1U, 1U},<br>
+      {Str, "zz", 0, StringRef::npos, StringRef::npos},<br>
+      {Str, "ll", 2U, 2U, 2U},<br>
+      {Str, "ll", 3U, StringRef::npos, 7U},<br>
+      {Str, "LL", 2U, 7U, 2U},<br>
+      {Str, "LL", 3U, 7U, 7U},<br>
+      {Str, "", 0U, 0U, 0U},<br>
+      {LongStr, "hello", 0U, 36U, 36U},<br>
+      {LongStr, "foo", 0U, 28U, 28U},<br>
+      {LongStr, "hell", 2U, 12U, 12U},<br>
+      {LongStr, "HELL", 2U, 42U, 12U},<br>
+      {LongStr, "", 0U, 0U, 0U}};<br>
+<br>
+  for (auto &E : CharExpectations) {<br>
+    EXPECT_EQ(E.Pos, E.Str.find(E.C, E.From));<br>
+    EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.C, E.From));<br>
+    EXPECT_EQ(E.LowerPos, E.Str.find_lower(toupper(E.C), E.From));<br>
+  }<br>
+<br>
+  for (auto &E : StrExpectations) {<br>
+    EXPECT_EQ(E.Pos, E.Str.find(E.S, E.From));<br>
+    EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.S, E.From));<br>
+    EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.S.upper(), E.From));<br>
+  }<br>
<br>
   EXPECT_EQ(3U, Str.rfind('l'));<br>
   EXPECT_EQ(StringRef::npos, Str.rfind('z'));<br>
@@ -433,10 +470,19 @@ TEST(StringRefTest, Find) {<br>
   EXPECT_EQ(1U, Str.rfind("ello"));<br>
   EXPECT_EQ(StringRef::npos, Str.rfind("zz"));<br>
<br>
+  EXPECT_EQ(8U, Str.rfind_lower('l'));<br>
+  EXPECT_EQ(8U, Str.rfind_lower('L'));<br>
+  EXPECT_EQ(StringRef::npos, Str.rfind_lower('z'));<br>
+  EXPECT_EQ(StringRef::npos, Str.rfind_lower("HELLOWORLD"))<wbr>;<br>
+  EXPECT_EQ(5U, Str.rfind("HELLO"));<br>
+  EXPECT_EQ(6U, Str.rfind("ELLO"));<br>
+  EXPECT_EQ(StringRef::npos, Str.rfind("ZZ"));<br>
+<br>
   EXPECT_EQ(2U, Str.find_first_of('l'));<br>
   EXPECT_EQ(1U, Str.find_first_of("el"));<br>
   EXPECT_EQ(StringRef::npos, Str.find_first_of("xyz"));<br>
<br>
+  Str = "hello";<br>
   EXPECT_EQ(1U, Str.find_first_not_of('h'));<br>
   EXPECT_EQ(4U, Str.find_first_not_of("hel"));<br>
   EXPECT_EQ(StringRef::npos, Str.find_first_not_of("hello")<wbr>);<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>