From b0940b46edbbe9d3f62d7f6f70330fd87f3507e1 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Fri, 11 May 2012 22:08:50 +0000 Subject: [PATCH] [Support/StringRef] Add find_last_not_of and {r,l,}trim. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156652 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/StringRef.h | 22 ++++++++++++++++++++++ lib/Support/StringRef.cpp | 26 ++++++++++++++++++++++++++ unittests/ADT/StringRefTest.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 76ba66e746c..b54856842c2 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -292,6 +292,16 @@ namespace llvm { /// Note: O(size() + Chars.size()) size_type find_last_of(StringRef Chars, size_t From = npos) const; + /// find_last_not_of - Find the last character in the string that is not + /// \arg C, or npos if not found. + size_type find_last_not_of(char C, size_t From = npos) const; + + /// find_last_not_of - Find the last character in the string that is not in + /// \arg Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_last_not_of(StringRef Chars, size_t From = npos) const; + /// @} /// @name Helpful Algorithms /// @{ @@ -480,6 +490,18 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); } + StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_front(std::min(Length, find_first_not_of(Chars))); + } + + StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const { + return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1)); + } + + StringRef trim(StringRef Chars = " \t\n\v\f\r") const { + return ltrim(Chars).rtrim(Chars); + } + /// @} }; diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index 97af0fff5ee..8aab4b2760e 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/edit_distance.h" + #include using namespace llvm; @@ -230,6 +231,31 @@ StringRef::size_type StringRef::find_last_of(StringRef Chars, return npos; } +/// find_last_not_of - Find the last character in the string that is not +/// \arg C, or npos if not found. +StringRef::size_type StringRef::find_last_not_of(char C, size_t From) const { + for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + if (Data[i] != C) + return i; + return npos; +} + +/// find_last_not_of - Find the last character in the string that is not in +/// \arg Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_last_not_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0, e = Chars.size(); i != e; ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + if (!CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + void StringRef::split(SmallVectorImpl &A, StringRef Separators, int MaxSplit, bool KeepEmpty) const { diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index cc7a7fbe332..315eacbaa40 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -221,6 +221,30 @@ TEST(StringRefTest, Split2) { EXPECT_TRUE(parts == expected); } +TEST(StringRefTest, Trim) { + StringRef Str0("hello"); + StringRef Str1(" hello "); + StringRef Str2(" hello "); + + EXPECT_EQ(StringRef("hello"), Str0.rtrim()); + EXPECT_EQ(StringRef(" hello"), Str1.rtrim()); + EXPECT_EQ(StringRef(" hello"), Str2.rtrim()); + EXPECT_EQ(StringRef("hello"), Str0.ltrim()); + EXPECT_EQ(StringRef("hello "), Str1.ltrim()); + EXPECT_EQ(StringRef("hello "), Str2.ltrim()); + EXPECT_EQ(StringRef("hello"), Str0.trim()); + EXPECT_EQ(StringRef("hello"), Str1.trim()); + EXPECT_EQ(StringRef("hello"), Str2.trim()); + + EXPECT_EQ(StringRef("ello"), Str0.trim("hhhhhhhhhhh")); + + EXPECT_EQ(StringRef(""), StringRef("").trim()); + EXPECT_EQ(StringRef(""), StringRef(" ").trim()); + EXPECT_EQ(StringRef("\0", 1), StringRef(" \0 ", 3).trim()); + EXPECT_EQ(StringRef("\0\0", 2), StringRef("\0\0", 2).trim()); + EXPECT_EQ(StringRef("x"), StringRef("\0\0x\0\0", 5).trim(StringRef("\0", 1))); +} + TEST(StringRefTest, StartsWith) { StringRef Str("hello"); EXPECT_TRUE(Str.startswith("he")); @@ -267,6 +291,10 @@ TEST(StringRefTest, Find) { EXPECT_EQ(1U, Str.find_first_not_of('h')); EXPECT_EQ(4U, Str.find_first_not_of("hel")); EXPECT_EQ(StringRef::npos, Str.find_first_not_of("hello")); + + EXPECT_EQ(3U, Str.find_last_not_of('o')); + EXPECT_EQ(1U, Str.find_last_not_of("lo")); + EXPECT_EQ(StringRef::npos, Str.find_last_not_of("helo")); } TEST(StringRefTest, Count) {