diff --git a/sprout/string.hpp b/sprout/string.hpp index b98cf055..d5a630ca 100644 --- a/sprout/string.hpp +++ b/sprout/string.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/sprout/string/shift_concat.hpp b/sprout/string/shift_concat.hpp new file mode 100644 index 00000000..10a9c691 --- /dev/null +++ b/sprout/string/shift_concat.hpp @@ -0,0 +1,199 @@ +/*============================================================================= + Copyright (c) 2011-2016 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_STRING_SHIFT_CONCAT_HPP +#define SPROUT_STRING_SHIFT_CONCAT_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR std::size_t checked_length(std::size_t n) { + return n <= N ? n + : throw std::length_error("length exceeded") + ; + } + } // namespace detail + + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::basic_string + string_rshift( + sprout::basic_string const& lhs, std::size_t lsize, + T const& rhs, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(lsize + 1), + (Indexes < lsize ? lhs[Indexes] + : Indexes < lsize + 1 ? rhs + : T() + )... + ); + } + 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, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(lsize + rsize), + (Indexes < lsize ? lhs[Indexes] + : Indexes < lsize + rsize ? rhs[Indexes - lsize] + : T() + )... + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + string_rshift( + sprout::basic_string const& lhs, std::size_t lsize, + sprout::basic_string const& rhs, std::size_t rsize, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(lsize + rsize), + (Indexes < lsize ? lhs[Indexes] + : Indexes < lsize + rsize ? rhs[Indexes - lsize] + : T() + )... + ); + } + } // namespace detail + // + // operator<< + // + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator<<(sprout::basic_string const& lhs, T const& rhs) { + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, + sprout::make_index_tuple::make() + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator<<(sprout::basic_string const& lhs, T const (& rhs)[M]) { + typedef sprout::char_traits_helper traits_type; + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, traits_type::length(rhs, M - 1), + sprout::make_index_tuple::make() + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator<<(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, rhs.size(), + sprout::make_index_tuple::make() + ); + } + + namespace detail { + template + inline SPROUT_CONSTEXPR sprout::basic_string + string_lshift( + sprout::basic_string const& lhs, std::size_t lsize, + T const& rhs, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(1 + lsize), + (Indexes < 1 ? rhs + : Indexes < 1 + lsize ? lhs[Indexes - 1] + : T() + )... + ); + } + 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, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(rsize + lsize), + (Indexes < rsize ? rhs[Indexes] + : Indexes < rsize + lsize ? lhs[Indexes - rsize] + : T() + )... + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + string_lshift( + sprout::basic_string const& lhs, std::size_t lsize, + sprout::basic_string const& rhs, std::size_t rsize, + sprout::index_tuple + ) + { + typedef sprout::detail::string_construct_access access_type; + return access_type::raw_construct( + sprout::detail::checked_length(rsize + lsize), + (Indexes < rsize ? rhs[Indexes] + : Indexes < rsize + lsize ? lhs[Indexes - rsize] + : T() + )... + ); + } + // + // operator>> + // + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator>>(sprout::basic_string const& lhs, T const& rhs) { + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, + sprout::make_index_tuple::make() + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator>>(sprout::basic_string const& lhs, T const (& rhs)[M]) { + typedef sprout::char_traits_helper traits_type; + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, traits_type::length(rhs, M - 1), + sprout::make_index_tuple::make() + ); + } + template + inline SPROUT_CONSTEXPR sprout::basic_string + operator>>(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + return sprout::detail::string_rshift( + lhs, lhs.size(), + rhs, rhs.size(), + sprout::make_index_tuple::make() + ); + } + } // namespace detail +} // namespace sprout + +#endif // #ifndef SPROUT_STRING_SHIFT_CONCAT_HPP diff --git a/sprout/string/string.hpp b/sprout/string/string.hpp index 753d49a9..95b04299 100644 --- a/sprout/string/string.hpp +++ b/sprout/string/string.hpp @@ -288,9 +288,16 @@ namespace sprout { } SPROUT_CXX14_CONSTEXPR void lengthcheck(size_type n) const { if (n > static_size) { - throw std::length_error("basic_string<>: length error"); + throw std::length_error("basic_string<>: length exceeded"); } } + SPROUT_CXX14_CONSTEXPR void put_terminator() { + traits_type::assign(begin() + impl_.len, static_size - impl_.len, value_type()); + } + SPROUT_CXX14_CONSTEXPR void put_terminator(size_type n) { + impl_.len = n; + put_terminator(); + } public: // construct/copy/destroy: SPROUT_CONSTEXPR basic_string() SPROUT_DEFAULTED_DEFAULT_CONSTRUCTOR_DECL @@ -484,8 +491,7 @@ namespace sprout { if (n > size()) { traits_type::assign(end(), n - size(), c); } - traits_type::assign(begin() + n, static_size - n, value_type()); - impl_.len = n; + put_terminator(n); } SPROUT_CXX14_CONSTEXPR void resize(size_type n) { @@ -493,8 +499,7 @@ namespace sprout { } SPROUT_CXX14_CONSTEXPR void clear() SPROUT_NOEXCEPT { - traits_type::assign(begin(), static_size, value_type()); - impl_.len = 0; + put_terminator(0); } SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { @@ -557,10 +562,7 @@ namespace sprout { for (size_type i = 0; i < n; ++i) { traits_type::assign(impl_.elems[i], s[i]); } - for (size_type i = n; i < static_size; ++i) { - traits_type::assign(impl_.elems[i], value_type()); - } - impl_.len = n; + put_terminator(n); return *this; } SPROUT_CXX14_CONSTEXPR basic_string& @@ -571,8 +573,7 @@ namespace sprout { assign(size_type n, value_type c) { maxcheck(n); traits_type::assign(begin(), n, c); - traits_type::assign(begin() + n, static_size - n, value_type()); - impl_.len = n; + put_terminator(n); return *this; } template @@ -582,10 +583,7 @@ namespace sprout { for (; n < static_size || first != last; ++n, ++first) { traits_type::assign(impl_.elems[n], *first); } - for (size_type i = n; i < static_size; ++i) { - traits_type::assign(impl_.elems[i], value_type()); - } - impl_.len = n; + put_terminator(n); return *this; } SPROUT_CXX14_CONSTEXPR void @@ -787,7 +785,6 @@ namespace sprout { operator=(StringConstIterator rhs) { return assign(rhs); } - // modifiers (for string iterator): template SPROUT_CXX14_CONSTEXPR typename std::enable_if< @@ -799,10 +796,7 @@ namespace sprout { for (size_type i = 0; i < n; ++i) { traits_type::assign(impl_.elems[i], s[i]); } - for (size_type i = n; i < static_size; ++i) { - traits_type::assign(impl_.elems[i], value_type()); - } - impl_.len = n; + put_terminator(n); return *this; } template @@ -979,6 +973,52 @@ 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); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& operator<<=(T const (& rhs)[M]) { + std::size_t rsize = traits_type::length(rhs, M - 1); + lengthcheck(size() + rsize); + traits_type::copy(end(), rhs, rsize); + put_terminator(impl_.len + rsize); + return *this; + } + 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>>=(T const& rhs) { + lengthcheck(size() + 1); + traits_type::move(begin() + 1, begin(), size()); + traits_type::assign(begin(), 1, rhs); + put_terminator(impl_.len + 1); + return *this; + } + template + SPROUT_CXX14_CONSTEXPR basic_string& operator>>=(T const (& rhs)[M]) { + std::size_t rsize = traits_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); + return *this; + } + template + 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()); + return *this; + } }; template SPROUT_CONSTEXPR_OR_CONST typename sprout::basic_string::size_type sprout::basic_string::npos; diff --git a/sprout/sub_array/sub_array.hpp b/sprout/sub_array/sub_array.hpp index fbb60d47..5834217d 100644 --- a/sprout/sub_array/sub_array.hpp +++ b/sprout/sub_array/sub_array.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include namespace sprout { @@ -223,6 +224,7 @@ namespace sprout { SPROUT_STATIC_CONSTEXPR bool is_reference = impl_type::is_reference; SPROUT_STATIC_CONSTEXPR bool is_const = impl_type::is_const; public: + typedef typename facade_type::value_type value_type; typedef typename facade_type::iterator iterator; typedef typename facade_type::const_iterator const_iterator; typedef typename facade_type::reference reference; @@ -413,6 +415,41 @@ namespace sprout { return impl_.to_last_ - sprout::size(get_internal()); } + SPROUT_CXX14_CONSTEXPR sub_array& window(difference_type to_first = 0) { + impl_.to_first_ = to_first; + impl_.to_last_ = size(); + return *this; + } + SPROUT_CXX14_CONSTEXPR sub_array& window(difference_type to_first, difference_type to_last) { + impl_.to_first_ = to_first; + impl_.to_last_ = to_last; + return *this; + } + SPROUT_CONSTEXPR sub_array window(difference_type to_first = 0) const { + return sub_array(impl_.array_, to_first, size()); + } + SPROUT_CONSTEXPR sub_array window(difference_type to_first, difference_type to_last) const { + return sub_array(impl_.array_, to_first, to_last); + } + SPROUT_CONSTEXPR sub_array cwindow(difference_type to_first = 0) const { + return window(to_first); + } + SPROUT_CONSTEXPR sub_array cwindow(difference_type to_first, difference_type to_last) const { + return window(to_first, to_last); + } + + SPROUT_CXX14_CONSTEXPR sub_array& offset(difference_type from_begin = 0, difference_type from_end = 0) { + impl_.to_first_ += from_begin; + impl_.to_last_ += from_end; + return *this; + } + SPROUT_CONSTEXPR sub_array offset(difference_type from_begin = 0, difference_type from_end = 0) const { + return sub_array(impl_.array_, impl_.to_first_ + from_begin, impl_.to_last_ + from_end); + } + SPROUT_CONSTEXPR sub_array coffset(difference_type from_begin = 0, difference_type from_end = 0) const { + return offset(from_begin, from_end); + } + SPROUT_CXX14_CONSTEXPR iterator nth(size_type i) { return i < size() ? sprout::next(begin(), i) @@ -431,6 +468,37 @@ namespace sprout { SPROUT_CONSTEXPR size_type index_of(const_iterator p) const { return sprout::distance(begin(), p); } + + SPROUT_CXX14_CONSTEXPR void push_back(value_type const& x) { + impl_.array_[impl_.to_last_] = x; + ++impl_.to_last_; + } + SPROUT_CXX14_CONSTEXPR void push_back(value_type&& x) { + impl_.array_[impl_.to_last_] = sprout::move(x); + ++impl_.to_last_; + } + SPROUT_CXX14_CONSTEXPR void pop_back() { + impl_.array_[impl_.to_last_ - 1] = value_type(); + --impl_.to_last_; + } + SPROUT_CXX14_CONSTEXPR void drop_back() { + --impl_.to_last_; + } + SPROUT_CXX14_CONSTEXPR void push_front(value_type const& x) { + impl_.array_[impl_.to_first_ - 1] = x; + --impl_.to_first_; + } + SPROUT_CXX14_CONSTEXPR void push_front(value_type&& x) { + impl_.array_[impl_.to_first_ - 1] = sprout::move(x); + --impl_.to_first_; + } + SPROUT_CXX14_CONSTEXPR void pop_front() { + impl_.array_[impl_.to_first_] = value_type(); + ++impl_.to_first_; + } + SPROUT_CXX14_CONSTEXPR void drop_front() { + ++impl_.to_first_; + } }; template SPROUT_CONSTEXPR_OR_CONST typename sprout::sub_array::size_type sprout::sub_array::enumerable_size;