From: Talin Date: Tue, 24 Jan 2012 23:43:59 +0000 (+0000) Subject: Additional methods for SmallString. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=2527188a42b3250671b69dc979102565be1f910f;p=oota-llvm.git Additional methods for SmallString. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148881 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index da264164821..199783ba389 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -24,21 +24,244 @@ namespace llvm { template class SmallString : public SmallVector { public: - // Default ctor - Initialize to empty. + /// Default ctor - Initialize to empty. SmallString() {} - // Initialize from a StringRef. + /// Initialize from a StringRef. SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} - // Initialize with a range. + /// Initialize with a range. template SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} - // Copy ctor. + /// Copy ctor. SmallString(const SmallString &RHS) : SmallVector(RHS) {} + // Note that in order to add new overloads for append & assign, we have to + // duplicate the inherited versions so as not to inadvertently hide them. + + /// @} + /// @name String Assignment + /// @{ + + /// Assign from a repeated element + void assign(unsigned NumElts, char Elt) { + this->SmallVectorImpl::assign(NumElts, Elt); + } + + /// Assign from an iterator pair + template + void assign(in_iter S, in_iter E) { + this->clear(); + SmallVectorImpl::append(S, E); + } + + /// Assign from a StringRef + void assign(StringRef RHS) { + this->clear(); + SmallVectorImpl::append(RHS.begin(), RHS.end()); + } + + /// Assign from a SmallVector + void assign(const SmallVectorImpl &RHS) { + this->clear(); + SmallVectorImpl::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Concatenation + /// @{ + + /// Append from an iterator pair + template + void append(in_iter S, in_iter E) { + SmallVectorImpl::append(S, E); + } + + /// Append from a StringRef + void append(StringRef RHS) { + SmallVectorImpl::append(RHS.begin(), RHS.end()); + } + + /// Append from a SmallVector + void append(const SmallVectorImpl &RHS) { + SmallVectorImpl::append(RHS.begin(), RHS.end()); + } + + /// @} + /// @name String Comparison + /// @{ + + /// equals - Check for string equality, this is more efficient than + /// compare() when the relative ordering of inequal strings isn't needed. + bool equals(StringRef RHS) const { + return str().equals(RHS); + } + + /// equals_lower - Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return str().equals_lower(RHS); + } + + /// compare - Compare two strings; the result is -1, 0, or 1 if this string + /// is lexicographically less than, equal to, or greater than the \arg RHS. + int compare(StringRef RHS) const { + return str().compare(RHS); + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const { + return str().compare_lower(RHS); + } + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const { + return str().compare_numeric(RHS); + } + + /// @} + /// @name String Predicates + /// @{ + + /// startswith - Check if this string starts with the given \arg Prefix. + bool startswith(StringRef Prefix) const { + return str().startswith(Prefix); + } + + /// endswith - Check if this string ends with the given \arg Suffix. + bool endswith(StringRef Suffix) const { + return str().endswith(Suffix); + } + + /// @} + /// @name String Searching + /// @{ + + /// find - Search for the first character \arg C in the string. + /// + /// \return - The index of the first occurrence of \arg C, or npos if not + /// found. + size_t find(char C, size_t From = 0) const { + return str().find(C, From); + } + + /// find - Search for the first string \arg Str in the string. + /// + /// \return - The index of the first occurrence of \arg Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const { + return str().find(Str, From); + } + + /// rfind - Search for the last character \arg C in the string. + /// + /// \return - The index of the last occurrence of \arg C, or npos if not + /// found. + size_t rfind(char C, size_t From = StringRef::npos) const { + return str().rfind(C, From); + } + + /// rfind - Search for the last string \arg Str in the string. + /// + /// \return - The index of the last occurrence of \arg Str, or npos if not + /// found. + size_t rfind(StringRef Str) const { + return str().rfind(Str); + } + + /// find_first_of - Find the first character in the string that is \arg C, + /// or npos if not found. Same as find. + size_t find_first_of(char C, size_t From = 0) const { + return str().find_first_of(C, From); + } + + /// find_first_of - Find the first character in the string that is in \arg + /// Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_t find_first_of(StringRef Chars, size_t From = 0) const { + return str().find_first_of(Chars, From); + } + + /// find_first_not_of - Find the first character in the string that is not + /// \arg C or npos if not found. + size_t find_first_not_of(char C, size_t From = 0) const { + return str().find_first_not_of(C, From); + } + + /// find_first_not_of - Find the first character in the string that is not + /// in the string \arg Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_t find_first_not_of(StringRef Chars, size_t From = 0) const { + return str().find_first_not_of(Chars, From); + } + + /// find_last_of - Find the last character in the string that is \arg C, or + /// npos if not found. + size_t find_last_of(char C, size_t From = StringRef::npos) const { + return str().find_last_of(C, From); + } + + /// find_last_of - Find the last character in the string that is in \arg C, + /// or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_t find_last_of( + StringRef Chars, size_t From = StringRef::npos) const { + return str().find_last_of(Chars, From); + } + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// count - Return the number of occurrences of \arg C in the string. + size_t count(char C) const { + return str().count(C); + } + + /// count - Return the number of non-overlapped occurrences of \arg Str in + /// the string. + size_t count(StringRef Str) const { + return str().count(Str); + } + + /// @} + /// @name Substring Operations + /// @{ + + /// substr - Return a reference to the substring from [Start, Start + N). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N - The number of characters to included in the substring. If N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \arg Start) will be returned. + StringRef substr(size_t Start, size_t N = StringRef::npos) const { + return str().substr(Start, N); + } + + /// slice - Return a reference to the substring from [Start, End). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End - The index following the last character to include in the + /// substring. If this is npos, or less than \arg Start, or exceeds the + /// number of characters remaining in the string, the string suffix + /// (starting with \arg Start) will be returned. + StringRef slice(size_t Start, size_t End) const { + return str().slice(Start, End); + } // Extra methods. + + /// Explicit conversion to StringRef StringRef str() const { return StringRef(this->begin(), this->size()); } // TODO: Make this const, if it's safe... @@ -48,7 +271,7 @@ public: return this->data(); } - // Implicit conversion to StringRef. + /// Implicit conversion to StringRef. operator StringRef() const { return str(); } // Extra operators. diff --git a/unittests/ADT/SmallStringTest.cpp b/unittests/ADT/SmallStringTest.cpp index 099d8159c91..660ac44a8bc 100644 --- a/unittests/ADT/SmallStringTest.cpp +++ b/unittests/ADT/SmallStringTest.cpp @@ -44,5 +44,153 @@ TEST_F(SmallStringTest, EmptyStringTest) { EXPECT_TRUE(theString.rbegin() == theString.rend()); } +TEST_F(SmallStringTest, AssignRepeated) { + theString.assign(3, 'a'); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("aaa", theString.c_str()); } +TEST_F(SmallStringTest, AssignIterPair) { + StringRef abc = "abc"; + theString.assign(abc.begin(), abc.end()); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("abc", theString.c_str()); +} + +TEST_F(SmallStringTest, AssignStringRef) { + StringRef abc = "abc"; + theString.assign(abc); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("abc", theString.c_str()); +} + +TEST_F(SmallStringTest, AssignSmallVector) { + StringRef abc = "abc"; + SmallVector abcVec(abc.begin(), abc.end()); + theString.assign(abcVec); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("abc", theString.c_str()); +} + +TEST_F(SmallStringTest, AppendIterPair) { + StringRef abc = "abc"; + theString.append(abc.begin(), abc.end()); + theString.append(abc.begin(), abc.end()); + EXPECT_EQ(6u, theString.size()); + EXPECT_STREQ("abcabc", theString.c_str()); +} + +TEST_F(SmallStringTest, AppendStringRef) { + StringRef abc = "abc"; + theString.append(abc); + theString.append(abc); + EXPECT_EQ(6u, theString.size()); + EXPECT_STREQ("abcabc", theString.c_str()); +} + +TEST_F(SmallStringTest, AppendSmallVector) { + StringRef abc = "abc"; + SmallVector abcVec(abc.begin(), abc.end()); + theString.append(abcVec); + theString.append(abcVec); + EXPECT_EQ(6u, theString.size()); + EXPECT_STREQ("abcabc", theString.c_str()); +} + +TEST_F(SmallStringTest, Substr) { + theString = "hello"; + EXPECT_EQ("lo", theString.substr(3)); + EXPECT_EQ("", theString.substr(100)); + EXPECT_EQ("hello", theString.substr(0, 100)); + EXPECT_EQ("o", theString.substr(4, 10)); +} + +TEST_F(SmallStringTest, Slice) { + theString = "hello"; + EXPECT_EQ("l", theString.slice(2, 3)); + EXPECT_EQ("ell", theString.slice(1, 4)); + EXPECT_EQ("llo", theString.slice(2, 100)); + EXPECT_EQ("", theString.slice(2, 1)); + EXPECT_EQ("", theString.slice(10, 20)); +} + +TEST_F(SmallStringTest, Find) { + theString = "hello"; + EXPECT_EQ(2U, theString.find('l')); + EXPECT_EQ(StringRef::npos, theString.find('z')); + EXPECT_EQ(StringRef::npos, theString.find("helloworld")); + EXPECT_EQ(0U, theString.find("hello")); + EXPECT_EQ(1U, theString.find("ello")); + EXPECT_EQ(StringRef::npos, theString.find("zz")); + EXPECT_EQ(2U, theString.find("ll", 2)); + EXPECT_EQ(StringRef::npos, theString.find("ll", 3)); + EXPECT_EQ(0U, theString.find("")); + + EXPECT_EQ(3U, theString.rfind('l')); + EXPECT_EQ(StringRef::npos, theString.rfind('z')); + EXPECT_EQ(StringRef::npos, theString.rfind("helloworld")); + EXPECT_EQ(0U, theString.rfind("hello")); + EXPECT_EQ(1U, theString.rfind("ello")); + EXPECT_EQ(StringRef::npos, theString.rfind("zz")); + + EXPECT_EQ(2U, theString.find_first_of('l')); + EXPECT_EQ(1U, theString.find_first_of("el")); + EXPECT_EQ(StringRef::npos, theString.find_first_of("xyz")); + + EXPECT_EQ(1U, theString.find_first_not_of('h')); + EXPECT_EQ(4U, theString.find_first_not_of("hel")); + EXPECT_EQ(StringRef::npos, theString.find_first_not_of("hello")); + + theString = "hellx xello hell ello world foo bar hello"; + EXPECT_EQ(36U, theString.find("hello")); + EXPECT_EQ(28U, theString.find("foo")); + EXPECT_EQ(12U, theString.find("hell", 2)); + EXPECT_EQ(0U, theString.find("")); +} + +TEST_F(SmallStringTest, Count) { + theString = "hello"; + EXPECT_EQ(2U, theString.count('l')); + EXPECT_EQ(1U, theString.count('o')); + EXPECT_EQ(0U, theString.count('z')); + EXPECT_EQ(0U, theString.count("helloworld")); + EXPECT_EQ(1U, theString.count("hello")); + EXPECT_EQ(1U, theString.count("ello")); + EXPECT_EQ(0U, theString.count("zz")); +} + +TEST(StringRefTest, Comparisons) { + EXPECT_EQ(-1, SmallString<10>("aab").compare("aad")); + EXPECT_EQ( 0, SmallString<10>("aab").compare("aab")); + EXPECT_EQ( 1, SmallString<10>("aab").compare("aaa")); + EXPECT_EQ(-1, SmallString<10>("aab").compare("aabb")); + EXPECT_EQ( 1, SmallString<10>("aab").compare("aa")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare("\1")); + + EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aAd")); + EXPECT_EQ( 0, SmallString<10>("AaB").compare_lower("aab")); + EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("AAA")); + EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aaBb")); + EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("aA")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare_lower("\1")); + + EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aad")); + EXPECT_EQ( 0, SmallString<10>("aab").compare_numeric("aab")); + EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aaa")); + EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aabb")); + EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aa")); + EXPECT_EQ(-1, SmallString<10>("1").compare_numeric("10")); + EXPECT_EQ( 0, SmallString<10>("10").compare_numeric("10")); + EXPECT_EQ( 0, SmallString<10>("10a").compare_numeric("10a")); + EXPECT_EQ( 1, SmallString<10>("2").compare_numeric("1")); + EXPECT_EQ( 0, SmallString<10>("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare_numeric("\1")); + EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V1_q0")); + EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V16")); + EXPECT_EQ(-1, SmallString<10>("V8_q0").compare_numeric("V16")); + EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V8_q0")); + EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V8_q0")); + EXPECT_EQ( 1, SmallString<10>("V8_q0").compare_numeric("V1_q0")); +} + +}