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