diff --git a/sprout/string/char_traits.hpp b/sprout/string/char_traits.hpp index 5e3cbe76..ce20e738 100644 --- a/sprout/string/char_traits.hpp +++ b/sprout/string/char_traits.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -113,7 +114,7 @@ namespace sprout { ); } static SPROUT_CXX14_CONSTEXPR char_type* move(char_type* s1, char_type const* s2, std::size_t n) { - sprout::copy_backward(s2, s2 + n, s1 + n); + sprout::copy_backward(s2, s2 + n, sprout::next(s1, n)); return s1; } static SPROUT_CXX14_CONSTEXPR char_type* copy(char_type* s1, char_type const* s2, std::size_t n) { @@ -160,56 +161,56 @@ namespace sprout { } #endif #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION - template - static SPROUT_CONSTEXPR int compare(char_type const* s1, ConstInputIterator s2, std::size_t n) { + template + static SPROUT_CONSTEXPR int compare(char_type const* s1, ForwardIterator s2, std::size_t n) { return sprout::tristate_lexicographical_compare( sprout::ptr_index(s1), sprout::ptr_index(s1, n), char_type(), - s2, s2 + n, char_type(), + s2, sprout::next(s2, n), char_type(), sprout::detail::char_traits_lt() ); } - template - static SPROUT_CONSTEXPR int compare(ConstInputIterator s1, char_type const* s2, std::size_t n) { + template + static SPROUT_CONSTEXPR int compare(ForwardIterator s1, char_type const* s2, std::size_t n) { return sprout::tristate_lexicographical_compare( - s1, s1 + n, char_type(), + s1, sprout::next(s1, n), char_type(), sprout::ptr_index(s2), sprout::ptr_index(s2, n), char_type(), sprout::detail::char_traits_lt() ); } - template - static SPROUT_CONSTEXPR int compare(ConstInputIterator1 s1, ConstInputIterator2 s2, std::size_t n) { + template + static SPROUT_CONSTEXPR int compare(ForwardIterator1 s1, ForwardIterator2 s2, std::size_t n) { return sprout::tristate_lexicographical_compare( - s1, s1 + n, char_type(), - s2, s2 + n, char_type(), + s1, sprout::next(s1, n), char_type(), + s2, sprout::next(s2, n), char_type(), sprout::detail::char_traits_lt() ); } - template - static SPROUT_CONSTEXPR std::size_t length(ConstInputIterator s) { + template + static SPROUT_CONSTEXPR std::size_t length(InputIterator s) { return sprout::detail::strlen(s); } - template - static SPROUT_CONSTEXPR ConstInputIterator find(ConstInputIterator s, std::size_t n, char_type const& a) { + template + static SPROUT_CONSTEXPR ForwardIterator find(ForwardIterator s, std::size_t n, char_type const& a) { return sprout::ptr_unindex( sprout::find_if( - s, s + n, + s, sprout::next(s, n), sprout::bind2nd(sprout::detail::char_traits_eq(), a) ) ); } - template - static SPROUT_CXX14_CONSTEXPR OutputIterator move(OutputIterator s1, ConstInputIterator s2, std::size_t n) { - sprout::copy_backward(s2, s2 + n, s1 + n); + template + static SPROUT_CXX14_CONSTEXPR BidirectionalIterator1 move(BidirectionalIterator1 s1, BidirectionalIterator2 s2, std::size_t n) { + sprout::copy_backward(s2, sprout::next(s2, n), sprout::next(s1, n)); return s1; } - template - static SPROUT_CXX14_CONSTEXPR OutputIterator copy(OutputIterator s1, ConstInputIterator s2, std::size_t n) { - sprout::copy(s2, s2 + n, s1); + template + static SPROUT_CXX14_CONSTEXPR OutputIterator copy(OutputIterator s1, BidirectionalIterator s2, std::size_t n) { + sprout::copy(s2, sprout::next(s2, n), s1); return s1; } - template - static SPROUT_CXX14_CONSTEXPR OutputIterator assign(OutputIterator s, std::size_t n, char_type a) { - sprout::fill(s, s + n, a); + template + static SPROUT_CXX14_CONSTEXPR ForwardIterator assign(ForwardIterator s, std::size_t n, char_type a) { + sprout::fill(s, sprout::next(s, n), a); return s; } #endif @@ -243,19 +244,19 @@ namespace sprout { return found != last; } #if SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION - template - static SPROUT_CONSTEXPR std::size_t length(ConstInputIterator s, std::size_t n) { + template + static SPROUT_CONSTEXPR std::size_t length(InputIterator s, std::size_t n) { return sprout::detail::strlen(s, n); } - template - static SPROUT_CONSTEXPR ConstInputIterator find(ConstInputIterator s, std::size_t n, char_type const& a) { + template + static SPROUT_CONSTEXPR ForwardIterator find(ForwardIterator s, std::size_t n, char_type const& a) { return sprout::find_if( - s, s + n, + s, sprout::next(s, n), sprout::bind2nd(sprout::detail::char_traits_eq(), a) ); } - template - static SPROUT_CONSTEXPR bool is_found(ConstInputIterator found, ConstInputIterator last) { + template + static SPROUT_CONSTEXPR bool is_found(InputIterator found, InputIterator last) { return found != last; } #endif diff --git a/sprout/string/shift_concat.hpp b/sprout/string/shift_concat.hpp index bcef6ae6..83f9807e 100644 --- a/sprout/string/shift_concat.hpp +++ b/sprout/string/shift_concat.hpp @@ -43,11 +43,11 @@ namespace sprout { )... ); } - template + template inline SPROUT_CONSTEXPR sprout::basic_string string_rshift( sprout::basic_string const& lhs, std::size_t lsize, - T const (& rhs)[M], std::size_t rsize, + T const* rhs, std::size_t rsize, sprout::index_tuple ) { @@ -90,13 +90,12 @@ namespace sprout { sprout::make_index_tuple::make() ); } - template + template inline SPROUT_CONSTEXPR sprout::basic_string - operator<<(sprout::basic_string const& lhs, T const (& rhs)[M]) { - typedef sprout::char_traits_helper traits_type; + operator<<(sprout::basic_string const& lhs, T const* rhs) { return sprout::detail::string_rshift( lhs, lhs.size(), - rhs, traits_type::length(rhs, M - 1), + rhs, Traits::length(rhs), sprout::make_index_tuple::make() ); } @@ -128,11 +127,11 @@ namespace sprout { )... ); } - template + template inline SPROUT_CONSTEXPR sprout::basic_string string_lshift( sprout::basic_string const& lhs, std::size_t lsize, - T const (& rhs)[M], std::size_t rsize, + T const* rhs, std::size_t rsize, sprout::index_tuple ) { @@ -175,13 +174,12 @@ namespace sprout { sprout::make_index_tuple::make() ); } - template + template inline SPROUT_CONSTEXPR sprout::basic_string - operator>>(sprout::basic_string const& lhs, T const (& rhs)[M]) { - typedef sprout::char_traits_helper traits_type; + operator>>(sprout::basic_string const& lhs, T const* rhs) { return sprout::detail::string_lshift( lhs, lhs.size(), - rhs, traits_type::length(rhs, M - 1), + rhs, Traits::length(rhs), sprout::make_index_tuple::make() ); } diff --git a/sprout/string/string.hpp b/sprout/string/string.hpp index 5e06e77f..3d07843d 100644 --- a/sprout/string/string.hpp +++ b/sprout/string/string.hpp @@ -292,12 +292,56 @@ namespace sprout { } } SPROUT_CXX14_CONSTEXPR void put_terminator() { - traits_type::assign(begin() + impl_.len, static_size - impl_.len, value_type()); + traits_type::assign(begin() + size(), static_size - size(), value_type()); } SPROUT_CXX14_CONSTEXPR void put_terminator(size_type n) { impl_.len = n; put_terminator(); } + template + SPROUT_CXX14_CONSTEXPR basic_string& assign(InputIterator first, InputIterator last, std::input_iterator_tag*) { + iterator it = begin(); + for (; first != last; ++first, ++it) { + if (sprout::distance(begin(), it) > static_size) { + throw std::length_error("basic_string<>: length exceeded"); + } + traits_type::assign(*it, *first); + } + put_terminator(sprout::distance(begin(), it)); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& assign(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag*) { + lengthcheck(sprout::distance(first, last)); + iterator it = begin(); + for (; first != last; ++first, ++it) { + traits_type::assign(*it, *first); + } + put_terminator(sprout::distance(begin(), it)); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& append(InputIterator first, InputIterator last, std::input_iterator_tag*) { + iterator it = end(); + for (; first != last; ++first, ++it) { + if (sprout::distance(begin(), it) > static_size) { + throw std::length_error("basic_string<>: length exceeded"); + } + traits_type::assign(*it, *first); + } + put_terminator(size() + sprout::distance(end(), it)); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& append(ForwardIterator first, ForwardIterator last, std::forward_iterator_tag*) { + lengthcheck(size() + sprout::distance(first, last)); + iterator it = end(); + for (; first != last; ++first, ++it) { + traits_type::assign(*it, *first); + } + put_terminator(size() + sprout::distance(end(), it)); + return *this; + } public: // construct/copy/destroy: SPROUT_CONSTEXPR basic_string() SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL @@ -545,23 +589,70 @@ namespace sprout { // modifiers: template SPROUT_CXX14_CONSTEXPR basic_string& + append(basic_string const& str) { + return append(str.begin(), str.size()); + } + template + SPROUT_CXX14_CONSTEXPR basic_string& + append(basic_string const& str, size_type pos, size_type n = npos) { + str.rangecheck(pos); + size_type rlen = n != npos + ? NS_SSCRISK_CEL_OR_SPROUT::min(n, str.size() - pos) + : str.size() - pos + ; + return append(str.begin() + pos, rlen); + } + SPROUT_CXX14_CONSTEXPR basic_string& + append(value_type const* s, size_type n) { + lengthcheck(size() + n); + traits_type::move(end(), s, n); + put_terminator(size() + n); + return *this; + } + SPROUT_CXX14_CONSTEXPR basic_string& + append(value_type const* s) { + return append(s, traits_type::length(s)); + } + SPROUT_CXX14_CONSTEXPR basic_string& + append(size_type n, value_type c) { + lengthcheck(size() + n); + traits_type::assign(end(), n, c); + put_terminator(size() + n); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& + append(InputIterator first, InputIterator last) { + typedef typename std::iterator_traits::iterator_category* category; + return append(first, last, category()); + } + SPROUT_CXX14_CONSTEXPR basic_string& + append(std::initializer_list il) { + return append(il.begin(), il.end()); + } + SPROUT_CXX14_CONSTEXPR void + push_back(value_type c) { + append(size_type(1), c); + } + template + SPROUT_CXX14_CONSTEXPR basic_string& assign(basic_string const& str) { return assign(str, 0, npos); } template SPROUT_CXX14_CONSTEXPR basic_string& - assign(basic_string const& str, size_type pos, size_type n) { - if (str.size() < pos) { - throw std::out_of_range("basic_string<>: index out of range"); - } - return assign(str.begin() + pos, NS_SSCRISK_CEL_OR_SPROUT::min(n, str.size() - pos)); + assign(basic_string const& str, size_type pos, size_type n = npos) { + str.rangecheck(pos); + size_type rlen = n != npos + ? NS_SSCRISK_CEL_OR_SPROUT::min(n, str.size() - pos) + : str.size() - pos + ; + return assign(str.begin() + pos, rlen); } SPROUT_CXX14_CONSTEXPR basic_string& assign(value_type const* s, size_type n) { lengthcheck(n); - for (size_type i = 0; i < n; ++i) { - traits_type::assign(impl_.elems[i], s[i]); - } + traits_type::move(begin(), s, n); put_terminator(n); return *this; } @@ -579,13 +670,18 @@ namespace sprout { template SPROUT_CXX14_CONSTEXPR basic_string& assign(InputIterator first, InputIterator last) { - size_type n = 0; - for (; n < static_size || first != last; ++n, ++first) { - traits_type::assign(impl_.elems[n], *first); - } - put_terminator(n); - return *this; + typedef typename std::iterator_traits::iterator_category* category; + return assign(first, last, category()); } + SPROUT_CXX14_CONSTEXPR basic_string& + assign(std::initializer_list il) { + return assign(il.begin(), il.end()); + } + SPROUT_CXX14_CONSTEXPR void + pop_back() { + put_terminator(size() - 1); + } + //!!! SPROUT_CXX14_CONSTEXPR void swap(basic_string& other) SPROUT_NOEXCEPT_IF_EXPR(sprout::swap(std::declval(), std::declval())) @@ -614,6 +710,13 @@ namespace sprout { c_array() const SPROUT_NOEXCEPT { return impl_.elems; } + SPROUT_CXX14_CONSTEXPR size_type + copy(value_type* s, size_type n, size_type pos = 0) const { + rangecheck(pos); + size_type llen = NS_SSCRISK_CEL_OR_SPROUT::min(n, size() - pos); + traits_type::copy(s, begin() + pos, llen); + return llen; + } template SPROUT_CONSTEXPR size_type find(basic_string const& str, size_type pos = 0) const SPROUT_NOEXCEPT { @@ -770,7 +873,7 @@ namespace sprout { } SPROUT_CXX14_CONSTEXPR void rangecheck(size_type i) const { - return i >= size() ? throw std::out_of_range("uuid: index out of range") + return i >= size() ? throw std::out_of_range("basic_string<>: index out of range") : (void)0 ; } @@ -791,11 +894,28 @@ namespace sprout { is_string_iterator::value, basic_string& >::type + append(StringConstIterator s, size_type n) { + lengthcheck(size() + n); + traits_type::move(end(), s, n); + put_terminator(size() + n); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR typename std::enable_if< + is_string_iterator::value, + basic_string& + >::type + append(StringConstIterator s) { + return append(s, traits_type::length(s)); + } + template + SPROUT_CXX14_CONSTEXPR typename std::enable_if< + is_string_iterator::value, + basic_string& + >::type assign(StringConstIterator s, size_type n) { lengthcheck(n); - for (size_type i = 0; i < n; ++i) { - traits_type::assign(impl_.elems[i], s[i]); - } + traits_type::move(begin(), s, n); put_terminator(n); return *this; } @@ -809,6 +929,14 @@ namespace sprout { } // string operations (for string iterator): + template + SPROUT_CXX14_CONSTEXPR size_type + copy(StringIterator s, size_type n, size_type pos = 0) const { + rangecheck(pos); + size_type llen = NS_SSCRISK_CEL_OR_SPROUT::min(n, size() - pos); + traits_type::copy(s, begin() + pos, llen); + return llen; + } template SPROUT_CONSTEXPR typename std::enable_if< is_string_iterator::value, @@ -973,52 +1101,38 @@ namespace sprout { return sprout::distance(begin(), p); } #endif - SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(T const& rhs) { - lengthcheck(size() + 1); - traits_type::assign(end(), 1, rhs); - put_terminator(impl_.len + 1); + push_back(rhs); return *this; } - template - SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(T const (& rhs)[M]) { - typedef sprout::char_traits_helper helper_type; - std::size_t rsize = helper_type::length(rhs, M - 1); - lengthcheck(size() + rsize); - traits_type::copy(end(), rhs, rsize); - put_terminator(impl_.len + rsize); - return *this; + SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(value_type const* rhs) { + return append(rhs); } template - SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(basic_string const& rhs) { - lengthcheck(size() + rhs.size()); - traits_type::copy(end(), rhs.begin(), rhs.size()); - put_terminator(impl_.len + rhs.size()); - return *this; + SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(basic_string const& rhs) { + return append(rhs); } SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(T const& rhs) { lengthcheck(size() + 1); traits_type::move(begin() + 1, begin(), size()); traits_type::assign(begin(), 1, rhs); - put_terminator(impl_.len + 1); + put_terminator(size() + 1); return *this; } - template - SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(T const (& rhs)[M]) { - typedef sprout::char_traits_helper helper_type; - std::size_t rsize = helper_type::length(rhs, M - 1); - lengthcheck(size() + rsize); - traits_type::move(begin() + rsize, begin(), size()); - traits_type::copy(begin(), rhs, rsize); - put_terminator(impl_.len + rsize); + SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(value_type const* rhs) { + size_type rlen = traits_type::length(rhs); + lengthcheck(size() + rlen); + traits_type::move(begin() + rlen, begin(), size()); + traits_type::move(begin(), rhs, rlen); + put_terminator(size() + rlen); return *this; } template - SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(basic_string const& rhs) { + SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(basic_string const& rhs) { lengthcheck(size() + rhs.size()); traits_type::move(begin() + rhs.size(), begin(), size()); - traits_type::copy(begin(), rhs.begin(), rhs.size()); - put_terminator(impl_.len + rhs.size()); + traits_type::move(begin(), rhs.begin(), rhs.size()); + put_terminator(size() + rhs.size()); return *this; } };