Add StringRef::{rfind, rsplit}

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82087 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2009-09-16 22:38:48 +00:00
parent 358f1ef765
commit e65512809a
4 changed files with 150 additions and 42 deletions

View File

@ -147,7 +147,7 @@ namespace llvm {
/// @name String Searching /// @name String Searching
/// @{ /// @{
/// find - Search for the character \arg C in the string. /// find - Search for the first character \arg C in the string.
/// ///
/// \return - The index of the first occurence of \arg C, or npos if not /// \return - The index of the first occurence of \arg C, or npos if not
/// found. /// found.
@ -158,7 +158,7 @@ namespace llvm {
return npos; return npos;
} }
/// find - Search for the string \arg Str in the string. /// find - Search for the first string \arg Str in the string.
/// ///
/// \return - The index of the first occurence of \arg Str, or npos if not /// \return - The index of the first occurence of \arg Str, or npos if not
/// found. /// found.
@ -172,6 +172,35 @@ namespace llvm {
return npos; return npos;
} }
/// rfind - Search for the last character \arg C in the string.
///
/// \return - The index of the last occurence of \arg C, or npos if not
/// found.
size_t rfind(char C) const {
for (size_t i = Length, e = 0; i != e;) {
--i;
if (Data[i] == C)
return i;
}
return npos;
}
/// rfind - Search for the last string \arg Str in the string.
///
/// \return - The index of the last occurence of \arg Str, or npos if not
/// found.
size_t rfind(const StringRef &Str) const {
size_t N = Str.size();
if (N > Length)
return npos;
for (size_t i = Length - N + 1, e = 0; i != e;) {
--i;
if (substr(i, N).equals(Str))
return i;
}
return npos;
}
/// count - Return the number of occurrences of \arg C in the string. /// count - Return the number of occurrences of \arg C in the string.
size_t count(char C) const { size_t count(char C) const {
size_t Count = 0; size_t Count = 0;
@ -245,6 +274,23 @@ namespace llvm {
return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
} }
/// rsplit - Split into two substrings around the last occurence of a
/// separator character.
///
/// If \arg Separator is in the string, then the result is a pair (LHS, RHS)
/// such that (*this == LHS + Separator + RHS) is true and RHS is
/// minimal. If \arg Separator is not in the string, then the result is a
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
///
/// \param Separator - The character to split on.
/// \return - The split substrings.
std::pair<StringRef, StringRef> rsplit(char Separator) const {
size_t Idx = rfind(Separator);
if (Idx == npos)
return std::make_pair(*this, StringRef());
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
}
/// @} /// @}
}; };

View File

@ -27,6 +27,7 @@ add_llvm_library(LLVMSupport
StringExtras.cpp StringExtras.cpp
StringMap.cpp StringMap.cpp
StringPool.cpp StringPool.cpp
StringRef.cpp
SystemUtils.cpp SystemUtils.cpp
TargetRegistry.cpp TargetRegistry.cpp
Timer.cpp Timer.cpp

13
lib/Support/StringRef.cpp Normal file
View File

@ -0,0 +1,13 @@
//===-- StringRef.cpp - Lightweight String References ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
using namespace llvm;
const size_t StringRef::npos;

View File

@ -14,18 +14,29 @@ using namespace llvm;
namespace { namespace {
std::ostream &operator<<(std::ostream &OS, const StringRef &S) {
OS << S;
return OS;
}
std::ostream &operator<<(std::ostream &OS,
const std::pair<StringRef, StringRef> &P) {
OS << "(" << P.first << ", " << P.second << ")";
return OS;
}
TEST(StringRefTest, Construction) { TEST(StringRefTest, Construction) {
EXPECT_TRUE(StringRef() == ""); EXPECT_EQ("", StringRef());
EXPECT_TRUE(StringRef("hello") == "hello"); EXPECT_EQ("hello", StringRef("hello"));
EXPECT_TRUE(StringRef("hello world", 5) == "hello"); EXPECT_EQ("hello", StringRef("hello world", 5));
EXPECT_TRUE(StringRef(std::string("hello")) == "hello"); EXPECT_EQ("hello", StringRef(std::string("hello")));
} }
TEST(StringRefTest, Iteration) { TEST(StringRefTest, Iteration) {
StringRef S("hello"); StringRef S("hello");
const char *p = "hello"; const char *p = "hello";
for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p) for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p)
EXPECT_TRUE(*p == *it); EXPECT_EQ(*it, *p);
} }
TEST(StringRefTest, StringOps) { TEST(StringRefTest, StringOps) {
@ -41,7 +52,7 @@ TEST(StringRefTest, StringOps) {
} }
TEST(StringRefTest, Operators) { TEST(StringRefTest, Operators) {
EXPECT_TRUE(StringRef() == ""); EXPECT_EQ("", StringRef());
EXPECT_TRUE(StringRef("aab") < StringRef("aad")); EXPECT_TRUE(StringRef("aab") < StringRef("aad"));
EXPECT_FALSE(StringRef("aab") < StringRef("aab")); EXPECT_FALSE(StringRef("aab") < StringRef("aab"));
EXPECT_TRUE(StringRef("aab") <= StringRef("aab")); EXPECT_TRUE(StringRef("aab") <= StringRef("aab"));
@ -50,58 +61,95 @@ TEST(StringRefTest, Operators) {
EXPECT_FALSE(StringRef("aab") > StringRef("aab")); EXPECT_FALSE(StringRef("aab") > StringRef("aab"));
EXPECT_TRUE(StringRef("aab") >= StringRef("aab")); EXPECT_TRUE(StringRef("aab") >= StringRef("aab"));
EXPECT_FALSE(StringRef("aaa") >= StringRef("aab")); EXPECT_FALSE(StringRef("aaa") >= StringRef("aab"));
EXPECT_TRUE(StringRef("aab") == StringRef("aab")); EXPECT_EQ(StringRef("aab"), StringRef("aab"));
EXPECT_FALSE(StringRef("aab") == StringRef("aac")); EXPECT_FALSE(StringRef("aab") == StringRef("aac"));
EXPECT_FALSE(StringRef("aab") != StringRef("aab")); EXPECT_FALSE(StringRef("aab") != StringRef("aab"));
EXPECT_TRUE(StringRef("aab") != StringRef("aac")); EXPECT_TRUE(StringRef("aab") != StringRef("aac"));
EXPECT_EQ('a', StringRef("aab")[1]); EXPECT_EQ('a', StringRef("aab")[1]);
} }
TEST(StringRefTest, Utilities) { TEST(StringRefTest, Substr) {
StringRef Str("hello"); StringRef Str("hello");
EXPECT_TRUE(Str.substr(3) == "lo"); EXPECT_EQ("lo", Str.substr(3));
EXPECT_TRUE(Str.substr(100) == ""); EXPECT_EQ("", Str.substr(100));
EXPECT_TRUE(Str.substr(0, 100) == "hello"); EXPECT_EQ("hello", Str.substr(0, 100));
EXPECT_TRUE(Str.substr(4, 10) == "o"); EXPECT_EQ("o", Str.substr(4, 10));
}
EXPECT_TRUE(Str.slice(2, 3) == "l"); TEST(StringRefTest, Slice) {
EXPECT_TRUE(Str.slice(1, 4) == "ell"); StringRef Str("hello");
EXPECT_TRUE(Str.slice(2, 100) == "llo"); EXPECT_EQ("l", Str.slice(2, 3));
EXPECT_TRUE(Str.slice(2, 1) == ""); EXPECT_EQ("ell", Str.slice(1, 4));
EXPECT_TRUE(Str.slice(10, 20) == ""); EXPECT_EQ("llo", Str.slice(2, 100));
EXPECT_EQ("", Str.slice(2, 1));
EXPECT_EQ("", Str.slice(10, 20));
}
EXPECT_TRUE(Str.split('X') == std::make_pair(StringRef("hello"), TEST(StringRefTest, Split) {
StringRef(""))); StringRef Str("hello");
EXPECT_TRUE(Str.split('e') == std::make_pair(StringRef("h"), EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
StringRef("llo"))); Str.split('X'));
EXPECT_TRUE(Str.split('h') == std::make_pair(StringRef(""), EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
StringRef("ello"))); Str.split('e'));
EXPECT_TRUE(Str.split('o') == std::make_pair(StringRef("hell"), EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
StringRef(""))); Str.split('h'));
EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("lo")),
Str.split('l'));
EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
Str.split('o'));
EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
Str.rsplit('X'));
EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
Str.rsplit('e'));
EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
Str.rsplit('h'));
EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")),
Str.rsplit('l'));
EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
Str.rsplit('o'));
}
TEST(StringRefTest, StartsWith) {
StringRef Str("hello");
EXPECT_TRUE(Str.startswith("he")); EXPECT_TRUE(Str.startswith("he"));
EXPECT_FALSE(Str.startswith("helloworld")); EXPECT_FALSE(Str.startswith("helloworld"));
EXPECT_FALSE(Str.startswith("hi")); EXPECT_FALSE(Str.startswith("hi"));
}
TEST(StringRefTest, Find) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.find('l'));
EXPECT_EQ(StringRef::npos, Str.find('z'));
EXPECT_EQ(StringRef::npos, Str.find("helloworld"));
EXPECT_EQ(0U, Str.find("hello"));
EXPECT_EQ(1U, Str.find("ello"));
EXPECT_EQ(StringRef::npos, Str.find("zz"));
EXPECT_EQ(3U, Str.rfind('l'));
EXPECT_EQ(StringRef::npos, Str.rfind('z'));
EXPECT_EQ(StringRef::npos, Str.rfind("helloworld"));
EXPECT_EQ(0U, Str.rfind("hello"));
EXPECT_EQ(1U, Str.rfind("ello"));
EXPECT_EQ(StringRef::npos, Str.rfind("zz"));
}
TEST(StringRefTest, Count) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.count('l'));
EXPECT_EQ(1U, Str.count('o'));
EXPECT_EQ(0U, Str.count('z'));
EXPECT_EQ(0U, Str.count("helloworld"));
EXPECT_EQ(1U, Str.count("hello"));
EXPECT_EQ(1U, Str.count("ello"));
EXPECT_EQ(0U, Str.count("zz"));
}
TEST(StringRefTest, Misc) {
std::string Storage; std::string Storage;
raw_string_ostream OS(Storage); raw_string_ostream OS(Storage);
OS << StringRef("hello"); OS << StringRef("hello");
EXPECT_EQ("hello", OS.str()); EXPECT_EQ("hello", OS.str());
EXPECT_TRUE(Str.find('l') == 2);
EXPECT_TRUE(Str.find('z') == StringRef::npos);
EXPECT_TRUE(Str.find("helloworld") == StringRef::npos);
EXPECT_TRUE(Str.find("hello") == 0);
EXPECT_TRUE(Str.find("ello") == 1);
EXPECT_TRUE(Str.find("zz") == StringRef::npos);
EXPECT_TRUE(Str.count('l') == 2);
EXPECT_TRUE(Str.count('o') == 1);
EXPECT_TRUE(Str.count('z') == 0);
EXPECT_TRUE(Str.count("helloworld") == 0);
EXPECT_TRUE(Str.count("hello") == 1);
EXPECT_TRUE(Str.count("ello") == 1);
EXPECT_TRUE(Str.count("zz") == 0);
} }
} // end anonymous namespace } // end anonymous namespace