diff --git a/sprout/array.hpp b/sprout/array.hpp index da310d35..b523b9ba 100644 --- a/sprout/array.hpp +++ b/sprout/array.hpp @@ -171,7 +171,7 @@ namespace sprout { // swap // template - SPROUT_CONSTEXPR inline void swap(sprout::array& lhs, sprout::array& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + inline void swap(sprout::array& lhs, sprout::array& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } @@ -290,3 +290,4 @@ namespace std { } // namespace std #endif // #ifndef SPROUT_ARRAY_HPP + diff --git a/sprout/fixed_container/size.hpp b/sprout/fixed_container/size.hpp index 24f86635..4ebbacb5 100644 --- a/sprout/fixed_container/size.hpp +++ b/sprout/fixed_container/size.hpp @@ -12,7 +12,7 @@ namespace sprout { // size // template - SPROUT_CONSTEXPR typename sprout::fixed_container_traits::difference_type size(Range const& range) { + SPROUT_CONSTEXPR inline typename sprout::fixed_container_traits::difference_type size(Range const& range) { return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::distance(sprout::begin(range), sprout::end(range)); } } // namespace sprout diff --git a/sprout/string.hpp b/sprout/string.hpp index ae218105..79427945 100644 --- a/sprout/string.hpp +++ b/sprout/string.hpp @@ -2,9 +2,10 @@ #define SPROUT_STRING_HPP #include -#include +#include #include #include +#include #include #include #include @@ -18,10 +19,77 @@ #include HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL namespace sprout { + // + // char_traits + // + template + class char_traits { + private: + typedef std::char_traits impl_type; + public: + typedef typename impl_type::char_type char_type; + typedef typename impl_type::int_type int_type; + typedef typename impl_type::off_type off_type; + typedef typename impl_type::pos_type pos_type; + typedef typename impl_type::state_type state_type; + public: + static void assign(char_type& c1, char_type const& c2) SPROUT_NOEXCEPT { + impl_type::assign(c1, c2); + } + static SPROUT_CONSTEXPR bool eq(char_type c1, char_type c2) SPROUT_NOEXCEPT { + return impl_type::eq(c1, c2); + } + static SPROUT_CONSTEXPR bool lt(char_type c1, char_type c2) SPROUT_NOEXCEPT { + return impl_type::lt(c1, c2); + } + static SPROUT_CONSTEXPR int compare(char_type const* s1, char_type const* s2, std::size_t n) { + return !n ? 0 + : lt(*s1, *s2) ? -1 + : lt(*s2, *s1) ? 1 + : compare(s1 + 1, s2 + 1, n - 1) + ; + } + static SPROUT_CONSTEXPR std::size_t length(char_type const* s) { + return !*s ? 0 + : 1 + length(s + 1) + ; + } + static SPROUT_CONSTEXPR char_type const* find(char_type const* s, std::size_t n, char_type const& a) { + return !n ? nullptr + : eq(*s, a) ? s + : find(s + 1, n - 1, a) + ; + } + static char_type* move(char_type* s1, char_type const* s2, std::size_t n) { + return impl_type::move(s1, s2, n); + } + static char_type* copy(char_type* s1, char_type const* s2, std::size_t n) { + return impl_type::copy(s1, s2, n); + } + static char_type* assign(char_type* s, std::size_t n, char_type a) { + return impl_type::assign(s, n, a); + } + static SPROUT_CONSTEXPR int_type not_eof(int_type c) SPROUT_NOEXCEPT { + return impl_type::not_eof(c); + } + static SPROUT_CONSTEXPR char_type to_char_type(int_type c) SPROUT_NOEXCEPT { + return impl_type::to_char_type(c); + } + static SPROUT_CONSTEXPR int_type to_int_type(char_type c) SPROUT_NOEXCEPT { + return impl_type::to_int_type(c); + } + static SPROUT_CONSTEXPR bool eq_int_type(int_type c1, int_type c2) SPROUT_NOEXCEPT { + return impl_type::eq_int_type(c1, c2); + } + static SPROUT_CONSTEXPR int_type eof() SPROUT_NOEXCEPT { + return impl_type::eof(); + } + }; + // // basic_string // - template + template > class basic_string { public: typedef T value_type; @@ -35,20 +103,41 @@ namespace sprout { typedef T const* const_pointer; typedef sprout::detail::reverse_iterator reverse_iterator; typedef sprout::detail::reverse_iterator const_reverse_iterator; + typedef Traits traits_type; public: + SPROUT_STATIC_CONSTEXPR size_type npos = -1; SPROUT_STATIC_CONSTEXPR size_type static_size = N; SPROUT_STATIC_CONSTEXPR size_type fixed_size = static_size; public: T elems[N + 1]; + size_type len; + private: + SPROUT_CONSTEXPR int compare_impl_2(int compared, size_type n1, size_type n2) const { + return compared != 0 ? compared + : n1 < n2 ? -1 + : n2 < n1 ? 1 + : 0 + ; + } + SPROUT_CONSTEXPR int compare_impl_1(size_type pos1, size_type n1, char const* s, size_type n2) const { + return compare_impl_2( + traits_type::compare(c_str() + pos1, s, NS_SSCRISK_CEL_OR_SPROUT_DETAIL::min(n1, n2)), + n1, + n2 + ); + } public: SPROUT_CONSTEXPR size_type size() const SPROUT_NOEXCEPT { - return N; + return len; + } + SPROUT_CONSTEXPR size_type length() const SPROUT_NOEXCEPT { + return size(); } SPROUT_CONSTEXPR bool empty() const SPROUT_NOEXCEPT { - return N == 0; + return size() == 0; } SPROUT_CONSTEXPR size_type max_size() const SPROUT_NOEXCEPT { - return size(); + return N; } void rangecheck(size_type i) const { if (i >= size()) { @@ -126,75 +215,213 @@ namespace sprout { pointer c_array() SPROUT_NOEXCEPT { return &elems[0]; } - const_pointer c_str() const SPROUT_NOEXCEPT { + SPROUT_CONSTEXPR const_pointer c_str() const SPROUT_NOEXCEPT { return &elems[0]; } - void assign(const_reference value) { - fill(value); - } void fill(const_reference value) { std::fill_n(begin(), size(), value); } - void swap(basic_string& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { + void swap(basic_string& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(std::swap(std::declval(), std::declval()))) { std::swap_ranges(other.begin(), other.end(), begin()); } - template - basic_string& operator=(basic_string const& rhs) { + template + basic_string& operator=(basic_string const& rhs) { std::copy(rhs.begin(), rhs.end(), begin()); return *this; } - template - basic_string& operator=(basic_string&& rhs) { + template + basic_string& operator=(basic_string&& rhs) { std::move(rhs.begin(), rhs.end(), begin()); return *this; } + template + SPROUT_CONSTEXPR int compare(basic_string const& str) const { + return compare(0, size(), str.c_str(), str.size()); + } + SPROUT_CONSTEXPR int compare(T const* s) const { + return compare(0, size(), s, traits_type::length(s)); + } + template + SPROUT_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string const& str) const { + return compare(pos1, n1, str, 0, npos); + } + SPROUT_CONSTEXPR int compare(size_type pos1, size_type n1, char const* s) const { + return compare(pos1, n1, s, traits_type::length(s)); + } + template + SPROUT_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string const& str, size_type pos2, size_type n2) const { + return !(str.size() < pos2) + ? compare(pos1, n1, str.c_str() + pos2, NS_SSCRISK_CEL_OR_SPROUT_DETAIL::min(n2, str.size() - pos2)) + : throw "basic_string<>: index out of range" + ; + } + SPROUT_CONSTEXPR int compare(size_type pos1, size_type n1, char const* s, size_type n2) const { + return !(size() < pos1) + ? compare_impl_1(pos1, NS_SSCRISK_CEL_OR_SPROUT_DETAIL::min(n1, size() - pos1), s, n2) + : throw "basic_string<>: index out of range" + ; + } }; - template - SPROUT_CONSTEXPR inline bool operator==(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { - return N1 == N2 && NS_SSCRISK_CEL_OR_SPROUT_DETAIL::equal(lhs.begin(), lhs.end(), rhs.begin()); + template + SPROUT_CONSTEXPR inline bool operator==(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + return lhs.compare(rhs) == 0; } - template - SPROUT_CONSTEXPR inline bool operator!=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + template + SPROUT_CONSTEXPR inline bool operator==(sprout::basic_string const& lhs, T const* rhs) { + return lhs.compare(rhs) == 0; + } + template + SPROUT_CONSTEXPR inline bool operator==(T const* lhs, sprout::basic_string const& rhs) { + return 0 == rhs.compare(lhs); + } + template + SPROUT_CONSTEXPR inline bool operator!=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { return !(lhs == rhs); } - template - SPROUT_CONSTEXPR inline bool operator<(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { - return NS_SSCRISK_CEL_OR_SPROUT_DETAIL::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + template + SPROUT_CONSTEXPR inline bool operator!=(sprout::basic_string const& lhs, T const* rhs) { + return !(lhs == rhs); } - template - SPROUT_CONSTEXPR inline bool operator>(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + template + SPROUT_CONSTEXPR inline bool operator!=(T const* lhs, sprout::basic_string const& rhs) { + return !(lhs == rhs); + } + template + SPROUT_CONSTEXPR inline bool operator<(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + return lhs.compare(rhs) < 0; + } + template + SPROUT_CONSTEXPR inline bool operator<(sprout::basic_string const& lhs, T const* rhs) { + return lhs.compare(rhs) < 0; + } + template + SPROUT_CONSTEXPR inline bool operator<(T const* lhs, sprout::basic_string const& rhs) { + return 0 < rhs.compare(lhs); + } + template + SPROUT_CONSTEXPR inline bool operator>(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { return rhs < lhs; } - template - SPROUT_CONSTEXPR inline bool operator<=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + template + SPROUT_CONSTEXPR inline bool operator>(sprout::basic_string const& lhs, T const* rhs) { + return rhs < lhs; + } + template + SPROUT_CONSTEXPR inline bool operator>(T const* lhs, sprout::basic_string const& rhs) { + return rhs < lhs; + } + template + SPROUT_CONSTEXPR inline bool operator<=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { return !(rhs < lhs); } - template - SPROUT_CONSTEXPR inline bool operator>=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + template + SPROUT_CONSTEXPR inline bool operator<=(sprout::basic_string const& lhs, T const* rhs) { + return !(rhs < lhs); + } + template + SPROUT_CONSTEXPR inline bool operator<=(T const* lhs, sprout::basic_string const& rhs) { + return !(rhs < lhs); + } + template + SPROUT_CONSTEXPR inline bool operator>=(sprout::basic_string const& lhs, sprout::basic_string const& rhs) { + return !(lhs < rhs); + } + template + SPROUT_CONSTEXPR inline bool operator>=(sprout::basic_string const& lhs, T const* rhs) { + return !(lhs < rhs); + } + template + SPROUT_CONSTEXPR inline bool operator>=(T const* lhs, sprout::basic_string const& rhs) { return !(lhs < rhs); } // // swap // - template - SPROUT_CONSTEXPR inline void swap(sprout::basic_string& lhs, sprout::basic_string& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { + template + inline void swap( + sprout::basic_string& lhs, + sprout::basic_string& rhs + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { lhs.swap(rhs); } + // + // resize + // + namespace detail { + template + SPROUT_CONSTEXPR inline typename std::enable_if< + sizeof...(Args) != N, + sprout::basic_string + >::type resize_impl( + sprout::basic_string const& str, + typename sprout::basic_string::size_type new_size, + Args const&... args + ) + { + return sprout::detail::resize_impl(str, new_size, args..., sizeof...(Args) < new_size ? str[sizeof...(Args)] : T()); + } + template + SPROUT_CONSTEXPR inline typename std::enable_if< + sizeof...(Args) == N, + sprout::basic_string + >::type resize_impl( + sprout::basic_string const& str, + typename sprout::basic_string::size_type new_size, + Args const&... args + ) + { + return sprout::basic_string{{args...}, new_size}; + } + } // namespace detail + template + SPROUT_CONSTEXPR inline sprout::basic_string resize( + sprout::basic_string const& str, + typename sprout::basic_string::size_type new_size + ) + { + return new_size <= N ? sprout::detail::resize_impl(str, new_size) + : throw "basic_string<>: index out of range" + ; + } + // // rebind_fixed_size // - template - struct rebind_fixed_size > { + template + struct rebind_fixed_size > { public: - template >::size_type S> + template >::size_type S> struct apply { public: - typedef sprout::basic_string type; + typedef sprout::basic_string type; }; }; + // + // make_clone_functor + // + template + struct make_clone_functor > { + private: + typedef typename sprout::fixed_container_traits >::clone_type clone_type; + private: + static SPROUT_CONSTEXPR typename clone_type::size_type length() { + return 0; + } + template + static SPROUT_CONSTEXPR typename clone_type::size_type length(T const& head, Tail const&... tail) { + return !head ? 0 : 1 + length(tail...); + } + public: + template + SPROUT_CONSTEXPR clone_type operator()(Args const&... args) const { + return clone_type{{args...}, length(args...)}; + } + }; + namespace detail { template struct is_basic_string_impl { @@ -208,7 +435,7 @@ namespace sprout { typename std::enable_if< std::is_same< T, - sprout::basic_string + sprout::basic_string >::value >::type > { @@ -286,13 +513,22 @@ namespace sprout { {}; namespace detail { + template + SPROUT_CONSTEXPR inline sprout::basic_string to_string_impl_1( + T const(& arr)[N], + sprout::index_tuple, + typename sprout::basic_string::size_type len + ) + { + return sprout::basic_string{{(Indexes < len ? arr[Indexes] : T())...}, len}; + } template SPROUT_CONSTEXPR inline sprout::basic_string to_string_impl( T const(& arr)[N], sprout::index_tuple ) { - return sprout::basic_string{{arr[Indexes]...}}; + return to_string_impl_1(arr, sprout::index_tuple(), sprout::char_traits::length(arr)); } } // namespace detail // @@ -303,60 +539,105 @@ namespace sprout { return sprout::detail::to_string_impl(arr, typename sprout::index_range<0, N - 1>::type()); } - template - SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::push_back, T>::type operator+( - sprout::basic_string const& lhs, + template + SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::push_back, T>::type operator+( + sprout::basic_string const& lhs, T const& rhs ) { return sprout::fixed::push_back(lhs, rhs); } - template - SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::push_front, T>::type operator+( + template + SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::push_front, T>::type operator+( T const& lhs, - sprout::basic_string const& rhs + sprout::basic_string const& rhs ) { return sprout::fixed::push_front(rhs, lhs); } - template + template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::join_back< - sprout::basic_string, - sprout::basic_string + sprout::basic_string, + sprout::basic_string >::type operator+( - sprout::basic_string const& lhs, + sprout::basic_string const& lhs, T const (& rhs)[N2] ) { return sprout::fixed::join_back(lhs, sprout::to_string(rhs)); } - template + template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::join_front< - sprout::basic_string, - sprout::basic_string + sprout::basic_string, + sprout::basic_string >::type operator+( T const (& lhs)[N2], - sprout::basic_string const& rhs + sprout::basic_string const& rhs ) { return sprout::fixed::join_front(rhs, sprout::to_string(lhs)); } - template + template SPROUT_CONSTEXPR inline typename sprout::fixed::result_of::join_back< - sprout::basic_string, - sprout::basic_string + sprout::basic_string, + sprout::basic_string >::type operator+( - sprout::basic_string const& lhs, - sprout::basic_string const& rhs + sprout::basic_string const& lhs, + sprout::basic_string const& rhs ) { return sprout::fixed::join_back(lhs, rhs); } - template - inline std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::basic_string const& rhs) { + template + inline std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::basic_string const& rhs) { return lhs << rhs.c_str(); } + template + inline std::basic_istream& operator>>(std::basic_istream& lhs, sprout::basic_string& rhs) { + typedef T elem_type; + typedef StreamTraits traits_type; + typedef std::basic_istream istream_type; + typedef sprout::basic_string string_type; + typedef std::ctype ctype_type; + typedef typename string_type::size_type size_type; + std::ios_base::iostate state = std::ios_base::goodbit; + bool changed = false; + size_type current = 0; + if (typename istream_type::sentry(lhs)) { + ctype_type const& ctype_fac = std::use_facet(lhs.getloc()); + try { + size_type remain = 0 < lhs.width() && static_cast(lhs.width()) < rhs.max_size() + ? static_cast(lhs.width()) + : rhs.max_size() + ; + typename traits_type::int_type meta = lhs.rdbuf()->sgetc(); + for (; remain; --remain, meta = lhs.rdbuf()->snextc()) + if (traits_type::eq_int_type(traits_type::eof(), meta)) { + state |= std::ios_base::eofbit; + break; + } else if (ctype_fac.is(ctype_type::space, traits_type::to_char_type(meta))) { + break; + } else { + rhs[current] = traits_type::to_char_type(meta); + changed = true; + ++current; + } + } catch (...) { + state |= std::ios_base::badbit; + } + } + lhs.width(0); + if (!changed) { + state |= std::ios_base::failbit; + } + lhs.setstate(state); + rhs.len = current; + for (; current != rhs.max_size(); ++current) { + rhs[current] = T(); + } + return lhs; + } #if 0 // @@ -419,8 +700,8 @@ namespace std { // // tuple_size // - template - struct tuple_size > { + template + struct tuple_size > { public: typedef std::integral_constant type; SPROUT_STATIC_CONSTEXPR std::size_t value = type::value; @@ -429,8 +710,8 @@ namespace std { // // tuple_element // - template - struct tuple_element > { + template + struct tuple_element > { public: static_assert(I < N, "tuple_element<>: index out of range"); typedef T type; @@ -439,20 +720,21 @@ namespace std { // // get // - template - T& get(sprout::basic_string& arr) SPROUT_NOEXCEPT { + template + T& get(sprout::basic_string& arr) SPROUT_NOEXCEPT { static_assert(I < N, "tuple_element<>: index out of range"); return arr[I]; } - template - SPROUT_CONSTEXPR T const& get(sprout::basic_string const& arr) SPROUT_NOEXCEPT { + template + SPROUT_CONSTEXPR T const& get(sprout::basic_string const& arr) SPROUT_NOEXCEPT { static_assert(I < N, "tuple_element<>: index out of range"); return arr[I]; } - template - T&& get(sprout::basic_string&& arr) SPROUT_NOEXCEPT { + template + T&& get(sprout::basic_string&& arr) SPROUT_NOEXCEPT { return std::move(get(arr)); } } // namespace std #endif // #ifndef SPROUT_STRING_HPP +