Last active
January 4, 2016 19:39
-
-
Save oskaritimperi/8668788 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef STRINGREF_H | |
| #define STRINGREF_H | |
| #include <string> | |
| #include <algorithm> | |
| template<class StringT> | |
| class BasicStringRef | |
| { | |
| public: | |
| typedef StringT basic_string; | |
| typedef typename basic_string::size_type size_type; | |
| typedef typename basic_string::value_type value_type; | |
| BasicStringRef() : | |
| m_begin(0), | |
| m_end(0) | |
| {} | |
| BasicStringRef(const BasicStringRef &other) : | |
| m_begin(other.m_begin), | |
| m_end(other.m_end) | |
| {} | |
| BasicStringRef(const basic_string &s) : | |
| m_begin(s.data()), | |
| m_end(s.data()+s.size()) | |
| {} | |
| BasicStringRef(const value_type *begin, const value_type *end) : | |
| m_begin(begin), | |
| m_end(end) | |
| {} | |
| BasicStringRef(const value_type *str, size_type size) : | |
| m_begin(str), | |
| m_end(str+size) | |
| {} | |
| BasicStringRef(const value_type *str) : | |
| m_begin(str), | |
| m_end(str) | |
| { | |
| while (*m_end++) ; | |
| m_end--; | |
| } | |
| BasicStringRef &operator=(BasicStringRef other) | |
| { | |
| swap(*this, other); | |
| return *this; | |
| } | |
| void swap(BasicStringRef &lhs, BasicStringRef &rhs) | |
| { | |
| std::swap(lhs.m_begin, rhs.m_begin); | |
| std::swap(lhs.m_end, rhs.m_end); | |
| } | |
| size_type size() const | |
| { | |
| return m_end - m_begin; | |
| } | |
| BasicStringRef substr(size_type pos = 0, size_type count = basic_string::npos) const | |
| { | |
| if (pos > size()) | |
| return BasicStringRef(); | |
| const value_type *begin = m_begin + pos; | |
| if (count == basic_string::npos) | |
| count = size() - pos; | |
| if (pos+count > size()) | |
| count = size() - pos; | |
| return BasicStringRef(begin, count); | |
| } | |
| size_type find(const value_type *s, size_type pos, size_type count) const | |
| { | |
| if (count == 0) | |
| return pos; | |
| if (pos >= size() || size() == 0) | |
| return basic_string::npos; | |
| const value_type *p = std::search(m_begin, m_end, s, s+count); | |
| if (p != m_end) | |
| return p - m_begin; | |
| return basic_string::npos; | |
| } | |
| size_type find(const basic_string &str, size_type pos = 0) const | |
| { | |
| return find(str.c_str(), pos, str.size()); | |
| } | |
| size_type find(const value_type *s, size_type pos = 0) const | |
| { | |
| if (pos >= size() || size() == 0) | |
| return basic_string::npos; | |
| const value_type *tmp = s; | |
| while (*tmp++) ; | |
| return find(s, pos, tmp-s-1); | |
| } | |
| size_type find(value_type ch, size_type pos = 0) const | |
| { | |
| return find(&ch, pos, 1); | |
| } | |
| size_type find_first_of(const value_type *s, size_type pos, size_type count) const | |
| { | |
| if (pos >= size()) | |
| return basic_string::npos; | |
| const value_type *p = std::find_first_of(m_begin+pos, m_end, s, s+count); | |
| if (p == m_end) | |
| return basic_string::npos; | |
| return p - m_begin; | |
| } | |
| size_type find_first_of(const basic_string &str, size_type pos = 0) const | |
| { | |
| return find_first_of(str.c_str(), pos, str.size()); | |
| } | |
| size_type find_first_of(const value_type *s, size_type pos = 0) const | |
| { | |
| if (pos >= size() || size() == 0) | |
| return basic_string::npos; | |
| const value_type *tmp = s; | |
| while (*tmp++) ; | |
| return find_first_of(s, pos, tmp-s-1); | |
| } | |
| size_type find_first_of(value_type ch, size_type pos = 0) const | |
| { | |
| return find_first_of(&ch, pos, 1); | |
| } | |
| size_type find_first_not_of(const basic_string &str, size_type pos = 0) const | |
| { | |
| return find_first_not_of(str.c_str(), pos, str.size()); | |
| } | |
| size_type find_first_not_of(const value_type *s, size_type pos, size_type count) const | |
| { | |
| if (pos >= size() || count == 0) | |
| return basic_string::npos; | |
| for (; pos < size(); ++pos) | |
| { | |
| if (std::find(s, s+count, *(m_begin+pos)) == s+count) | |
| { | |
| return pos; | |
| } | |
| } | |
| return basic_string::npos; | |
| } | |
| size_type find_first_not_of(const value_type *s, size_type pos = 0) const | |
| { | |
| if (pos >= size() || size() == 0) | |
| return basic_string::npos; | |
| const value_type *tmp = s; | |
| while (*tmp++) ; | |
| return find_first_not_of(s, pos, tmp-s-1); | |
| } | |
| size_type find_first_not_of(value_type ch, size_type pos = 0) const | |
| { | |
| return find_first_not_of(&ch, pos, 1); | |
| } | |
| size_type find_last_of(const value_type *s, size_type pos, size_type count) const | |
| { | |
| if (size() == 0 || count == 0) | |
| return basic_string::npos; | |
| size_type size = this->size(); | |
| if (--size > pos) | |
| size = pos; | |
| do | |
| { | |
| if (std::find(s, s+count, *(m_begin+size)) != s+count) | |
| return size; | |
| } | |
| while (size-- != 0); | |
| return basic_string::npos; | |
| } | |
| size_type find_last_of(const value_type *s, size_type pos = basic_string::npos) const | |
| { | |
| const value_type *tmp = s; | |
| while (*tmp++) ; | |
| return find_last_of(s, pos, tmp-s-1); | |
| } | |
| size_type find_last_of(const basic_string &s, size_type pos = basic_string::npos) const | |
| { | |
| return find_last_of(s.c_str(), pos, s.size()); | |
| } | |
| size_type find_last_of(value_type ch, size_type pos = basic_string::npos) const | |
| { | |
| return find_last_of(&ch, pos, 1); | |
| } | |
| size_type find_last_not_of(const value_type *s, size_type pos, size_type count) const | |
| { | |
| if (size() == 0 || count == 0) | |
| return basic_string::npos; | |
| size_type size = this->size(); | |
| if (--size > pos) | |
| size = pos; | |
| do | |
| { | |
| if (std::find(s, s+count, *(m_begin+size)) == s+count) | |
| return size; | |
| } | |
| while (size-- != 0); | |
| return basic_string::npos; | |
| } | |
| size_type find_last_not_of(const value_type *s, size_type pos = basic_string::npos) const | |
| { | |
| const value_type *tmp = s; | |
| while (*tmp++) ; | |
| return find_last_not_of(s, pos, tmp-s-1); | |
| } | |
| size_type find_last_not_of(const basic_string &s, size_type pos = basic_string::npos) const | |
| { | |
| return find_last_not_of(s.c_str(), pos, s.size()); | |
| } | |
| size_type find_last_not_of(value_type ch, size_type pos = basic_string::npos) const | |
| { | |
| return find_last_not_of(&ch, pos, 1); | |
| } | |
| operator basic_string() const | |
| { | |
| return to_string(); | |
| } | |
| basic_string to_string() const | |
| { | |
| return basic_string(m_begin, m_end); | |
| } | |
| template<class ContainerT> | |
| void split(ContainerT &values, const basic_string &delims, | |
| size_type max_split = basic_string::npos, bool trim_empty = false) | |
| { | |
| size_type pos, last_pos = 0; | |
| while (true) | |
| { | |
| pos = find_first_of(delims, last_pos); | |
| if (pos == basic_string::npos) | |
| { | |
| pos = size(); | |
| if (pos != last_pos || !trim_empty) | |
| values.push_back(typename ContainerT::value_type(m_begin+last_pos, pos-last_pos)); | |
| break; | |
| } | |
| else | |
| { | |
| if (pos != last_pos || !trim_empty) | |
| { | |
| values.push_back(typename ContainerT::value_type(m_begin+last_pos, pos-last_pos)); | |
| if (max_split != basic_string::npos && values.size() == max_split) | |
| { | |
| values.push_back(typename ContainerT::value_type(m_begin+pos+1, size()-pos-1)); | |
| break; | |
| } | |
| } | |
| } | |
| last_pos = pos+1; | |
| } | |
| } | |
| BasicStringRef lstrip(const basic_string &chars) | |
| { | |
| if (size() == 0) | |
| return *this; | |
| size_type i = find_first_not_of(chars); | |
| if (i != basic_string::npos) | |
| return BasicStringRef(m_begin+i, m_end); | |
| return BasicStringRef(); | |
| } | |
| BasicStringRef rstrip(const basic_string &chars) | |
| { | |
| if (size() == 0) | |
| return *this; | |
| size_type i = find_last_not_of(chars); | |
| if (i != basic_string::npos) | |
| return BasicStringRef(m_begin, m_begin+i+1); | |
| return BasicStringRef(); | |
| } | |
| BasicStringRef strip(const basic_string &chars) | |
| { | |
| return lstrip(chars).rstrip(chars); | |
| } | |
| bool starts_with(const basic_string &prefix) | |
| { | |
| if (prefix.size() > size()) | |
| return false; | |
| return std::equal(m_begin, m_begin+prefix.size(), prefix.begin()); | |
| } | |
| bool ends_with(const basic_string &suffix) | |
| { | |
| if (suffix.size() > size()) | |
| return false; | |
| return std::equal(m_end-suffix.size(), m_end, suffix.begin()); | |
| } | |
| private: | |
| const value_type *m_begin; | |
| const value_type *m_end; | |
| }; | |
| typedef BasicStringRef<std::string> StringRef; | |
| #endif // STRINGREF_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "stringref.h" | |
| #include "gtest/gtest.h" | |
| static const char *s = "The quick brown fox jumps over the lazy dog"; | |
| static const std::string ss = s; | |
| static const size_t s_len = 43; | |
| static const char *s2 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"; | |
| static const std::string ss2 = s2; | |
| static const size_t s2_len = 93; | |
| TEST(StringRef, default_constructor) | |
| { | |
| StringRef ref; | |
| ASSERT_EQ(0, (int) ref.size()); | |
| } | |
| TEST(StringRef, copy_constructor) | |
| { | |
| StringRef ref1(s); | |
| StringRef ref2(ref1); | |
| ASSERT_EQ(s_len, ref1.size()); | |
| ASSERT_EQ(s_len, ref2.size()); | |
| ASSERT_STREQ(s, ((std::string)ref1).c_str()); | |
| ASSERT_STREQ(s, ((std::string)ref2).c_str()); | |
| } | |
| TEST(StringRef, std_string_constructor) | |
| { | |
| StringRef ref(ss); | |
| ASSERT_EQ(s_len, ref.size()); | |
| ASSERT_STREQ(s, ((std::string)ref).c_str()); | |
| } | |
| TEST(StringRef, charp_count_constructor) | |
| { | |
| StringRef ref(s, 9); | |
| ASSERT_EQ(9, (int) ref.size()); | |
| ASSERT_STREQ("The quick", ((std::string)ref).c_str()); | |
| } | |
| TEST(StringRef, charp_constructor) | |
| { | |
| StringRef ref(s); | |
| ASSERT_EQ(s_len, ref.size()); | |
| ASSERT_STREQ(s, ((std::string)ref).c_str()); | |
| } | |
| TEST(StringRef, assignment) | |
| { | |
| StringRef ref1(s); | |
| ASSERT_EQ(s_len, ref1.size()); | |
| ASSERT_STREQ(s, ref1.to_string().c_str()); | |
| StringRef ref2; | |
| ASSERT_EQ(0, (int) ref2.size()); | |
| ref2 = ref1; | |
| ASSERT_EQ(s_len, ref2.size()); | |
| ASSERT_STREQ(s, ref2.to_string().c_str()); | |
| } | |
| TEST(StringRef, swap) | |
| { | |
| StringRef ref1(s, s_len); | |
| ASSERT_EQ(s_len, ref1.size()); | |
| StringRef ref2(s2, s2_len); | |
| ASSERT_EQ(s2_len, ref2.size()); | |
| ref1.swap(ref1, ref2); | |
| ASSERT_EQ(s_len, ref2.size()); | |
| ASSERT_EQ(s2_len, ref1.size()); | |
| } | |
| TEST(StringRef, size) | |
| { | |
| StringRef ref1; | |
| ASSERT_EQ(0, (int) ref1.size()); | |
| StringRef ref2(s, s_len); | |
| ASSERT_EQ(s_len, ref2.size()); | |
| StringRef ref3(s2); | |
| ASSERT_EQ(s2_len, ref3.size()); | |
| } | |
| TEST(StringRef, substr) | |
| { | |
| StringRef ref1(s, s_len); | |
| StringRef subref11 = ref1.substr(); | |
| ASSERT_EQ(s_len, subref11.size()); | |
| StringRef subref12 = ref1.substr(4); | |
| ASSERT_STREQ("quick brown fox jumps over the lazy dog", subref12.to_string().c_str()); | |
| StringRef subref13 = ref1.substr(4, 5); | |
| ASSERT_EQ(5, (int) subref13.size()); | |
| ASSERT_STREQ("quick", subref13.to_string().c_str()); | |
| StringRef subref14 = ref1.substr(0, s_len+10); | |
| ASSERT_EQ(s_len, subref14.size()); | |
| StringRef subref15 = ref1.substr(4, s_len+10); | |
| ASSERT_STREQ("quick brown fox jumps over the lazy dog", subref15.to_string().c_str()); | |
| StringRef subref16 = ref1.substr(s_len+10, 5); | |
| ASSERT_EQ(0, (int) subref16.size()); | |
| } | |
| TEST(StringRef, find_std_str) | |
| { | |
| StringRef ref1(s, s_len); | |
| StringRef::size_type i = ref1.find(std::string("brown")); | |
| ASSERT_EQ(10, (int) i); | |
| StringRef ref2(s+15); | |
| i = ref2.find(std::string("brown")); | |
| ASSERT_EQ(std::string::npos, i); | |
| } | |
| TEST(StringRef, find_charp_pos_count) | |
| { | |
| StringRef ref(s, s_len); | |
| StringRef::size_type i = ref.find("fox", 0, 3); | |
| ASSERT_EQ(16, (int) i); | |
| i = ref.find("jumps", i, 5); | |
| ASSERT_EQ(20, (int) i); | |
| i = ref.find("foobar", i, 6); | |
| ASSERT_EQ(std::string::npos, i); | |
| } | |
| TEST(StringRef, find_char_pos) | |
| { | |
| StringRef ref(s, s_len); | |
| size_t i = ref.find('g'); | |
| ASSERT_EQ((size_t)42, i); | |
| i = ref.find('\n'); | |
| ASSERT_EQ(std::string::npos, i); | |
| } | |
| TEST(StringRef, split) | |
| { | |
| std::vector<std::string> correct; | |
| correct.push_back("The"); | |
| correct.push_back("quick"); | |
| correct.push_back("brown"); | |
| correct.push_back("fox"); | |
| correct.push_back("jumps"); | |
| correct.push_back("over"); | |
| correct.push_back("the"); | |
| correct.push_back("lazy"); | |
| correct.push_back("dog"); | |
| StringRef ref(s, s_len); | |
| std::vector<std::string> strings; | |
| ref.split(strings, " "); | |
| ASSERT_EQ(correct.size(), strings.size()); | |
| for (size_t i = 0; i < correct.size(); ++i) | |
| { | |
| ASSERT_STREQ(correct[i].c_str(), strings[i].c_str()); | |
| } | |
| std::vector<StringRef> refs; | |
| ref.split(refs, " "); | |
| ASSERT_EQ(refs.size(), correct.size()); | |
| for (size_t i = 0; i < correct.size(); ++i) | |
| { | |
| ASSERT_STREQ(correct[i].c_str(), refs[i].to_string().c_str()); | |
| } | |
| } | |
| TEST(StringRef, split_w_max_split) | |
| { | |
| std::string a = "foo bar foo yeah"; | |
| StringRef ref(a); | |
| std::vector<StringRef> refs; | |
| ref.split(refs, " ", 1); | |
| ASSERT_EQ((size_t)2, refs.size()); | |
| ASSERT_STREQ("foo", refs[0].to_string().c_str()); | |
| ASSERT_STREQ("bar foo yeah", refs[1].to_string().c_str()); | |
| refs.clear(); | |
| ref.split(refs, " ", 2); | |
| ASSERT_EQ((size_t)3, refs.size()); | |
| ASSERT_STREQ("foo", refs[0].to_string().c_str()); | |
| ASSERT_STREQ("bar", refs[1].to_string().c_str()); | |
| ASSERT_STREQ("foo yeah", refs[2].to_string().c_str()); | |
| } | |
| TEST(StringRef, split_trim_empty) | |
| { | |
| std::string a = "foo bar yeah"; | |
| StringRef refa(a); | |
| std::vector<StringRef> refs; | |
| refa.split(refs, " ", std::string::npos, true); | |
| ASSERT_EQ((size_t)3, refs.size()); | |
| refs.clear(); | |
| std::string b = "foo bar yeah"; | |
| StringRef refb(b); | |
| refb.split(refs, " ", std::string::npos, true); | |
| ASSERT_EQ((size_t)3, refs.size()); | |
| refs.clear(); | |
| refb.split(refs, " ", std::string::npos, false); | |
| ASSERT_EQ((size_t)4, refs.size()); | |
| refs.clear(); | |
| refb.split(refs, " ", 2, false); | |
| ASSERT_EQ((size_t)3, refs.size()); | |
| ASSERT_STREQ(" yeah", refs[refs.size()-1].to_string().c_str()); | |
| } | |
| TEST(StringRef, split_max_split_last_split_until_end_of_orig_str) | |
| { | |
| std::string a = "this is some text\n"; | |
| StringRef ref(a.c_str(), a.size()-1); | |
| std::vector<StringRef> tokens; | |
| ref.split(tokens, " ", 2); | |
| ASSERT_EQ((size_t)3, tokens.size()); | |
| ASSERT_STREQ("this", tokens[0].to_string().c_str()); | |
| ASSERT_STREQ("is", tokens[1].to_string().c_str()); | |
| ASSERT_STREQ("some text", tokens[2].to_string().c_str()); | |
| } | |
| TEST(StringRef, lstrip) | |
| { | |
| const char *a = "foobar "; | |
| StringRef aref(a); | |
| aref = aref.lstrip(" "); | |
| ASSERT_EQ(strlen(a), aref.size()); | |
| ASSERT_STREQ(a, aref.to_string().c_str()); | |
| const char *b = " foobar"; | |
| StringRef bref(b); | |
| bref = bref.lstrip(" "); | |
| ASSERT_EQ(strlen(b)-2, bref.size()); | |
| ASSERT_STREQ("foobar", bref.to_string().c_str()); | |
| const char *c = ""; | |
| StringRef cref(c); | |
| cref = cref.lstrip(" "); | |
| ASSERT_EQ((size_t)0, cref.size()); | |
| const char *d = " "; | |
| StringRef dref(d); | |
| dref = dref.lstrip(" "); | |
| ASSERT_EQ((size_t)0, dref.size()); | |
| const char *e = " foobar "; | |
| StringRef eref(e); | |
| eref = eref.lstrip(" "); | |
| ASSERT_EQ((size_t)11, eref.size()); | |
| } | |
| TEST(StringRef, rstrip) | |
| { | |
| const char *a = " foobar"; | |
| StringRef aref(a); | |
| aref = aref.rstrip(" "); | |
| ASSERT_EQ(strlen(a), aref.size()); | |
| ASSERT_STREQ(a, aref.to_string().c_str()); | |
| const char *b = "foobar "; | |
| StringRef bref(b); | |
| bref = bref.rstrip(" "); | |
| ASSERT_EQ(strlen(b)-2, bref.size()); | |
| ASSERT_STREQ("foobar", bref.to_string().c_str()); | |
| const char *c = ""; | |
| StringRef cref(c); | |
| cref = cref.rstrip(" "); | |
| ASSERT_EQ((size_t)0, cref.size()); | |
| const char *d = " "; | |
| StringRef dref(d); | |
| dref = dref.rstrip(" "); | |
| ASSERT_EQ((size_t)0, dref.size()); | |
| const char *e = " foobar "; | |
| StringRef eref(e); | |
| eref = eref.rstrip(" "); | |
| ASSERT_EQ((size_t)10, eref.size()); | |
| } | |
| TEST(StringRef, strip) | |
| { | |
| const char *a = " foobar"; | |
| StringRef aref(a); | |
| aref = aref.strip(" "); | |
| ASSERT_EQ((size_t)6, aref.size()); | |
| ASSERT_STREQ("foobar", aref.to_string().c_str()); | |
| const char *b = "foobar "; | |
| StringRef bref(b); | |
| bref = bref.strip(" "); | |
| ASSERT_EQ((size_t)6, bref.size()); | |
| ASSERT_STREQ("foobar", bref.to_string().c_str()); | |
| const char *c = ""; | |
| StringRef cref(c); | |
| cref = cref.strip(" "); | |
| ASSERT_EQ((size_t)0, cref.size()); | |
| const char *d = " "; | |
| StringRef dref(d); | |
| dref = dref.strip(" "); | |
| ASSERT_EQ((size_t)0, dref.size()); | |
| const char *e = " foobar "; | |
| StringRef eref(e); | |
| eref = eref.strip(" "); | |
| ASSERT_EQ((size_t)6, eref.size()); | |
| ASSERT_STREQ("foobar", eref.to_string().c_str()); | |
| } | |
| TEST(StringRef, starts_with) | |
| { | |
| const char *a = "foobar baz"; | |
| StringRef aref(a); | |
| ASSERT_TRUE(aref.starts_with("foo")); | |
| ASSERT_TRUE(aref.starts_with("foobar")); | |
| ASSERT_TRUE(aref.starts_with("foobar baz")); | |
| ASSERT_FALSE(aref.starts_with("fob")); | |
| ASSERT_FALSE(aref.starts_with("foobar bazz")); | |
| } | |
| TEST(StringRef, ends_with) | |
| { | |
| const char *a = "foobar baz"; | |
| StringRef aref(a); | |
| ASSERT_TRUE(aref.ends_with("baz")); | |
| ASSERT_TRUE(aref.ends_with("foobar baz")); | |
| ASSERT_FALSE(aref.ends_with("zab")); | |
| ASSERT_FALSE(aref.ends_with(" foobar baz")); | |
| } | |
| TEST(StringRef, find_first_of) | |
| { | |
| StringRef ref1(s, s_len); | |
| size_t i1 = ref1.find_first_of("lazy", 0, 4); | |
| size_t i2 = ref1.find_first_of("azyl", 0, 4); | |
| size_t i3 = ref1.find_first_of("zyla", 0, 4); | |
| size_t i4 = ref1.find_first_of("ylaz", 0, 4); | |
| ASSERT_EQ((size_t)35, i1); | |
| ASSERT_EQ(i1, i2); | |
| ASSERT_EQ(i1, i3); | |
| ASSERT_EQ(i1, i4); | |
| } | |
| TEST(StringRef, find_first_not_of) | |
| { | |
| const char *a = " foobar "; | |
| StringRef ref(a); | |
| size_t i = ref.find_first_not_of(" ", 0, 1); | |
| ASSERT_EQ((size_t)2, i); | |
| i = ref.find_first_not_of("fobar ", 0, 6); | |
| ASSERT_EQ(std::string::npos, i); | |
| } | |
| TEST(StringRef, find_last_of) | |
| { | |
| // The quick brown | |
| StringRef ref(s, 15); | |
| size_t i = ref.find_last_of("k ", std::string::npos, 2); | |
| ASSERT_EQ((size_t)9, i); | |
| i = ref.find_last_of("brown", std::string::npos, 5); | |
| ASSERT_EQ((size_t)14, i); | |
| i = ref.find_last_of("T", std::string::npos, 1); | |
| ASSERT_EQ((size_t)0, i); | |
| i = ref.find_last_of("\t", std::string::npos, 1); | |
| ASSERT_EQ(std::string::npos, i); | |
| i = ref.find_last_of("quick", 3, 5); | |
| ASSERT_EQ(std::string::npos, i); | |
| } | |
| TEST(StringRef, find_last_not_of) | |
| { | |
| // The quick brown | |
| StringRef ref(s, 15); | |
| size_t i; | |
| i = ref.find_last_not_of(" ", std::string::npos, 1); | |
| ASSERT_EQ((size_t)14, i); | |
| i = ref.find_last_not_of(" n", std::string::npos, 2); | |
| ASSERT_EQ((size_t)13, i); | |
| i = ref.find_last_not_of("brown", std::string::npos, 5); | |
| ASSERT_EQ((size_t)9, i); | |
| i = ref.find_last_not_of("T", std::string::npos, 1); | |
| ASSERT_EQ((size_t)14, i); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment