fix recursion depth: cstring algorithm

This commit is contained in:
bolero-MURAKAMI 2013-01-13 01:16:48 +09:00
parent f26032dce8
commit b51b14efa9
25 changed files with 792 additions and 142 deletions

View file

@ -56,7 +56,7 @@ namespace sprout {
template<typename ForwardIterator1>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator1, bool>
search_impl_check(sprout::pair<ForwardIterator1, bool> const& current, ForwardIterator1 last1, ForwardIterator1 searched) {
search_impl_fork(sprout::pair<ForwardIterator1, bool> const& current, ForwardIterator1 last1, ForwardIterator1 searched) {
typedef sprout::pair<ForwardIterator1, bool> type;
return searched == current.first || searched == last1 ? type(searched, true)
: type(sprout::next(current.first), false)
@ -72,7 +72,7 @@ namespace sprout {
{
typedef sprout::pair<ForwardIterator1, bool> type;
return current.second || current.first == last1 ? current
: n == 1 ? sprout::detail::search_impl_check(
: n == 1 ? sprout::detail::search_impl_fork(
current, last1,
sprout::detail::search_one(current.first, last1, first2, last2, pred)
)

View file

@ -87,7 +87,7 @@ namespace sprout {
template<typename InputIterator1, typename InputIterator2, typename Compare>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, InputIterator2>
tristate_lexicographical_compare_impl_1(
sprout::pair<InputIterator1, InputIterator2> current,
sprout::pair<InputIterator1, InputIterator2> const& current,
InputIterator1 last1, InputIterator2 last2, Compare comp,
typename std::iterator_traits<InputIterator1>::difference_type n
)
@ -109,7 +109,7 @@ namespace sprout {
template<typename InputIterator1, typename InputIterator2, typename Compare>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, InputIterator2>
tristate_lexicographical_compare_impl(
sprout::pair<InputIterator1, InputIterator2> current,
sprout::pair<InputIterator1, InputIterator2> const& current,
InputIterator1 last1, InputIterator2 last2, Compare comp,
typename std::iterator_traits<InputIterator1>::difference_type n
)
@ -252,7 +252,7 @@ namespace sprout {
template<typename InputIterator1, typename T1, typename InputIterator2, typename T2, typename Compare>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, InputIterator2>
tristate_lexicographical_compare_impl_1(
sprout::pair<InputIterator1, InputIterator2> current,
sprout::pair<InputIterator1, InputIterator2> const& current,
InputIterator1 last1, T1 const& delim1, InputIterator2 last2, T2 const& delim2, Compare comp,
typename std::iterator_traits<InputIterator1>::difference_type n
)
@ -276,7 +276,7 @@ namespace sprout {
template<typename InputIterator1, typename T1, typename InputIterator2, typename T2, typename Compare>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, InputIterator2>
tristate_lexicographical_compare_impl(
sprout::pair<InputIterator1, InputIterator2> current,
sprout::pair<InputIterator1, InputIterator2> const& current,
InputIterator1 last1, T1 const& delim1, InputIterator2 last2, T2 const& delim2, Compare comp,
typename std::iterator_traits<InputIterator1>::difference_type n
)

View file

@ -1,24 +1,92 @@
#ifndef SPROUT_CSTRING_STRCHR_HPP
#define SPROUT_CSTRING_STRCHR_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/detail/str.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, bool>
strchr_impl_1(
sprout::pair<InputIterator, bool> const& current,
T const& value, typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, bool> type;
return current.second || !*current.first ? current
: n == 1 ? *current.first == value ? type(current.first, true) : type(sprout::next(current.first), false)
: sprout::detail::strchr_impl_1(
sprout::detail::strchr_impl_1(
current,
value, n / 2
),
value, n - n / 2
)
;
}
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, bool>
strchr_impl(
sprout::pair<InputIterator, bool> const& current,
T const& value, typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, bool> type;
return current.second || !*current.first ? current
: sprout::detail::strchr_impl(
sprout::detail::strchr_impl_1(
current,
value, n
),
value, n * 2
)
;
}
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR InputIterator
strchr(InputIterator first, T const& value) {
typedef sprout::pair<InputIterator, bool> type;
return sprout::detail::strchr_impl(type(first, false), value, 1).first;
}
} // namespace detail
// 7.21.5.2 strchr ŠÖ<C5A0>
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR char const*
strchr(char const* s, int c) {
return *s == static_cast<char>(c) ? s
: !*s ? nullptr
: sprout::strchr(s + 1, c)
;
return sprout::detail::str_find_check(
sprout::detail::strchr(s, static_cast<char>(c)),
static_cast<char>(c)
);
}
inline SPROUT_CONSTEXPR char*
strchr(char* s, int c) {
return const_cast<char*>(sprout::strchr(const_cast<char const*>(s), c));
return sprout::detail::str_find_check(
sprout::detail::strchr(s, static_cast<char>(c)),
static_cast<char>(c)
);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
Elem*
>::type
strchr(Elem* s, typename std::decay<Elem>::type c) {
return sprout::detail::str_find_check(
sprout::detail::strchr(s, c),
c
);
}
} // namespace sprout

View file

@ -1,20 +1,91 @@
#ifndef SPROUT_CSTRING_STRCMP_HPP
#define SPROUT_CSTRING_STRCMP_HPP
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/type_traits/is_char_type.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename InputIterator1, typename InputIterator2>
inline SPROUT_CONSTEXPR int
strcmp_impl_check(sprout::tuples::tuple<InputIterator1, InputIterator2, int> const& found) {
return !*sprout::tuples::get<1>(found) ? (!*sprout::tuples::get<0>(found) ? 0 : 1)
: !*sprout::tuples::get<0>(found) ? -1
: sprout::tuples::get<2>(found)
;
}
template<typename InputIterator1, typename InputIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, InputIterator2, int>
strcmp_impl_1(
sprout::tuples::tuple<InputIterator1, InputIterator2, int> const& current,
typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, int> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<1>(current) || !*sprout::tuples::get<0>(current) ? current
: n == 1 ? (*sprout::tuples::get<0>(current)) < (*sprout::tuples::get<1>(current)) ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), -1)
: (*sprout::tuples::get<1>(current)) < (*sprout::tuples::get<0>(current)) ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), 1)
: type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), 0)
: sprout::detail::strcmp_impl_1(
sprout::detail::strcmp_impl_1(
current,
n / 2
),
n - n / 2
)
;
}
template<typename InputIterator1, typename InputIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, InputIterator2, int>
strcmp_impl(
sprout::tuples::tuple<InputIterator1, InputIterator2, int> const& current,
typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, int> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<1>(current) || !*sprout::tuples::get<0>(current) ? current
: sprout::detail::strcmp_impl(
sprout::detail::strcmp_impl_1(
current,
n
),
n * 2
)
;
}
template<typename InputIterator1, typename InputIterator2>
inline SPROUT_CONSTEXPR int
strcmp(InputIterator1 first1, InputIterator2 first2)
{
typedef sprout::tuples::tuple<InputIterator1, InputIterator2, int> type;
return sprout::detail::strcmp_impl_check(
sprout::detail::strcmp_impl(type(first1, first2, 0), 1)
);
}
} // namespace detail
// 7.21.4.2 strcmp ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
strcmp(char const* s1, char const* s2) {
return !*s1 && !*s2 ? 0
: !*s1 ? -1
: !*s2 ? 1
: *s1 == *s2 ? sprout::strcmp(s1 + 1, s2 + 1)
: static_cast<unsigned char>(*s1) - static_cast<unsigned char>(*s2)
;
return sprout::detail::strcmp(s1, s2);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
int
>::type
strcmp(Elem* s1, Elem* s2) {
return sprout::detail::strcmp(s1, s2);
}
} // namespace sprout

View file

@ -1,17 +1,30 @@
#ifndef SPROUT_CSTRING_STRCOLL_HPP
#define SPROUT_CSTRING_STRCOLL_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/cstring/strcmp.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
// 7.21.4.3 strcoll ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
strcoll(char const* s1, char const* s2) {
return sprout::strcmp(s1, s2);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
int
>::type
strcoll(Elem* s1, Elem* s2) {
return sprout::strcmp(s1, s2);
}
} // namespace sprout
#endif // #ifndef SPROUT_CSTRING_STRCOLL_HPP

View file

@ -2,16 +2,80 @@
#define SPROUT_CSTRING_STRCSPN_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/cstring/strchr.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, std::size_t, bool>
strcspn_impl_1(
sprout::tuples::tuple<InputIterator1, std::size_t, bool> const& current,
ForwardIterator2 first2, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<0>(current) ? current
: n == 1 ? !*sprout::detail::strchr(first2, *sprout::tuples::get<0>(current))
? type(sprout::next(sprout::tuples::get<0>(current)), sprout::tuples::get<1>(current) + 1, false)
: type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true)
: sprout::detail::strcspn_impl_1(
sprout::detail::strcspn_impl_1(
current,
first2, n / 2
),
first2, n - n / 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, std::size_t, bool>
strcspn_impl(
sprout::tuples::tuple<InputIterator1, std::size_t, bool> const& current,
ForwardIterator2 first2, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<0>(current) ? current
: sprout::detail::strcspn_impl(
sprout::detail::strcspn_impl_1(
current,
first2, n
),
first2, n * 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR std::size_t
strcspn(InputIterator1 first1, ForwardIterator2 first2) {
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<1>(sprout::detail::strcspn_impl(type(first1, 0, false), first2, 1));
}
} // namespace detail
// 7.21.5.3 strcspn ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR std::size_t
strcspn(char const* s1, char const* s2) {
return !*s1 || sprout::strchr(s2, *s1) ? 0
: 1 + sprout::strcspn(s1 + 1, s2)
;
return sprout::detail::strcspn(s1, s2);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
std::size_t
>::type
strcspn(Elem* s1, Elem* s2) {
return sprout::detail::strcspn(s1, s2);
}
} // namespace sprout

View file

@ -2,20 +2,71 @@
#define SPROUT_CSTRING_STRLEN_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/ptr_index_iterator.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/iterator/ptr_index_iterator.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/algorithm/find.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, std::size_t>
strlen_impl_1(
sprout::pair<InputIterator, std::size_t> const& current,
typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, std::size_t> type;
return !*current.first ? current
: n == 1 ? type(sprout::next(current.first), current.second + 1)
: sprout::detail::strlen_impl_1(
sprout::detail::strlen_impl_1(
current,
n / 2
),
n - n / 2
)
;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator, std::size_t>
strlen_impl(
sprout::pair<InputIterator, std::size_t> const& current,
typename std::iterator_traits<InputIterator>::difference_type n
)
{
typedef sprout::pair<InputIterator, std::size_t> type;
return !*current.first ? current
: sprout::detail::strlen_impl(
sprout::detail::strlen_impl_1(
current,
n
),
n * 2
)
;
}
template<typename InputIterator>
inline SPROUT_CONSTEXPR std::size_t
strlen(InputIterator first) {
typedef sprout::pair<InputIterator, std::size_t> type;
return sprout::detail::strlen_impl(type(first, 0), 1).second;
}
} // namespace detail
// 7.21.6.3 strlen ŠÖ<C5A0>
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR std::size_t
strlen(char const* s) {
return !*s ? 0
: 1 + sprout::strlen(s + 1)
;
return sprout::detail::strlen(s);
}
inline SPROUT_CONSTEXPR std::size_t
strlen(char const* s, std::size_t n) {
return sprout::distance(
@ -23,6 +74,27 @@ namespace sprout {
sprout::find(sprout::as_iterator(s), sprout::as_iterator(s, n), '\0')
);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
std::size_t
>::type
strlen(Elem* s) {
return sprout::detail::strlen(s);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
std::size_t
>::type
strlen(Elem* s, std::size_t n) {
typedef typename std::decay<Elem>::type type;
return sprout::distance(
sprout::as_iterator(s),
sprout::find(sprout::as_iterator(s), sprout::as_iterator(s, n), type())
);
}
} // namespace sprout
#endif // #ifndef SPROUT_CSTRING_STRLEN_HPP

View file

@ -2,12 +2,18 @@
#define SPROUT_CSTRING_STRNCMP_HPP
#include <cstddef>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/ptr_index_iterator.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/algorithm/tristate_lexicographical_compare.hpp>
namespace sprout {
// 7.21.4.4 strncmp ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
strncmp(char const* s1, char const* s2, std::size_t n) {
return sprout::tristate_lexicographical_compare(
@ -15,6 +21,19 @@ namespace sprout {
sprout::as_iterator(s2), sprout::as_iterator(s2, n), '\0'
);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
int
>::type
strncmp(Elem* s1, Elem* s2, std::size_t n) {
typedef typename std::decay<Elem>::type type;
return sprout::tristate_lexicographical_compare(
sprout::as_iterator(s1), sprout::as_iterator(s1, n), type(),
sprout::as_iterator(s2), sprout::as_iterator(s2, n), type()
);
}
} // namespace sprout
#endif // #ifndef SPROUT_CSTRING_STRNCMP_HPP

View file

@ -1,25 +1,93 @@
#ifndef SPROUT_CSTRING_STRPBRK_HPP
#define SPROUT_CSTRING_STRPBRK_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/cstring/strchr.hpp>
#include <sprout/detail/str.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, bool>
strpbrk_impl_1(
sprout::pair<InputIterator1, bool> current,
ForwardIterator2 first2,
typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::pair<InputIterator1, bool> type;
return current.second || !*current.first ? current
: n == 1 ? sprout::strchr(first2, *current.first)
? type(current.first, true)
: type(sprout::next(current.first), false)
: sprout::detail::strpbrk_impl_1(
sprout::detail::strpbrk_impl_1(
current,
first2, n / 2
),
first2, n - n / 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::pair<InputIterator1, bool>
strpbrk_impl(
sprout::pair<InputIterator1, bool> current,
ForwardIterator2 first2,
typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::pair<InputIterator1, bool> type;
return current.second || !*current.first ? current
: sprout::detail::strpbrk_impl(
sprout::detail::strpbrk_impl_1(
current,
first2, n
),
first2, n * 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR InputIterator1
strpbrk(InputIterator1 first1, ForwardIterator2 first2) {
typedef sprout::pair<InputIterator1, bool> type;
return sprout::detail::strpbrk_impl(type(first1, false), first2, 1).first;
}
} // namespace detail
// 7.21.5.4 strpbrk ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR char const*
strpbrk(char const* s1, char const* s2) {
return !*s1 ? nullptr
: sprout::strchr(s2, *s1) ? s1
: sprout::strpbrk(s1 + 1, s2)
;
return sprout::detail::str_find_check(
sprout::detail::strpbrk(s1, s2)
);
}
inline SPROUT_CONSTEXPR char*
strpbrk(char* s1, char const* s2) {
return const_cast<char*>(sprout::strpbrk(const_cast<char const*>(s1), s2));
return sprout::detail::str_find_check(
sprout::detail::strpbrk(s1, s2)
);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
Elem*
>::type
strpbrk(Elem* s1, typename std::remove_const<Elem>::type const* s2) {
return sprout::detail::str_find_check(
sprout::detail::strpbrk(s1, s2)
);
}
} // namespace sprout

View file

@ -1,24 +1,94 @@
#ifndef SPROUT_CSTRING_STRRCHR_HPP
#define SPROUT_CSTRING_STRRCHR_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/type_traits/is_char_type.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename ForwardIterator, typename T>
inline SPROUT_CONSTEXPR ForwardIterator
strrchr_impl_check(sprout::pair<ForwardIterator, ForwardIterator> const& found, T const& value) {
return *found.second == value ? found.second
: !value ? found.first
: ForwardIterator()
;
}
template<typename ForwardIterator, typename T>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, ForwardIterator>
strrchr_impl_1(
sprout::pair<ForwardIterator, ForwardIterator> const& current,
T const& value,
typename std::iterator_traits<ForwardIterator>::difference_type n
)
{
typedef sprout::pair<ForwardIterator, ForwardIterator> type;
return !*current.first ? current
: n == 1 ? *current.first == value ? type(sprout::next(current.first), current.first) : type(sprout::next(current.first), current.second)
: sprout::detail::strrchr_impl_1(
sprout::detail::strrchr_impl_1(
current,
value, n / 2
),
value, n - n / 2
)
;
}
template<typename ForwardIterator, typename T>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, ForwardIterator>
strrchr_impl(
sprout::pair<ForwardIterator, ForwardIterator> const& current,
T const& value,
typename std::iterator_traits<ForwardIterator>::difference_type n
)
{
typedef sprout::pair<ForwardIterator, ForwardIterator> type;
return !*current.first ? current
: sprout::detail::strrchr_impl(
sprout::detail::strrchr_impl_1(
current,
value, n
),
value, n * 2
)
;
}
template<typename ForwardIterator, typename T>
inline SPROUT_CONSTEXPR ForwardIterator
strrchr(ForwardIterator first, T const& value) {
typedef sprout::pair<ForwardIterator, ForwardIterator> type;
return sprout::detail::strrchr_impl_check(
sprout::detail::strrchr_impl(type(first, first), value, 1),
value
);
}
} // namespace detail
// 7.21.5.5 strrchr ŠÖ<C5A0>
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR char const*
strrchr(char const* s, int c) {
return *s == static_cast<char>(c) && (!*s || !sprout::strrchr(s + 1, c))? s
: !*s ? nullptr
: sprout::strrchr(s + 1, c)
;
return sprout::detail::strrchr(s, static_cast<char>(c));
}
inline SPROUT_CONSTEXPR char*
strrchr(char* s, int c) {
return const_cast<char*>(sprout::strrchr(const_cast<char const*>(s), c));
return sprout::detail::strrchr(s, static_cast<char>(c));
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
Elem*
>::type
strrchr(Elem* s, typename std::decay<Elem>::type c) {
return sprout::detail::strrchr(s, c);
}
} // namespace sprout

View file

@ -2,16 +2,80 @@
#define SPROUT_CSTRING_STRSPN_HPP
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/cstring/strchr.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, std::size_t, bool>
strspn_impl_1(
sprout::tuples::tuple<InputIterator1, std::size_t, bool> const& current,
ForwardIterator2 first2, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<0>(current) ? current
: n == 1 ? *sprout::detail::strchr(first2, *sprout::tuples::get<0>(current))
? type(sprout::next(sprout::tuples::get<0>(current)), sprout::tuples::get<1>(current) + 1, false)
: type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true)
: sprout::detail::strspn_impl_1(
sprout::detail::strspn_impl_1(
current,
first2, n / 2
),
first2, n - n / 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<InputIterator1, std::size_t, bool>
strspn_impl(
sprout::tuples::tuple<InputIterator1, std::size_t, bool> const& current,
ForwardIterator2 first2, typename std::iterator_traits<InputIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<2>(current) || !*sprout::tuples::get<0>(current) ? current
: sprout::detail::strspn_impl(
sprout::detail::strspn_impl_1(
current,
first2, n
),
first2, n * 2
)
;
}
template<typename InputIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR std::size_t
strspn(InputIterator1 first1, ForwardIterator2 first2) {
typedef sprout::tuples::tuple<InputIterator1, std::size_t, bool> type;
return sprout::tuples::get<1>(sprout::detail::strspn_impl(type(first1, 0, false), first2, 1));
}
} // namespace detail
// 7.21.5.6 strspn ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR std::size_t
strspn(char const* s1, char const* s2) {
return !*s1 || !sprout::strchr(s2, *s1) ? 0
: 1 + sprout::strspn(s1 + 1, s2)
;
return sprout::detail::strspn(s1, s2);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
std::size_t
>::type
strspn(Elem* s1, Elem* s2) {
return sprout::detail::strspn(s1, s2);
}
} // namespace sprout

View file

@ -1,24 +1,154 @@
#ifndef SPROUT_CSTRING_STRSTR_HPP
#define SPROUT_CSTRING_STRSTR_HPP
#include <iterator>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/utility/pair.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/type_traits/is_char_type.hpp>
#include <sprout/detail/str.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
namespace detail {
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool>
strstr_one_impl_1(
sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> const& current,
ForwardIterator1 first1_, typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<2>(current) ? current
: !*sprout::tuples::get<1>(current) ? type(first1_, sprout::tuples::get<1>(current), true)
: !*sprout::tuples::get<0>(current) ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true)
: n == 1 ? !(*sprout::tuples::get<0>(current) == *sprout::tuples::get<1>(current))
? type(sprout::next(sprout::tuples::get<0>(current)), sprout::tuples::get<1>(current), true)
: type(sprout::next(sprout::tuples::get<0>(current)), sprout::next(sprout::tuples::get<1>(current)), false)
: sprout::detail::strstr_one_impl_1(
sprout::detail::strstr_one_impl_1(
current,
first1_, n / 2
),
first1_, n - n / 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool>
strstr_one_impl(
sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> const& current,
ForwardIterator1 first1_, typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<2>(current) ? current
: !*sprout::tuples::get<1>(current) ? type(first1_, sprout::tuples::get<1>(current), true)
: !*sprout::tuples::get<0>(current) ? type(sprout::tuples::get<0>(current), sprout::tuples::get<1>(current), true)
: sprout::detail::strstr_one_impl(
sprout::detail::strstr_one_impl_1(
current,
first1_, n
),
first1_, n * 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR ForwardIterator1
strstr_one(ForwardIterator1 first1, ForwardIterator2 first2) {
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<0>(sprout::detail::strstr_one_impl(type(first1, first2, false), first1, 1));
}
template<typename ForwardIterator>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator, bool>
strstr_impl_fork(sprout::pair<ForwardIterator, bool> const& current, ForwardIterator searched) {
typedef sprout::pair<ForwardIterator, bool> type;
return searched == current.first || !*searched ? type(searched, true)
: type(sprout::next(current.first), false)
;
}
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator1, bool>
strstr_impl_1(
sprout::pair<ForwardIterator1, bool> const& current,
ForwardIterator2 first2,
typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
typedef sprout::pair<ForwardIterator1, bool> type;
return current.second || !*current.first ? current
: n == 1 ? sprout::detail::strstr_impl_fork(
current,
sprout::detail::strstr_one(current.first, first2)
)
: sprout::detail::strstr_impl_1(
sprout::detail::strstr_impl_1(
current,
first2, n / 2
),
first2, n - n / 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR sprout::pair<ForwardIterator1, bool>
strstr_impl(
sprout::pair<ForwardIterator1, bool> const& current,
ForwardIterator2 first2,
typename std::iterator_traits<ForwardIterator1>::difference_type n
)
{
typedef sprout::pair<ForwardIterator1, bool> type;
return current.second || !*current.first ? current
: sprout::detail::strstr_impl(
sprout::detail::strstr_impl_1(
current,
first2, n
),
first2, n * 2
)
;
}
template<typename ForwardIterator1, typename ForwardIterator2>
inline SPROUT_CONSTEXPR ForwardIterator1
strstr(ForwardIterator1 first1, ForwardIterator2 first2) {
typedef sprout::pair<ForwardIterator1, bool> type;
return !*first2 ? first1
: sprout::detail::strstr_impl(type(first1, false), first2, 1).first
;
}
} // namespace detail
// 7.21.5.7 strstr ŠÖ<C5A0>
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR char const*
strstr(char const* s1, char const* s2) {
return !*s2 ? s1
: !*s1 ? nullptr
: *s1 == *s2 && sprout::strstr(s1 + 1, s2 + 1) ? s1
: sprout::strstr(s1 + 1, s2)
;
return sprout::detail::str_find_check(
sprout::detail::strstr(s1, s2)
);
}
inline SPROUT_CONSTEXPR char*
strstr(char* s1, char const* s2) {
return const_cast<char*>(sprout::strstr(const_cast<char const*>(s1), s2));
return sprout::detail::str_find_check(
sprout::detail::strstr(s1, s2)
);
}
template<typename Elem>
inline SPROUT_CONSTEXPR typename std::enable_if<
sprout::is_char_type<Elem>::value,
Elem*
>::type
strstr(Elem* s1, typename std::remove_const<Elem>::type const* s2) {
return sprout::detail::str_find_check(
sprout::detail::strstr(s1, s2)
);
}
} // namespace sprout

View file

@ -3,21 +3,22 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/cstring/strchr.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcschr
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR wchar_t const*
wcschr(wchar_t const* s, int c) {
return *s == static_cast<wchar_t>(c) ? s
: !*s ? nullptr
: sprout::wcschr(s + 1, c)
;
wcschr(wchar_t const* s, wchar_t c) {
return sprout::strchr(s, c);
}
inline SPROUT_CONSTEXPR wchar_t*
wcschr(wchar_t* s, int c) {
return const_cast<wchar_t*>(sprout::wcschr(const_cast<wchar_t const*>(s), c));
wcschr(wchar_t* s, wchar_t c) {
return sprout::strchr(s, c);
}
} // namespace sprout

View file

@ -2,21 +2,18 @@
#define SPROUT_CWCHAR_WCSCMP_HPP
#include <sprout/config.hpp>
#include <sprout/cstring/strcmp.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcscmp
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
wcscmp(wchar_t const* s1, wchar_t const* s2) {
return !*s1 && !*s2 ? 0
: !*s1 ? -1
: !*s2 ? 1
: *s1 == *s2 ? sprout::wcscmp(s1 + 1, s2 + 1)
: *s1 - *s2
;
return sprout::strcmp(s1, s2);
}
} // namespace sprout

View file

@ -2,17 +2,18 @@
#define SPROUT_CWCHAR_WCSCOLL_HPP
#include <sprout/config.hpp>
#include <sprout/cwchar/wcscmp.hpp>
#include <sprout/cstring/strcoll.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcscoll
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
wcscoll(wchar_t const* s1, wchar_t const* s2) {
return sprout::wcscmp(s1, s2);
return sprout::strcoll(s1, s2);
}
} // namespace sprout

View file

@ -3,17 +3,18 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/cwchar/wcschr.hpp>
#include <sprout/cstring/strcspn.hpp>
namespace sprout {
//
// wcscspn
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR std::size_t
wcscspn(wchar_t const* s1, wchar_t const* s2) {
return !*s1 || sprout::wcschr(s2, *s1) ? 0
: 1 + sprout::wcscspn(s1 + 1, s2)
;
return sprout::strcspn(s1, s2);
}
} // namespace sprout

View file

@ -3,27 +3,22 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/iterator/ptr_index_iterator.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/algorithm/find.hpp>
#include <sprout/cstring/strlen.hpp>
namespace sprout {
//
// wcslen
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR std::size_t
wcslen(wchar_t const* s) {
return !*s ? 0
: 1 + sprout::wcslen(s + 1)
;
return sprout::strlen(s);
}
inline SPROUT_CONSTEXPR std::size_t
wcslen(wchar_t const* s, std::size_t n) {
return sprout::distance(
sprout::as_iterator(s),
sprout::find(sprout::as_iterator(s), sprout::as_iterator(s, n), L'\0')
);
return sprout::strlen(s, n);
}
} // namespace sprout

View file

@ -3,19 +3,18 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/iterator/ptr_index_iterator.hpp>
#include <sprout/algorithm/tristate_lexicographical_compare.hpp>
#include <sprout/cstring/strncmp.hpp>
namespace sprout {
//
// wcsncmp
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR int
wcsncmp(wchar_t const* s1, wchar_t const* s2, std::size_t n) {
return sprout::tristate_lexicographical_compare(
sprout::as_iterator(s1), sprout::as_iterator(s1, n), L'\0',
sprout::as_iterator(s2), sprout::as_iterator(s2, n), L'\0'
);
return sprout::strncmp(s1, s2, n);
}
} // namespace sprout

View file

@ -3,25 +3,22 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/cwchar/wcschr.hpp>
#include <sprout/cstring/strpbrk.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcspbrk
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR wchar_t const*
wcspbrk(wchar_t const* s1, wchar_t const* s2) {
return !*s1 ? nullptr
: sprout::wcschr(s2, *s1) ? s1
: sprout::wcspbrk(s1 + 1, s2)
;
return sprout::strpbrk(s1, s2);
}
inline SPROUT_CONSTEXPR wchar_t*
wcspbrk(wchar_t* s1, wchar_t const* s2) {
return const_cast<wchar_t*>(sprout::wcspbrk(const_cast<wchar_t const*>(s1), s2));
return sprout::strpbrk(s1, s2);
}
} // namespace sprout

View file

@ -3,24 +3,22 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/cstring/strrchr.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcsrchr
//
// recursion depth:
// O(log N)
//
inline SPROUT_CONSTEXPR wchar_t const*
wcsrchr(wchar_t const* s, int c) {
return *s == static_cast<wchar_t>(c) && (!*s || !sprout::wcsrchr(s + 1, c))? s
: !*s ? nullptr
: sprout::wcsrchr(s + 1, c)
;
wcsrchr(wchar_t const* s, wchar_t c) {
return sprout::strrchr(s, c);
}
inline SPROUT_CONSTEXPR wchar_t*
wcsrchr(wchar_t* s, int c) {
return const_cast<wchar_t*>(sprout::wcsrchr(const_cast<wchar_t const*>(s), c));
wcsrchr(wchar_t* s, wchar_t c) {
return sprout::strrchr(s, c);
}
} // namespace sprout

View file

@ -3,17 +3,18 @@
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/cwchar/wcschr.hpp>
#include <sprout/cstring/strspn.hpp>
namespace sprout {
//
// wcsspn
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR std::size_t
wcsspn(wchar_t const* s1, wchar_t const* s2) {
return !*s1 || !sprout::wcschr(s2, *s1) ? 0
: 1 + sprout::wcsspn(s1 + 1, s2)
;
return sprout::strspn(s1, s2);
}
} // namespace sprout

View file

@ -2,22 +2,22 @@
#define SPROUT_CWCHAR_WCSSTR_HPP
#include <sprout/config.hpp>
#include <sprout/cstring/strstr.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
//
// wcsstr
//
// recursion depth:
// O(log(N1+N2))
//
inline SPROUT_CONSTEXPR wchar_t const*
wcsstr(wchar_t const* s1, wchar_t const* s2) {
return !*s2 ? s1
: !*s1 ? nullptr
: *s1 == *s2 && sprout::wcsstr(s1 + 1, s2 + 1) ? s1
: sprout::wcsstr(s1 + 1, s2)
;
return sprout::strstr(s1, s2);
}
inline SPROUT_CONSTEXPR wchar_t*
wcsstr(wchar_t* s1, wchar_t const* s2) {
return const_cast<wchar_t*>(sprout::wcsstr(const_cast<wchar_t const*>(s1), s2));
return sprout::strstr(s1, s2);
}
} // namespace sprout

View file

@ -89,9 +89,7 @@ namespace sprout {
)
{
typedef sprout::tuples::tuple<ForwardIterator1, ForwardIterator2, bool> type;
return sprout::tuples::get<0>(
sprout::detail::search_one_impl(type(first1, first2, false), last1, last2, pred, first1, 1)
);
return sprout::tuples::get<0>(sprout::detail::search_one_impl(type(first1, first2, false), last1, last2, pred, first1, 1));
}
//

26
sprout/detail/str.hpp Normal file
View file

@ -0,0 +1,26 @@
#ifndef SPROUT_DETAIL_STR_HPP
#define SPROUT_DETAIL_STR_HPP
#include <sprout/config.hpp>
namespace sprout {
namespace detail {
template<typename InputIterator>
inline SPROUT_CONSTEXPR InputIterator
str_find_check(InputIterator found) {
return !*found ? InputIterator()
: found
;
}
template<typename InputIterator, typename T>
inline SPROUT_CONSTEXPR InputIterator
str_find_check(InputIterator found, T const& value) {
return !(*found == value) && !*found ? InputIterator()
: found
;
}
} // namespace detail
} // namespace sprout
#endif // #ifndef SPROUT_DETAIL_STR_HPP

View file

@ -10,6 +10,7 @@
#include <sprout/algorithm/find_if.hpp>
#include <sprout/algorithm/tristate_lexicographical_compare.hpp>
#include <sprout/iterator/operation.hpp>
#include <sprout/cstring/strlen.hpp>
namespace sprout {
//
@ -62,9 +63,7 @@ namespace sprout {
);
}
static SPROUT_CONSTEXPR std::size_t length(char_type const* s) {
return !*s ? 0
: 1 + length(s + 1)
;
return sprout::detail::strlen(s);
}
static SPROUT_CONSTEXPR char_type const* find(char_type const* s, std::size_t n, char_type const& a) {
return find_impl(
@ -128,9 +127,7 @@ namespace sprout {
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR std::size_t length(ConstIterator s) {
return !*s ? 0
: 1 + length(s + 1)
;
return sprout::detail::strlen(s);
}
template<typename ConstIterator>
static SPROUT_CONSTEXPR ConstIterator find(ConstIterator s, std::size_t n, char_type const& a) {