From 9dd1fefa59bf25f1fbe4ed11cedf690676038e53 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Mon, 8 Oct 2012 21:29:35 +0900 Subject: [PATCH] add string::find_first_of, find_last_of --- libs/string/test/string.cpp | 18 +++++++ sprout/string/char_traits.hpp | 17 ++++++- sprout/string/string.hpp | 91 ++++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/libs/string/test/string.cpp b/libs/string/test/string.cpp index 999e52da..f534ed5d 100644 --- a/libs/string/test/string.cpp +++ b/libs/string/test/string.cpp @@ -149,6 +149,24 @@ namespace testspr { TESTSPR_BOTH_ASSERT(str1.rfind("barbar", decltype(str1)::npos, 3) == 3); TESTSPR_BOTH_ASSERT(str1.rfind('b') == 3); + // find_first_of + TESTSPR_BOTH_ASSERT(str1.find_first_of(to_string("vwxyz")) == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_first_of(to_string("rab")) == 3); + TESTSPR_BOTH_ASSERT(str1.find_first_of("vwxyz") == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_first_of("rab") == 3); + TESTSPR_BOTH_ASSERT(str1.find_first_of("vwxyz", 0, 3) == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_first_of("rabrab", 0, 3) == 3); + TESTSPR_BOTH_ASSERT(str1.find_first_of('b') == 3); + + // find_last_of + TESTSPR_BOTH_ASSERT(str1.find_last_of(to_string("vwxyz")) == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_last_of(to_string("rab")) == 5); + TESTSPR_BOTH_ASSERT(str1.find_last_of("vwxyz") == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_last_of("rab") == 5); + TESTSPR_BOTH_ASSERT(str1.find_last_of("vwxyz", decltype(str1)::npos, 3) == decltype(str1)::npos); + TESTSPR_BOTH_ASSERT(str1.find_last_of("rabrab", decltype(str1)::npos, 3) == 5); + TESTSPR_BOTH_ASSERT(str1.find_last_of('r') == 5); + // substr { SPROUT_STATIC_CONSTEXPR auto str3 = str1.substr(); diff --git a/sprout/string/char_traits.hpp b/sprout/string/char_traits.hpp index 9a2e350c..5718db3e 100644 --- a/sprout/string/char_traits.hpp +++ b/sprout/string/char_traits.hpp @@ -105,7 +105,7 @@ namespace sprout { } template static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) { - return !n ? s + 1 + return !n ? s : eq(*s, a) ? s : find(s + 1, n - 1, a) ; @@ -141,10 +141,23 @@ namespace sprout { typedef typename traits_type::pos_type pos_type; typedef typename traits_type::state_type state_type; public: + static SPROUT_CONSTEXPR char_type const* find(char_type const* s, std::size_t n, char_type const& a) { + return !n ? s + : traits_type::eq(*s, a) ? s + : find(s + 1, n - 1, a) + ; + } static SPROUT_CONSTEXPR bool is_found(char_type const* found, char_type const* last) { - return found; + return found != last; } #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION + template + static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) { + return !n ? s + : traits_type::eq(*s, a) ? s + : find(s + 1, n - 1, a) + ; + } template static SPROUT_CONSTEXPR bool is_found(ConstIterator found, ConstIterator last) { return found != last; diff --git a/sprout/string/string.hpp b/sprout/string/string.hpp index 559d983a..58df43e4 100644 --- a/sprout/string/string.hpp +++ b/sprout/string/string.hpp @@ -96,6 +96,31 @@ namespace sprout { : npos ; } + template + static SPROUT_CONSTEXPR size_type + find_first_of_impl_1(const_iterator data, size_type len, ConstIterator s, size_type pos, size_type n) { + return n && pos < len + ? traits_helper_type::is_found(traits_helper_type::find(s, n, data[pos]), s + n) + ? pos + : find_first_of_impl_1(data, len, s, pos + 1, n) + : npos + ; + } + template + static SPROUT_CONSTEXPR size_type + find_last_of_impl_2(const_iterator data, size_type len, ConstIterator s, size_type pos, size_type n) { + return traits_helper_type::is_found(traits_helper_type::find(s, n, data[len]), s + n) ? len + : len != 0 ? find_last_of_impl_2(data, len - 1, s, pos, n) + : npos + ; + } + template + static SPROUT_CONSTEXPR size_type + find_last_of_impl_1(const_iterator data, size_type len, ConstIterator s, size_type pos, size_type n) { + return len && n ? find_last_of_impl_2(data, len - 1 > pos ? pos : len, s, pos, n) + : npos + ; + } static SPROUT_CONSTEXPR int compare_impl_2(int compared, size_type n1, size_type n2) { return compared != 0 ? compared @@ -389,7 +414,7 @@ namespace sprout { } SPROUT_CONSTEXPR size_type find(value_type c, size_type pos = 0) const { - return pos < len ? find_c_impl(traits_type::find(begin() + pos, len - pos, c), begin(), end()) + return pos < len ? find_c_impl(traits_helper_type::find(begin() + pos, len - pos, c), begin(), end()) : npos ; } @@ -411,6 +436,38 @@ namespace sprout { : npos ; } + SPROUT_CONSTEXPR size_type + find_first_of(basic_string const& str, size_type pos = 0) const SPROUT_NOEXCEPT { + return find_first_of_impl_1(begin(), len, str.begin(), pos, str.size()); + } + SPROUT_CONSTEXPR size_type + find_first_of(value_type const* s, size_type pos, size_type n) const { + return find_first_of_impl_1(begin(), len, s, pos, n); + } + SPROUT_CONSTEXPR size_type + find_first_of(value_type const* s, size_type pos = 0) const { + return find_first_of(s, pos, traits_type::length(s)); + } + SPROUT_CONSTEXPR size_type + find_first_of(value_type c, size_type pos = 0) const { + return find(c, pos); + } + SPROUT_CONSTEXPR size_type + find_last_of(basic_string const& str, size_type pos = npos) const SPROUT_NOEXCEPT { + return find_last_of_impl_1(begin(), len, str.begin(), pos, str.size()); + } + SPROUT_CONSTEXPR size_type + find_last_of(value_type const* s, size_type pos, size_type n) const { + return find_last_of_impl_1(begin(), len, s, pos, n); + } + SPROUT_CONSTEXPR size_type + find_last_of(value_type const* s, size_type pos = npos) const { + return find_last_of(s, pos, traits_type::length(s)); + } + SPROUT_CONSTEXPR size_type + find_last_of(value_type c, size_type pos = npos) const { + return rfind(c, pos); + } SPROUT_CONSTEXPR basic_string substr(size_type pos = 0, size_type n = npos) const { return !(size() < pos) @@ -545,6 +602,38 @@ namespace sprout { return rfind(s, pos, traits_type::length(s)); } template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_index_iterator::value, + size_type + >::type + find_first_of(ConstIterator s, size_type pos, size_type n) const { + return find_first_of_impl_1(begin(), len, s, pos, n); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_index_iterator::value, + size_type + >::type + find_first_of(ConstIterator s, size_type pos = 0) const { + return find_first_of(s, pos, traits_type::length(s)); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_index_iterator::value, + size_type + >::type + find_last_of(ConstIterator s, size_type pos, size_type n) const { + return find_last_of_impl_1(begin(), len, s, pos, n); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::is_index_iterator::value, + size_type + >::type + find_last_of(ConstIterator s, size_type pos = 0) const { + return find_last_of(s, pos, traits_type::length(s)); + } + template SPROUT_CONSTEXPR typename std::enable_if< sprout::is_index_iterator::value, int