diff --git a/include/boost/fixed_string/config.hpp b/include/boost/fixed_string/config.hpp index 99a2f90..dd3ed73 100644 --- a/include/boost/fixed_string/config.hpp +++ b/include/boost/fixed_string/config.hpp @@ -12,7 +12,7 @@ #define BOOST_FIXED_STRING_CONFIG_HPP // Are we dependent on Boost? -#define BOOST_FIXED_STRING_USE_BOOST +// #define BOOST_FIXED_STRING_STANDALONE // Can we have deduction guides? #ifdef __cpp_deduction_guides @@ -30,8 +30,45 @@ #define BOOST_FIXED_STRING_NODISCARD #endif -#ifdef BOOST_FIXED_STRING_USE_BOOST +//#undef _­_­cplusplus +//#define _­_­cplusplus 201703L + +#if __cplusplus > 201703L +#define BOOST_FIXED_STRING_CPP20_CXPER constexpr +#define BOOST_FIXED_STRING_CPP17_CXPER constexpr +#define BOOST_FIXED_STRING_CPP14_CXPER constexpr +#define BOOST_FIXED_STRING_CPP11_CXPER constexpr +#define BOOST_FIXED_STRING_CPP20_CXPER_USED +#define BOOST_FIXED_STRING_CPP17_CXPER_USED +#define BOOST_FIXED_STRING_CPP14_CXPER_USED +#define BOOST_FIXED_STRING_CPP11_CXPER_USED +#define BOOST_FIXED_STRING_ALLOW_UNINIT_MEM +#elif __cplusplus >= 201703L +#define BOOST_FIXED_STRING_CPP20_CXPER +#define BOOST_FIXED_STRING_CPP17_CXPER constexpr +#define BOOST_FIXED_STRING_CPP14_CXPER constexpr +#define BOOST_FIXED_STRING_CPP11_CXPER constexpr +#define BOOST_FIXED_STRING_CPP17_CXPER_USED +#define BOOST_FIXED_STRING_CPP14_CXPER_USED +#define BOOST_FIXED_STRING_CPP11_CXPER_USED +#elif __cplusplus >= 201402L +#define BOOST_FIXED_STRING_CPP20_CXPER +#define BOOST_FIXED_STRING_CPP17_CXPER +#define BOOST_FIXED_STRING_CPP14_CXPER constexpr +#define BOOST_FIXED_STRING_CPP11_CXPER constexpr +#define BOOST_FIXED_STRING_CPP14_CXPER_USED +#define BOOST_FIXED_STRING_CPP11_CXPER_USED +#else +#define BOOST_FIXED_STRING_CPP20_CXPER +#define BOOST_FIXED_STRING_CPP17_CXPER +#define BOOST_FIXED_STRING_CPP14_CXPER +#define BOOST_FIXED_STRING_CPP11_CXPER constexpr +#define BOOST_FIXED_STRING_CPP11_CXPER_USED +#endif + +#ifndef BOOST_FIXED_STRING_STANDALONE #include +#include #include #include #include @@ -41,7 +78,7 @@ #endif // Boost and non-Boost versions of utilities -#ifdef BOOST_FIXED_STRING_USE_BOOST +#ifndef BOOST_FIXED_STRING_STANDALONE #ifndef BOOST_FIXED_STRING_THROW #define BOOST_FIXED_STRING_THROW(ex) BOOST_THROW_EXCEPTION(ex) #endif @@ -66,18 +103,10 @@ namespace boost { namespace fixed_string { -/// The type of `string_view` used by the library -using string_view = -#ifdef BOOST_FIXED_STRING_USE_BOOST - boost::string_view; -#else - std::string_view; -#endif - /// The type of `basic_string_view` used by the library template using basic_string_view = -#ifdef BOOST_FIXED_STRING_USE_BOOST +#ifndef BOOST_FIXED_STRING_STANDALONE boost::basic_string_view; #else std::basic_string_view; diff --git a/include/boost/fixed_string/detail/fixed_string.hpp b/include/boost/fixed_string/detail/fixed_string.hpp index 39e9027..323086f 100644 --- a/include/boost/fixed_string/detail/fixed_string.hpp +++ b/include/boost/fixed_string/detail/fixed_string.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace boost { namespace fixed_string { @@ -22,12 +23,186 @@ namespace detail { template class fixed_string; -// Because k-ballo said so +// At minimum an integral type shall not qualify as an iterator (Agustin Berge) template using is_input_iterator = std::integral_constant::value>; +// Find the smallest width integral type that can hold a value as large as N (Glen Fernandes) +template +using smallest_width = + typename std::conditional<(N <= (std::numeric_limits::max)()), unsigned char, + typename std::conditional<(N <= (std::numeric_limits::max)()), unsigned short, + typename std::conditional<(N <= (std::numeric_limits::max)()), unsigned int, + typename std::conditional<(N <= (std::numeric_limits::max)()), unsigned long, + typename std::conditional<(N <= (std::numeric_limits::max)()), unsigned long long, + void>::type>::type>::type>::type>::type; + +// Optimization for using the smallest possible type +template +class fixed_string_base_zero +{ +public: + BOOST_FIXED_STRING_CPP11_CXPER + fixed_string_base_zero() noexcept { }; + + BOOST_FIXED_STRING_CPP11_CXPER + fixed_string_base_zero(std::size_t n) noexcept : size_(n) { } + + BOOST_FIXED_STRING_CPP14_CXPER + CharT* + data_impl() noexcept + { + return data_; + } + + BOOST_FIXED_STRING_CPP14_CXPER + CharT const* + data_impl() const noexcept + { + return data_; + } + + BOOST_FIXED_STRING_CPP11_CXPER + std::size_t + size_impl() const noexcept + { + return size_; + } + + BOOST_FIXED_STRING_CPP14_CXPER + std::size_t + set_size(std::size_t n) noexcept + { + return size_ = n; + } + + BOOST_FIXED_STRING_CPP14_CXPER + void + term_impl() noexcept + { + Traits::assign(data_[size_], 0); + } + + smallest_width size_{0}; +#ifdef BOOST_FIXED_STRING_ALLOW_UNINIT_MEM + CharT data_[N + 1]; +#else + CharT data_[N + 1]{}; +#endif +}; + +// Optimization for when the size is 0 +template +class fixed_string_base_zero<0, CharT, Traits> +{ +public: + BOOST_FIXED_STRING_CPP11_CXPER + fixed_string_base_zero() noexcept { } + + BOOST_FIXED_STRING_CPP11_CXPER + fixed_string_base_zero(std::size_t) noexcept { } + + // not possible to constexpr with the static there + CharT* + data_impl() const noexcept + { + static CharT null{}; + return &null; + } + + BOOST_FIXED_STRING_CPP11_CXPER + std::size_t + size_impl() const noexcept + { + return 0; + } + + BOOST_FIXED_STRING_CPP11_CXPER + std::size_t + set_size(std::size_t) noexcept + { + return 0; + } + + BOOST_FIXED_STRING_CPP14_CXPER + void + term_impl() noexcept + { + + } +}; + +// Optimization for storing the size in the last element +template +class fixed_string_base_null +{ +public: + BOOST_FIXED_STRING_CPP14_CXPER + fixed_string_base_null() noexcept { set_size(0); } + + BOOST_FIXED_STRING_CPP14_CXPER + fixed_string_base_null(std::size_t n) noexcept { set_size(n); } + + BOOST_FIXED_STRING_CPP14_CXPER + CharT* + data_impl() noexcept + { + return data_; + } + + BOOST_FIXED_STRING_CPP14_CXPER + CharT const* + data_impl() const noexcept + { + return data_; + } + + BOOST_FIXED_STRING_CPP11_CXPER + std::size_t + size_impl() const noexcept + { + return N - data_[N]; + } + + BOOST_FIXED_STRING_CPP14_CXPER + std::size_t + set_size(std::size_t n) noexcept + { + return data_[N] = (N - n); + } + + BOOST_FIXED_STRING_CPP14_CXPER + void + term_impl() noexcept + { + Traits::assign(data_[size_impl()], 0); + } + +#ifdef BOOST_FIXED_STRING_ALLOW_UNINIT_MEM + CharT data_[N + 1]; +#else + CharT data_[N + 1]{}; +#endif +}; + +//#define BOOST_FIXED_STRING_NO_NULL_OPTIMIZATION + +// Decides which size optimization to use +// If the size is zero, the object will have no members +// Otherwise, if CharT can hold the max size of the string, store the size in the last char +// Otherwise, store the size of the string using a member of the smallest type possible +template +using optimization_base = +#ifndef BOOST_FIXED_STRING_NO_NULL_OPTIMIZATION + typename std::conditional<(N <= (std::numeric_limits::max)()) && (N != 0), + fixed_string_base_null, + fixed_string_base_zero>::type; +#else + fixed_string_base_zero; +#endif + template inline int diff --git a/include/boost/fixed_string/fixed_string.hpp b/include/boost/fixed_string/fixed_string.hpp index fb3404c..2576cca 100644 --- a/include/boost/fixed_string/fixed_string.hpp +++ b/include/boost/fixed_string/fixed_string.hpp @@ -37,19 +37,22 @@ template< std::size_t N, typename CharT = char, typename Traits = std::char_traits> -class fixed_string +class fixed_string +#ifndef GENERATING_DOCUMENTATION + : detail::optimization_base +#endif { template friend class fixed_string; + BOOST_FIXED_STRING_CPP14_CXPER void - term() + term() noexcept { - Traits::assign(s_[n_], 0); + this->term_impl(); } - std::size_t n_; - CharT s_[N + 1]; + using base = detail::optimization_base; public: //-------------------------------------------------------------------------- @@ -86,7 +89,7 @@ public: //-------------------------------------------------------------------------- /// Maximum size of the string excluding any null terminator - static std::size_t constexpr static_capacity = N; + static constexpr size_type static_capacity = N; /// A special index static constexpr size_type npos = size_type(-1); @@ -101,7 +104,8 @@ public: Construct an empty string */ - fixed_string(); + BOOST_FIXED_STRING_CPP11_CXPER + fixed_string() noexcept; /** Construct a `fixed_string`. @@ -109,6 +113,7 @@ public: The behavior is undefined if `count >= npos` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( size_type count, CharT ch); @@ -118,6 +123,7 @@ public: Construct with a substring (pos, other.size()) of `other`. */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( fixed_string const& other, size_type pos); @@ -127,6 +133,7 @@ public: Construct with a substring (pos, count) of `other`. */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( fixed_string const& other, size_type pos, @@ -136,6 +143,7 @@ public: Construct with the first `count` characters of `s`, including nulls. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( CharT const* s, size_type count); @@ -144,6 +152,7 @@ public: Construct from a null terminated string. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( CharT const* s); @@ -152,6 +161,7 @@ public: Construct from a range of characters */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( InputIterator first, InputIterator last @@ -166,14 +176,16 @@ public: Copy constructor. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( - fixed_string const& other); + fixed_string const& other) noexcept; /** Construct a `fixed_string`. Copy constructor. */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( fixed_string const& other); @@ -181,6 +193,7 @@ public: Construct from an initializer list */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( std::initializer_list init); @@ -189,6 +202,7 @@ public: Construct from a `string_view` */ explicit + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( string_view_type sv); @@ -206,6 +220,7 @@ public: std::is_convertible::value>::type #endif > + BOOST_FIXED_STRING_CPP14_CXPER fixed_string( T const& t, size_type pos, @@ -222,6 +237,7 @@ public: If `*this` and `s` are the same object, this function has no effect. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( fixed_string const& s) noexcept @@ -236,6 +252,7 @@ public: @throw std::length_error if `s.size() > max_size()` */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( fixed_string const& s) @@ -249,6 +266,7 @@ public: @throw std::length_error if `Traits::length(s) > max_size()` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( CharT const* s) @@ -260,6 +278,7 @@ public: Assign from single character. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( CharT ch) @@ -272,6 +291,7 @@ public: Assign from initializer list. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( std::initializer_list ilist) @@ -283,6 +303,7 @@ public: Assign from `string_view_type`. */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator=( string_view_type sv) @@ -297,6 +318,7 @@ public: @throw std::length_error if `count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( size_type count, @@ -308,6 +330,7 @@ public: @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( fixed_string const& s) noexcept; @@ -320,6 +343,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( fixed_string const& s) @@ -338,6 +362,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( fixed_string const& s, @@ -351,6 +376,7 @@ public: @throw std::length_error if `count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( CharT const* s, @@ -363,6 +389,7 @@ public: @throw std::length_error if `Traits::length(s) > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& assign( CharT const* s) @@ -378,6 +405,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #ifdef GENERATING_DOCUMENTATION fixed_string& #else @@ -410,6 +438,7 @@ public: @throw std::length_error if `string_view_type{t}.size() > max_size()` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -437,6 +466,7 @@ public: */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -463,6 +493,7 @@ public: @throw std::out_of_range if `pos >= size()` */ + BOOST_FIXED_STRING_CPP14_CXPER reference at(size_type pos); @@ -470,6 +501,7 @@ public: @throw std::out_of_range if `pos >= size()` */ + BOOST_FIXED_STRING_CPP14_CXPER const_reference at(size_type pos) const; @@ -477,77 +509,86 @@ public: Undefined behavior if `pos > size()` */ + BOOST_FIXED_STRING_CPP14_CXPER reference - operator[](size_type pos) + operator[](size_type pos) noexcept { - return s_[pos]; + return data()[pos]; } /** Access specified character. Undefined behavior if `pos > size()` */ + BOOST_FIXED_STRING_CPP14_CXPER const_reference - operator[](size_type pos) const + operator[](size_type pos) const noexcept { - return s_[pos]; + return data()[pos]; } /** Accesses the first character. Undefined behavior if `empty() == true` */ + BOOST_FIXED_STRING_CPP14_CXPER CharT& - front() + front() noexcept { - return s_[0]; + return data()[0]; } /** Accesses the first character. Undefined behavior if `empty() == true` */ + BOOST_FIXED_STRING_CPP14_CXPER CharT const& - front() const + front() const noexcept { - return s_[0]; + return data()[0]; } /** Accesses the last character. Undefined behavior if `empty() == true` */ + BOOST_FIXED_STRING_CPP14_CXPER CharT& - back() + back() noexcept { - return s_[n_-1]; + return data()[size()-1]; } /** Accesses the last character. Undefined behavior if `empty() == true` */ + BOOST_FIXED_STRING_CPP14_CXPER CharT const& - back() const + back() const noexcept { - return s_[n_-1]; + return data()[size()-1]; } /// Returns a pointer to the first character of the string. + BOOST_FIXED_STRING_CPP14_CXPER CharT* data() noexcept { - return s_; + return this->data_impl(); } /// Returns a pointer to the first character of a string. + BOOST_FIXED_STRING_CPP14_CXPER CharT const* data() const noexcept { - return s_; + return this->data_impl(); } /// Returns a non-modifiable standard C character array version of the string. + BOOST_FIXED_STRING_CPP14_CXPER CharT const* c_str() const noexcept { @@ -555,10 +596,10 @@ public: } /// Convert a static string to a `string_view_type` + BOOST_FIXED_STRING_CPP11_CXPER operator string_view_type() const noexcept { - return basic_string_view< - CharT, Traits>{data(), size()}; + return string_view_type{data(), size()}; } //-------------------------------------------------------------------------- @@ -568,45 +609,51 @@ public: //-------------------------------------------------------------------------- /// Returns an iterator to the beginning. + BOOST_FIXED_STRING_CPP14_CXPER iterator begin() noexcept { - return s_; + return data(); } /// Returns an iterator to the beginning. + BOOST_FIXED_STRING_CPP14_CXPER const_iterator begin() const noexcept { - return s_; + return data(); } /// Returns an iterator to the beginning. + BOOST_FIXED_STRING_CPP14_CXPER const_iterator cbegin() const noexcept { - return s_; + return data(); } /// Returns an iterator to the end. + BOOST_FIXED_STRING_CPP14_CXPER iterator end() noexcept { - return &s_[n_]; + return &data()[size()]; } /// Returns an iterator to the end. + BOOST_FIXED_STRING_CPP14_CXPER const_iterator end() const noexcept { - return &s_[n_]; + return &data()[size()]; } /// Returns an iterator to the end. + BOOST_FIXED_STRING_CPP14_CXPER const_iterator cend() const noexcept { - return &s_[n_]; + return &data()[size()]; } /// Returns a reverse iterator to the beginning. @@ -659,32 +706,36 @@ public: /// Returns `true` if the string is empty. BOOST_FIXED_STRING_NODISCARD + BOOST_FIXED_STRING_CPP11_CXPER bool - empty() const + empty() const noexcept { - return n_ == 0; + return size() == 0; } /// Returns the number of characters, excluding the null terminator. + BOOST_FIXED_STRING_CPP11_CXPER size_type - size() const + size() const noexcept { - return n_; + return this->size_impl(); } /** Returns the number of characters, excluding the null terminator Equivalent to calling `size()`. */ + BOOST_FIXED_STRING_CPP11_CXPER size_type - length() const + length() const noexcept { return size(); } /// Returns the maximum number of characters that can be stored, excluding the null terminator. - size_type constexpr - max_size() const + BOOST_FIXED_STRING_CPP11_CXPER + size_type + max_size() const noexcept { return N; } @@ -695,6 +746,7 @@ public: @throw std::length_error if `n > max_size()` */ + BOOST_FIXED_STRING_CPP14_CXPER void reserve(std::size_t n); @@ -702,8 +754,9 @@ public: This function always returns `max_size()`. */ - size_type constexpr - capacity() const + BOOST_FIXED_STRING_CPP11_CXPER + size_type + capacity() const noexcept { return max_size(); } @@ -712,6 +765,7 @@ public: This function call has no effect. */ + BOOST_FIXED_STRING_CPP14_CXPER void shrink_to_fit() noexcept { @@ -724,8 +778,9 @@ public: //-------------------------------------------------------------------------- /// Clears the contents + BOOST_FIXED_STRING_CPP14_CXPER void - clear(); + clear() noexcept; /** Insert into the string. @@ -735,6 +790,7 @@ public: @throw std::length_error if `size() + count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& insert( size_type index, @@ -749,6 +805,7 @@ public: @throw std::length_error if `size() + count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& insert( size_type index, @@ -767,6 +824,7 @@ public: @throw std::length_error if ` size() + count> max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& insert( size_type index, @@ -783,6 +841,7 @@ public: @throw std::length_error if `size() + sv.size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& insert( size_type index, @@ -801,6 +860,7 @@ public: @throw std::length_error if `size() + sv.substr(index_str, count).size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& insert( size_type index, @@ -820,6 +880,7 @@ public: @throw std::length_error if `size() + 1> max_size()` @return An iterator to the first inserted character or pos if no insertion took place */ + BOOST_FIXED_STRING_CPP14_CXPER iterator insert( const_iterator pos, @@ -837,6 +898,7 @@ public: @throw std::length_error if `size() + count > max_size()` @return An iterator to the first inserted character or pos if no insertion took place */ + BOOST_FIXED_STRING_CPP14_CXPER iterator insert( const_iterator pos, @@ -855,6 +917,7 @@ public: @return An iterator to the first inserted character or pos if no insertion took place */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION iterator #else @@ -876,6 +939,7 @@ public: @throw std::length_error if `size() + ilist.size() > max_size()` @return An iterator to the first inserted character or pos if no insertion took place */ + BOOST_FIXED_STRING_CPP14_CXPER iterator insert( const_iterator pos, @@ -897,6 +961,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -925,6 +990,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -944,6 +1010,7 @@ public: @throw std::out_of_range if `index > size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& erase( size_type index = 0, @@ -953,6 +1020,7 @@ public: @return iterator pointing to the character immediately following the character erased, or `end()` if no such character exists */ + BOOST_FIXED_STRING_CPP14_CXPER iterator erase( const_iterator pos); @@ -961,6 +1029,7 @@ public: @return iterator pointing to the character last pointed to before the erase, or `end()` if no such character exists */ + BOOST_FIXED_STRING_CPP14_CXPER iterator erase( const_iterator first, @@ -970,6 +1039,7 @@ public: @throw std::length_error if `size() + 1 > max_size()` */ + BOOST_FIXED_STRING_CPP14_CXPER void push_back( CharT ch); @@ -978,11 +1048,13 @@ public: The behavior is undefined if the string is empty. */ + BOOST_FIXED_STRING_CPP14_CXPER void - pop_back() + pop_back() noexcept { - BOOST_FIXED_STRING_ASSERT(n_ > 0); - Traits::assign(s_[--n_], 0); + BOOST_FIXED_STRING_ASSERT(size() > 0); + this->set_size(size() - 1); + term(); } /** Appends `count` copies of character `ch` @@ -992,12 +1064,13 @@ public: @throw std::length_error if `size() + count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( size_type count, CharT ch) { - return insert(n_, count, ch); + return insert(size(), count, ch); } /** Append to the string. @@ -1009,6 +1082,7 @@ public: @throw std::length_error if `size() + sv.size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( string_view_type sv) @@ -1026,6 +1100,7 @@ public: @throw std::length_error if `size() + sv.substr(pos, count).size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( string_view_type sv, @@ -1044,6 +1119,7 @@ public: @throw std::length_error if `size() + count > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( CharT const* s, @@ -1059,6 +1135,7 @@ public: @throw std::length_error if `size() + Traits::length(s) > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( CharT const* s) @@ -1078,6 +1155,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1102,6 +1180,7 @@ public: @throw std::length_error if `size() + ilist.size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& append( std::initializer_list ilist) @@ -1123,6 +1202,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1153,6 +1233,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1176,6 +1257,7 @@ public: @throw std::length_error if `size() + s.size() > max_size()` */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator+=( fixed_string const& s) @@ -1189,6 +1271,7 @@ public: @throw std::length_error if `size() + 1 > max_size()` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator+=( CharT ch) @@ -1207,6 +1290,7 @@ public: @throw std::length_error if `size() + Traits::length(s) > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator+=( CharT const* s) @@ -1223,6 +1307,7 @@ public: @throw std::length_error if `size() + ilist.size() > max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& operator+=( std::initializer_list ilist) @@ -1242,6 +1327,7 @@ public: @throw std::length_error if `string_view_type{t}.size() > max_size()` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1261,12 +1347,13 @@ public: Compares this string to `s`. */ template + BOOST_FIXED_STRING_CPP14_CXPER int compare( - fixed_string const& s) const + fixed_string const& s) const noexcept { return detail::lexicographical_compare( - s_, n_, &s.s_[0], s.n_); + data(), size(), s.data(), s.size()); } /** Compare the string with another. @@ -1274,6 +1361,7 @@ public: Compares a `[pos1, pos1+count1)` substring of this string to `s`. If `count1 > size() - pos1` the substring is `[pos1, size())`. */ template + BOOST_FIXED_STRING_CPP14_CXPER int compare( size_type pos1, @@ -1281,7 +1369,7 @@ public: fixed_string const& s) const { return detail::lexicographical_compare( - substr(pos1, count1), s.data(), s.size()); + subview(pos1, count1), s.data(), s.size()); } /** Compare the string with another. @@ -1291,6 +1379,7 @@ public: second substring is `[pos2, s.size())`. */ template + BOOST_FIXED_STRING_CPP14_CXPER int compare( size_type pos1, @@ -1300,19 +1389,20 @@ public: size_type count2 = npos) const { return detail::lexicographical_compare( - substr(pos1, count1), s.substr(pos2, count2)); + subview(pos1, count1), s.subview(pos2, count2)); } /** Compare the string with another. Compares this string to the null-terminated character sequence beginning at the character pointed to by `s` with length `Traits::length(s)`. */ + BOOST_FIXED_STRING_CPP14_CXPER int compare( - CharT const* s) const + CharT const* s) const noexcept { return detail::lexicographical_compare( - s_, n_, s, Traits::length(s)); + data(), size(), s, Traits::length(s)); } /** Compare the string with another. @@ -1320,6 +1410,7 @@ public: Compares a `[pos1, pos1+count1)` substring of this string to the null-terminated character sequence beginning at the character pointed to by `s` with length `Traits::length(s)`. If `count1 > size() - pos1` the substring is `[pos1, size())`. */ + BOOST_FIXED_STRING_CPP14_CXPER int compare( size_type pos1, @@ -1327,13 +1418,14 @@ public: CharT const* s) const { return detail::lexicographical_compare( - substr(pos1, count1), s, Traits::length(s)); + subview(pos1, count1), s, Traits::length(s)); } /** Compare the string with another. Compares a `[pos1, pos1+count1)` substring of this string to the characters in the range `[s, s + count2)`. If `count1 > size() - pos1` the substring is `[pos1, size())`. */ + BOOST_FIXED_STRING_CPP14_CXPER int compare( size_type pos1, @@ -1342,25 +1434,27 @@ public: size_type count2) const { return detail::lexicographical_compare( - substr(pos1, count1), s, count2); + subview(pos1, count1), s, count2); } /** Compare the string with another. Compares this string to `s`. */ + BOOST_FIXED_STRING_CPP14_CXPER int compare( - string_view_type s) const + string_view_type s) const noexcept { return detail::lexicographical_compare( - s_, n_, s.data(), s.size()); + data(), size(), s.data(), s.size()); } /** Compare the string with another. Compares a `[pos1, pos1+count1)` substring of this string to `s`. If `count1 > size() - pos1` the substring is `[pos1, size())`. */ + BOOST_FIXED_STRING_CPP14_CXPER int compare( size_type pos1, @@ -1368,7 +1462,7 @@ public: string_view_type s) const { return detail::lexicographical_compare( - substr(pos1, count1), s); + subview(pos1, count1), s); } /** Compare the string with another. @@ -1380,6 +1474,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION int #else @@ -1405,26 +1500,41 @@ public: @throw std::out_of_range if `pos > size()` */ - string_view_type + BOOST_FIXED_STRING_CPP14_CXPER + fixed_string substr( size_type pos = 0, size_type count = npos) const; + /** Returns a view of a substring. + + Returns a view of a substring `(pos, pos + count)`. If the requested view is greater than the size of the string, the returned view is `[pos, size())`. + + @throw std::out_of_range if `pos > size()` + */ + BOOST_FIXED_STRING_CPP14_CXPER + string_view_type + subview( + size_type pos = 0, + size_type count = npos) const; + /** Copy a substring. Copy a substring `(pos, pos+count)` to character string pointed to by `dest`. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type copy( CharT* dest, size_type count, - size_type pos = 0) const; + size_type pos = 0) const noexcept; /** Changes the number of characters stored. If the resulting string is larger, the new characters are uninitialized. */ + BOOST_FIXED_STRING_CPP14_CXPER void resize( std::size_t n); @@ -1434,18 +1544,21 @@ public: If the resulting string is larger, the new characters are initialized to the value of `c`. */ + BOOST_FIXED_STRING_CPP14_CXPER void resize( std::size_t n, CharT c); /// Exchange the contents of this string with another. + BOOST_FIXED_STRING_CPP14_CXPER void swap( - fixed_string& s); + fixed_string& s) noexcept; /// Exchange the contents of this string with another. template + BOOST_FIXED_STRING_CPP14_CXPER void swap( fixed_string& s); @@ -1459,6 +1572,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( size_type pos1, @@ -1477,6 +1591,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( size_type pos1, @@ -1485,7 +1600,7 @@ public: size_type pos2, size_type n2 = npos) { - return replace(pos1, n1, str.substr(pos2, n2)); + return replace(pos1, n1, str.subview(pos2, n2)); } /** Replace a subset of the string. @@ -1501,6 +1616,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1532,6 +1648,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1559,6 +1676,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( size_type pos, @@ -1575,6 +1693,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( size_type pos, @@ -1592,6 +1711,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( size_type pos, @@ -1607,6 +1727,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( const_iterator i1, @@ -1629,6 +1750,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1654,6 +1776,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( const_iterator i1, @@ -1672,6 +1795,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( const_iterator i1, @@ -1689,6 +1813,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( const_iterator i1, @@ -1708,6 +1833,7 @@ public: @return `*this` */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION fixed_string& #else @@ -1732,6 +1858,7 @@ public: @throw std::length_error if the resulting string exceeds `max_size()` @return `*this` */ + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& replace( const_iterator i1, @@ -1756,6 +1883,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -1766,7 +1894,7 @@ public: #endif find( const T& t, - size_type pos = 0) const + size_type pos = 0) const { string_view_type sv = t; return find(sv.data(), pos, sv.size()); @@ -1777,6 +1905,7 @@ public: Finds the first substring equal to `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type find( const fixed_string& str, @@ -1789,11 +1918,12 @@ public: Finds the first substring equal to the range `(s, s + count)`. This range may contain null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the first substring. @@ -1803,15 +1933,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find( const CharT* s, - size_type pos = 0) const + size_type pos = 0) const noexcept { return find(s, pos, Traits::length(s)); } /// Finds the first character `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type find( CharT c, @@ -1830,6 +1962,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -1851,6 +1984,7 @@ public: Finds the last substring equal to `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type rfind( const fixed_string& str, @@ -1863,11 +1997,12 @@ public: Finds the last substring equal to the range `(s, s + count)`. This range may contain null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type rfind( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the last substring. @@ -1877,15 +2012,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type rfind( const CharT* s, - size_type pos = npos) const + size_type pos = npos) const noexcept { return rfind(s, pos, Traits::length(s)); } /// Finds the last character `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type rfind( CharT c, @@ -1903,6 +2040,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -1924,6 +2062,7 @@ public: Finds the first character equal to one of the characters in `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_of( const fixed_string& str, @@ -1936,11 +2075,12 @@ public: Finds the first character equal to one of the characters in the range `(s, s + count)`. This range can include null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_of( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the first character equal to any character in the string. @@ -1950,15 +2090,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_of( const CharT* s, - size_type pos = 0) const + size_type pos = 0) const noexcept { return find_first_of(s, pos, Traits::length(s)); } /// Finds the first character equal to `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_of( CharT c, @@ -1976,6 +2118,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -1997,6 +2140,7 @@ public: Finds the last character equal to one of the characters in `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_of( const fixed_string& str, @@ -2009,11 +2153,12 @@ public: Finds the last character equal to one of the characters in the range `(s, s + count)`. This range can include null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_of( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the last character equal to any character in the string. @@ -2023,15 +2168,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_of( const CharT* s, - size_type pos = npos) const + size_type pos = npos) const noexcept { return find_last_of(s, pos, Traits::length(s)); } /// Finds the last character equal to `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_of( CharT c, @@ -2049,6 +2196,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -2070,6 +2218,7 @@ public: Finds the first character equal to none of the characters in `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_not_of( const fixed_string& str, @@ -2082,11 +2231,12 @@ public: Finds the first character equal to none of characters in range `(s, s + count)`. This range can include null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_not_of( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the first character equal to none the characters in the string. @@ -2096,15 +2246,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_not_of( const CharT* s, - size_type pos = 0) const + size_type pos = 0) const noexcept { return find_first_not_of(s, pos, Traits::length(s)); } /// Finds the first character not equal to `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type find_first_not_of( CharT c, @@ -2122,6 +2274,7 @@ public: convertible to `CharT const*`. */ template + BOOST_FIXED_STRING_CPP14_CXPER #if GENERATING_DOCUMENTATION size_type #else @@ -2143,6 +2296,7 @@ public: Finds the last character equal to none of the characters in `str`. */ template + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_not_of( const fixed_string& str, @@ -2155,11 +2309,12 @@ public: Finds the last character equal to none of the characters in range `(s, s + count)`. This range can include null characters. */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_not_of( const CharT* s, size_type pos, - size_type n) const; + size_type n) const noexcept; /** Finds the last character equal to none the characters in the string. @@ -2170,15 +2325,17 @@ public: The length of the string is determined by the first null character using `Traits::length(s)` */ + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_not_of( const CharT* s, - size_type pos = npos) const + size_type pos = npos) const noexcept { return find_last_not_of(s, pos, Traits::length(s)); } /// Finds the last character not equal to `c`. + BOOST_FIXED_STRING_CPP14_CXPER size_type find_last_not_of( CharT c, @@ -2188,15 +2345,17 @@ public: } /// Returns whether the string begins with `s` + BOOST_FIXED_STRING_CPP14_CXPER bool starts_with( string_view_type s) const noexcept { const size_type len = s.size(); - return n_ >= len && !Traits::compare(s_, s.data(), len); + return size() >= len && !Traits::compare(data(), s.data(), len); } /// Returns whether the string begins with `c` + BOOST_FIXED_STRING_CPP14_CXPER bool starts_with( CharT c) const noexcept @@ -2205,24 +2364,27 @@ public: } /// Returns whether the string begins with `s` + BOOST_FIXED_STRING_CPP14_CXPER bool starts_with( const CharT* s) const noexcept { const size_type len = Traits::length(s); - return n_ >= len && !Traits::compare(s_, s, len); + return size() >= len && !Traits::compare(data(), s, len); } /// Returns whether the string ends with `s` + BOOST_FIXED_STRING_CPP14_CXPER bool ends_with( string_view_type s) const noexcept { const size_type len = s.size(); - return n_ >= len && !Traits::compare(s_ + (n_ - len), s.data(), len); + return size() >= len && !Traits::compare(data() + (size() - len), s.data(), len); } /// Returns whether the string ends with `c` + BOOST_FIXED_STRING_CPP14_CXPER bool ends_with( CharT c) const noexcept @@ -2231,17 +2393,19 @@ public: } /// Returns whether the string begins with `s` + BOOST_FIXED_STRING_CPP14_CXPER bool ends_with( const CharT* s) const noexcept { const size_type len = Traits::length(s); - return n_ >= len && !Traits::compare(s_ + (n_ - len), s, len); + return size() >= len && !Traits::compare(data() + (size() - len), s, len); } private: + BOOST_FIXED_STRING_CPP14_CXPER fixed_string& - assign_char(CharT ch, std::true_type); + assign_char(CharT ch, std::true_type) noexcept; fixed_string& assign_char(CharT ch, std::false_type); @@ -2558,7 +2722,7 @@ std::basic_ostream& operator<<(std::basic_ostream& os, fixed_string const& s) { - return os << string_view(s.data(), s.size()); + return os << string_view(s.data(), s.size()); } //------------------------------------------------------------------------------ @@ -2599,9 +2763,47 @@ fixed_string(CharT(&)[N]) -> fixed_string>; #endif +//------------------------------------------------------------------------------ +// +// Hashing +// +//------------------------------------------------------------------------------ + +#ifndef BOOST_FIXED_STRING_STANDALONE +// hash_value overload for Boost.Container_Hash +template +std::size_t +hash_value( + const fixed_string& str) +{ + return boost::hash_range(str.begin(), str.end()); +} +#endif + } // fixed_string } // boost -#include - +// std::hash partial specialization for fixed_string +namespace std +{ + template + struct hash> + { + std::size_t + operator()( + const boost::fixed_string::fixed_string& str) const + { +#ifndef BOOST_FIXED_STRING_STANDALONE + return boost::hash_range(str.begin(), str.end()); +#else + using sv = boost::fixed_string::basic_string_view; + return std::hash()(sv(str.data(), str.size())); +#endif + } + }; +} // std + +#include #endif diff --git a/include/boost/fixed_string/impl/fixed_string.hpp b/include/boost/fixed_string/impl/fixed_string.hpp index f8a9408..8ede83e 100644 --- a/include/boost/fixed_string/impl/fixed_string.hpp +++ b/include/boost/fixed_string/impl/fixed_string.hpp @@ -24,14 +24,17 @@ namespace fixed_string { //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP11_CXPER fixed_string:: -fixed_string() +fixed_string() noexcept { - n_ = 0; +#ifdef BOOST_FIXED_STRING_CPP20_CXPER_USED term(); +#endif } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(size_type count, CharT ch) { @@ -40,6 +43,7 @@ fixed_string(size_type count, CharT ch) template template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(fixed_string const& other, size_type pos) @@ -49,6 +53,7 @@ fixed_string(fixed_string const& other, template template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string( fixed_string const& other, @@ -59,6 +64,7 @@ fixed_string( } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(CharT const* s, size_type count) { @@ -66,6 +72,7 @@ fixed_string(CharT const* s, size_type count) } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(CharT const* s) { @@ -73,12 +80,13 @@ fixed_string(CharT const* s) if(count > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "count > max_size()"}); - n_ = count; - Traits::copy(s_, s, n_ + 1); + this->set_size(count); + Traits::copy(data(), s, size() + 1); } template template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string( InputIterator first, @@ -91,15 +99,17 @@ fixed_string( } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string( - fixed_string const& s) + fixed_string const& s) noexcept { assign(s); } template template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string( fixed_string const& s) @@ -108,6 +118,7 @@ fixed_string( } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(std::initializer_list init) { @@ -115,6 +126,7 @@ fixed_string(std::initializer_list init) } template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(string_view_type sv) { @@ -123,6 +135,7 @@ fixed_string(string_view_type sv) template template +BOOST_FIXED_STRING_CPP14_CXPER fixed_string:: fixed_string(T const& t, size_type pos, size_type n) { @@ -136,6 +149,7 @@ fixed_string(T const& t, size_type pos, size_type n) //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: assign( @@ -146,13 +160,14 @@ assign( if(count > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "count > max_size()"}); - n_ = count; - Traits::assign(s_, n_, ch); + this->set_size(count); + Traits::assign(data(), size(), ch); term(); return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: assign( @@ -161,16 +176,17 @@ assign( { if(this == &s) return *this; - n_ = s.n_; - auto const n = n_ + 1; + this->set_size(s.size()); + auto const n = size() + 1; // VFALCO This informs the static analyzer //BOOST_BEAST_ASSUME(n != 0); - Traits::copy(s_, &s.s_[0], n); + Traits::copy(data(), &s.data()[0], n); return *this; } template template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: assign( @@ -179,11 +195,12 @@ assign( size_type count) -> fixed_string& { - auto const ss = s.substr(pos, count); + auto const ss = s.subview(pos, count); return assign(ss.data(), ss.size()); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: assign( @@ -194,18 +211,15 @@ assign( if(count > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "count > max_size()"}); - n_ = count; - // check for overlap, then move if needed - if (s <= &s_[size()] && s >= s_) - Traits::move(s_, s, n_); - else - Traits::copy(s_, s, n_); + this->set_size(count); + Traits::move(data(), s, size()); term(); return *this; } template template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: assign( @@ -219,8 +233,8 @@ assign( if(n > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "n > max_size()"}); - n_ = n; - for(auto it = s_; first != last; ++it, ++first) + this->set_size(n); + for(auto it = data(); first != last; ++it, ++first) Traits::assign(*it, *first); term(); return *this; @@ -233,6 +247,7 @@ assign( //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: at(size_type pos) -> @@ -241,10 +256,11 @@ at(size_type pos) -> if(pos >= size()) BOOST_FIXED_STRING_THROW(std::out_of_range{ "pos >= size()"}); - return s_[pos]; + return data()[pos]; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: at(size_type pos) const -> @@ -253,7 +269,7 @@ at(size_type pos) const -> if(pos >= size()) BOOST_FIXED_STRING_THROW(std::out_of_range{ "pos >= size()"}); - return s_[pos]; + return data()[pos]; } //------------------------------------------------------------------------------ @@ -263,6 +279,7 @@ at(size_type pos) const -> //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: reserve(std::size_t n) @@ -279,17 +296,19 @@ reserve(std::size_t n) //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: -clear() +clear() noexcept { - n_ = 0; + this->set_size(0); term(); } //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -306,6 +325,7 @@ insert( } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -314,38 +334,41 @@ insert( size_type count) -> fixed_string& { - if(index > size()) + const auto curr_size = size(); + const auto curr_data = data(); + if(index > curr_size) BOOST_FIXED_STRING_THROW(std::out_of_range{ "index > size()"}); - if(size() + count > max_size()) + if(count > max_size() - curr_size) BOOST_FIXED_STRING_THROW(std::length_error{ "size() + count > max_size()"}); - const bool inside = s <= &s_[size()] && s >= s_; - if (!inside || (inside && ((s - s_) + count <= index))) + const bool inside = s <= &curr_data[curr_size] && s >= curr_data; + if (!inside || (inside && ((s - curr_data) + count <= index))) { - Traits::move(&s_[index + count], &s_[index], size() - index + 1); - Traits::copy(&s_[index], s, count); + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); + Traits::copy(&curr_data[index], s, count); } else { - const size_type offset = s - s_; - Traits::move(&s_[index + count], &s_[index], size() - index + 1); + const size_type offset = s - curr_data; + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); if (offset < index) { const size_type diff = index - offset; - Traits::copy(&s_[index], &s_[offset], diff); - Traits::copy(&s_[index + diff], &s_[index + count], count - diff); + Traits::copy(&curr_data[index], &curr_data[offset], diff); + Traits::copy(&curr_data[index + diff], &curr_data[index + count], count - diff); } else { - Traits::copy(&s_[index], &s_[offset + count], count); + Traits::copy(&curr_data[index], &curr_data[offset + count], count); } } - n_ += count; + this->set_size(curr_size + count); return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -354,20 +377,22 @@ insert( CharT ch) -> iterator { - if(size() + count > max_size()) + const auto curr_size = size(); + const auto curr_data = data(); + if(count > max_size() - curr_size) BOOST_FIXED_STRING_THROW(std::length_error{ "size() + count() > max_size()"}); - auto const index = pos - s_; - Traits::move( - &s_[index + count], &s_[index], size() - index); - n_ += count; - Traits::assign(&s_[index], count, ch); + auto const index = pos - curr_data; + Traits::move(&curr_data[index + count], &curr_data[index], curr_size - index); + this->set_size(curr_size + count); + Traits::assign(&curr_data[index], count, ch); term(); - return &s_[index]; + return &curr_data[index]; } template template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -384,6 +409,7 @@ insert( template template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -401,6 +427,7 @@ insert( template template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: insert( @@ -423,6 +450,7 @@ insert( //------------------------------------------------------------------------------ template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: erase( @@ -430,17 +458,19 @@ erase( size_type count) -> fixed_string& { - if(index > size()) + const auto curr_size = size(); + const auto curr_data = data(); + if(index > curr_size) BOOST_FIXED_STRING_THROW(std::out_of_range{ "index > size()"}); - auto const n = (std::min)(count, size() - index); - Traits::move( - &s_[index], &s_[index + n], size() - (index + n) + 1); - n_ -= n; + auto const n = (std::min)(count, curr_size - index); + Traits::move(&curr_data[index], &curr_data[index + n], curr_size - (index + n) + 1); + this->set_size(curr_size - n); return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: erase( @@ -452,6 +482,7 @@ erase( } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: erase( @@ -465,19 +496,23 @@ erase( } template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: push_back( CharT ch) { - if(size() >= max_size()) + const auto curr_size = size(); + if(curr_size >= max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "size() >= max_size()"}); - Traits::assign(s_[n_++], ch); + Traits::assign(data()[curr_size], ch); + this->set_size(curr_size + 1); term(); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: append( @@ -485,100 +520,123 @@ append( size_type count) -> fixed_string& { - if(size() + count > max_size()) + const auto curr_size = size(); + if(count > max_size() - curr_size) BOOST_FIXED_STRING_THROW(std::length_error{ "size() + count > max_size()"}); - Traits::move( - &s_[n_ + count], &s_[n_], size() - n_); - Traits::copy(&s_[n_], s, count); - n_ += count; + Traits::copy(&data()[curr_size], s, count); + this->set_size(curr_size + count); term(); return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: substr(size_type pos, size_type count) const -> - string_view + fixed_string { if(pos > size()) BOOST_FIXED_STRING_THROW(std::out_of_range{ "pos > size()"}); - return {&s_[pos], (std::min)(count, size() - pos)}; + return {&data()[pos], (std::min)(count, size() - pos)}; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: -copy(CharT* dest, size_type count, size_type pos) const -> +subview(size_type pos, size_type count) const -> + string_view_type +{ + if (pos > size()) + BOOST_FIXED_STRING_THROW(std::out_of_range{ + "pos > size()"}); + return {&data()[pos], (std::min)(count, size() - pos)}; +} + +template +BOOST_FIXED_STRING_CPP14_CXPER +auto +fixed_string:: +copy(CharT* dest, size_type count, size_type pos) const noexcept -> size_type { - auto const s = substr(pos, count); + auto const s = subview(pos, count); Traits::copy(dest, s.data(), s.size()); return s.size(); } template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: resize(std::size_t n) { + const auto curr_size = size(); if(n > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "n > max_size()"}); - if(n > n_) - Traits::assign(&s_[n_], n - n_, CharT{}); - n_ = n; + if(n > curr_size) + Traits::assign(&data()[curr_size], n - curr_size, CharT{}); + this->set_size(n); term(); } template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: resize(std::size_t n, CharT c) { + const auto curr_size = size(); if(n > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "n > max_size()"}); - if(n > n_) - Traits::assign(&s_[n_], n - n_, c); - n_ = n; + if(n > curr_size) + Traits::assign(&data()[curr_size], n - curr_size, c); + this->set_size(n); term(); } template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: -swap(fixed_string& s) +swap(fixed_string& s) noexcept { + const auto curr_size = size(); fixed_string tmp(s); - s.n_ = n_; - Traits::copy(&s.s_[0], s_, n_ + 1); - n_ = tmp.n_; - Traits::copy(s_, &tmp.s_[0], n_ + 1); + s.set_size(curr_size); + Traits::copy(&s.data()[0], data(), curr_size + 1); + this->set_size(tmp.size()); + Traits::copy(data(), tmp.data(), size() + 1); } template template +BOOST_FIXED_STRING_CPP14_CXPER void fixed_string:: swap(fixed_string& s) { - if(size() > s.max_size()) + const auto curr_size = size(); + if(curr_size > s.max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "size() > s.max_size()"}); if(s.size() > max_size()) BOOST_FIXED_STRING_THROW(std::length_error{ "s.size() > max_size()"}); fixed_string tmp(s); - s.n_ = n_; - Traits::copy(&s.s_[0], s_, n_ + 1); - n_ = tmp.n_; - Traits::copy(s_, &tmp.s_[0], n_ + 1); + s.set_size(curr_size); + Traits::copy(&s.data()[0], data(), curr_size + 1); + this->set_size(tmp.size()); + Traits::copy(data(), &tmp.data()[0], size() + 1); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: replace( @@ -587,52 +645,55 @@ replace( const CharT* s, size_type n2) -> fixed_string& { - if (pos > size()) - BOOST_FIXED_STRING_THROW(std::out_of_range{ - "pos > size()"}); - if (size() - (std::min)(n1, size() - pos) >= max_size() - n2) - BOOST_FIXED_STRING_THROW(std::length_error{ - "replaced string exceeds max_size()"}); - if (pos + n1 >= size()) - n1 = size() - pos; - const bool inside = s <= &s_[size()] && s >= s_; - if (inside && size_type(s - s_) == pos && n1 == n2) - return *this; - if (!inside || (inside && ((s - s_) + n2 <= pos))) - { - // source outside - Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); - Traits::copy(&s_[pos], s, n2); - } - else - { - // source inside - const size_type offset = s - s_; - if (n2 >= n1) + const auto curr_size = size(); + const auto curr_data = data(); + if (pos > curr_size) + BOOST_FIXED_STRING_THROW(std::out_of_range{ + "pos > size()"}); + if (curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2) + BOOST_FIXED_STRING_THROW(std::length_error{ + "replaced string exceeds max_size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + const bool inside = s <= &curr_data[curr_size] && s >= curr_data; + if (inside && size_type(s - curr_data) == pos && n1 == n2) + return *this; + if (!inside || (inside && ((s - curr_data) + n2 <= pos))) { - // grow/unchanged - // shift all right of splice point by n2 - n1 to the right - Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); - const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; - // copy all before splice point - Traits::move(&s_[pos], &s_[offset], diff); - // copy all after splice point - Traits::move(&s_[pos + diff], &s_[offset + (n2 - n1) + diff], n2 - diff); + // source outside + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + Traits::copy(&curr_data[pos], s, n2); } else { - // shrink - // copy all elements into place - Traits::move(&s_[pos], &s_[offset], n2); - // shift all elements after splice point left - Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); + // source inside + const size_type offset = s - curr_data; + if (n2 >= n1) + { + // grow/unchanged + // shift all right of splice point by n2 - n1 to the right + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; + // copy all before splice point + Traits::move(&curr_data[pos], &curr_data[offset], diff); + // copy all after splice point + Traits::move(&curr_data[pos + diff], &curr_data[offset + (n2 - n1) + diff], n2 - diff); + } + else + { + // shrink + // copy all elements into place + Traits::move(&curr_data[pos], &curr_data[offset], n2); + // shift all elements after splice point left + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + } } - } - n_ += (n2 - n1); - return *this; + this->set_size(curr_size + (n2 - n1)); + return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: replace( @@ -641,135 +702,150 @@ replace( size_type n2, CharT c) -> fixed_string & { - if (pos > size()) - BOOST_FIXED_STRING_THROW(std::out_of_range{ - "pos > size()"}); - if (size() - (std::min)(n1, size() - pos) >= max_size() - n2) - BOOST_FIXED_STRING_THROW(std::length_error{ - "replaced string exceeds max_size()"}); - if (pos + n1 >= size()) - n1 = size() - pos; - Traits::move(&s_[pos + n2], &s_[pos + n1], size() - pos - n1 + 1); - Traits::assign(&s_[pos], n2, c); - n_ += (n2 - n1); - return *this; + const auto curr_size = size(); + const auto curr_data = data(); + if (pos > curr_size) + BOOST_FIXED_STRING_THROW(std::out_of_range{ + "pos > size()"}); + if (curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2) + BOOST_FIXED_STRING_THROW(std::length_error{ + "replaced string exceeds max_size()"}); + if (pos + n1 >= curr_size) + n1 = curr_size - pos; + Traits::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); + Traits::assign(&curr_data[pos], n2, c); + this->set_size(curr_size + (n2 - n1)); + return *this; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: find( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (pos > n_ || n > n_ - pos) - return npos; - if (!n) - return pos; - const auto res = std::search(&s_[pos], &s_[n_], s, &s[n], Traits::eq); - return res == end() ? npos : std::distance(s_, res); + const auto curr_size = size(); + if (pos > curr_size || n > curr_size - pos) + return npos; + if (!n) + return pos; + const auto res = std::search(&data()[pos], &data()[curr_size], s, &s[n], Traits::eq); + return res == end() ? npos : std::distance(data(), res); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: rfind( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (n_ < n) + const auto curr_size = size(); + const auto curr_data = data(); + if (curr_size < n) + return npos; + if (pos > curr_size - n) + pos = curr_size - n; + if (!n) + return pos; + for (auto sub = &curr_data[pos]; sub >= curr_data; --sub) + if (!Traits::compare(sub, s, n)) + return std::distance(curr_data, sub); return npos; - if (pos > n_ - n) - pos = n_ - n; - if (!n) - return pos; - for (auto sub = &s_[pos]; sub >= s_; --sub) - if (!Traits::compare(sub, s, n)) - return std::distance(s_, sub); - return npos; } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: find_first_of( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (pos >= n_ || !n) - return npos; - const auto res = std::find_first_of(&s_[pos], &s_[n_], s, &s[n], Traits::eq); - return res == end() ? npos : std::distance(s_, res); + const auto curr_data = data(); + if (pos >= size() || !n) + return npos; + const auto res = std::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], Traits::eq); + return res == end() ? npos : std::distance(curr_data, res); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: find_last_of( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (!n) - return npos; - if (pos >= n_) - pos = 0; - else - pos = n_ - (pos + 1); - const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq); - return res == rend() ? npos : n_ - 1 - std::distance(rbegin(), res); + const auto curr_size = size(); + if (!n) + return npos; + if (pos >= curr_size) + pos = 0; + else + pos = curr_size - (pos + 1); + const auto res = std::find_first_of(rbegin() + pos, rend(), s, &s[n], Traits::eq); + return res == rend() ? npos : curr_size - 1 - std::distance(rbegin(), res); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: find_first_not_of( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (pos >= n_) - return npos; - if (!n) - return pos; - const auto res = detail::find_not_of(&s_[pos], &s_[n_], s, n); - return res == end() ? npos : std::distance(s_, res); + if (pos >= size()) + return npos; + if (!n) + return pos; + const auto res = detail::find_not_of(&data()[pos], &data()[size()], s, n); + return res == end() ? npos : std::distance(data(), res); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: find_last_not_of( const CharT* s, size_type pos, - size_type n) const -> + size_type n) const noexcept -> size_type { - if (pos >= n_) - pos = n_ - 1; - if (!n) - return pos; - pos = n_ - (pos + 1); - const auto res = detail::find_not_of(rbegin() + pos, rend(), s, n); - return res == rend() ? npos : n_ - 1 - std::distance(rbegin(), res); + const auto curr_size = size(); + if (pos >= curr_size) + pos = curr_size - 1; + if (!n) + return pos; + pos = curr_size - (pos + 1); + const auto res = detail::find_not_of(rbegin() + pos, rend(), s, n); + return res == rend() ? npos : curr_size - 1 - std::distance(rbegin(), res); } template +BOOST_FIXED_STRING_CPP14_CXPER auto fixed_string:: -assign_char(CharT ch, std::true_type) -> +assign_char(CharT ch, std::true_type) noexcept -> fixed_string& { - n_ = 1; - Traits::assign(s_[0], ch); + this->set_size(1); + Traits::assign(data()[0], ch); term(); return *this; } diff --git a/test/fixed_string.cpp b/test/fixed_string.cpp index c4d4038..8167071 100644 --- a/test/fixed_string.cpp +++ b/test/fixed_string.cpp @@ -1,47 +1,64 @@ -// -// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) -// Copyright (c) 2019 Krystian Stasiowski (sdkrystian at gmail dot com) -// -// 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) -// -// Official repository: https://github.com/boostorg/fixed_string -// - -// Test that header file is self-contained. -#include - -#include - -namespace boost { -namespace fixed_string { - - +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// Copyright (c) 2019 Krystian Stasiowski (sdkrystian at gmail dot com) +// +// 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) +// +// Official repository: https://github.com/boostorg/fixed_string +// + +// Test that header file is self-contained. +#include "boost/fixed_string/fixed_string.hpp" + +#include + +namespace boost { +namespace fixed_string { + + template bool testS(const S& s, typename S::size_type pos, typename S::size_type n) { if (pos <= s.size()) { - typename S::string_view_type str = s.substr(pos, n); + S str = s.substr(pos, n); typename S::size_type rlen = (std::min)(n, s.size() - pos); return (S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0); - } - else + } + else + { + BOOST_TEST_THROWS((s.substr(pos, n)), std::out_of_range); + return true; + } +} + +template +bool +testSV(const S& s, typename S::size_type pos, typename S::size_type n) +{ + if (pos <= s.size()) { - BOOST_TEST_THROWS((s.substr(pos, n)), std::out_of_range); - return true; - } -} - + typename S::string_view_type str = s.subview(pos, n); + typename S::size_type rlen = (std::min)(n, s.size() - pos); + return (S::traits_type::compare(s.data() + pos, str.data(), rlen) == 0); + } + else + { + BOOST_TEST_THROWS((s.subview(pos, n)), std::out_of_range); + return true; + } +} + template bool testAS(S s, const typename S::value_type* str, typename S::size_type n, S expected) { s.assign(str, n); return s == expected; -} - +} + template bool testI(S s, typename S::size_type pos, const typename S::value_type* str, typename S::size_type n, S expected) @@ -58,8 +75,8 @@ testI(S s, typename S::size_type pos, const typename S::value_type* str, typenam BOOST_TEST_THROWS((s.insert(pos, str, n)), std::out_of_range); return true; } -} - +} + template bool testE(S s, typename S::size_type pos, typename S::size_type n, S expected) @@ -76,15 +93,15 @@ testE(S s, typename S::size_type pos, typename S::size_type n, S expected) BOOST_TEST_THROWS(s.erase(pos, n), std::out_of_range); return true; } -} - +} + template bool testA(S s, const typename S::value_type* str, typename S::size_type n, S expected) { return s.append(str, n) == expected; -} - +} + int sign(int x) { @@ -93,8 +110,8 @@ sign(int x) if (x < 0) return -1; return 1; -} - +} + template bool testC(const S& s, typename S::size_type pos, typename S::size_type n1, const typename S::value_type* str, typename S::size_type n2, int x) @@ -105,51 +122,51 @@ testC(const S& s, typename S::size_type pos, typename S::size_type n1, const typ { BOOST_TEST_THROWS(s.compare(pos, n1, str, n2), std::out_of_range); return true; - } -} - + } +} + template bool testF(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.find(str, pos, n) == x; -} - +} + template bool testRF(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.rfind(str, pos, n) == x; -} - +} + template bool testFF(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.find_first_of(str, pos, n) == x; -} - +} + template bool testFL(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.find_last_of(str, pos, n) == x; -} - +} + template bool testFFN(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.find_first_not_of(str, pos, n) == x; -} - +} + template bool testFLN(const S& s, const typename S::value_type* str, typename S::size_type pos, typename S::size_type n, typename S::size_type x) { return s.find_last_not_of(str, pos, n) == x; -} - +} + template bool testR(S s, typename S::size_type pos1, typename S::size_type n1, const typename S::value_type* str, S expected) @@ -158,8 +175,8 @@ testR(S s, typename S::size_type pos1, typename S::size_type n1, const typename typename S::const_iterator last = s.begin() + pos1 + n1; s.replace(first, last, str); return s == expected; -} - +} + template bool testR(S s, typename S::size_type pos, typename S::size_type n1, typename S::size_type n2, typename S::value_type c, S expected) @@ -176,8 +193,8 @@ testR(S s, typename S::size_type pos, typename S::size_type n1, typename S::size BOOST_TEST_THROWS((s.replace(pos, n1, n2, c)), std::out_of_range); return true; } -} - +} + template bool testR(S s, typename S::size_type pos, typename S::size_type n1, const typename S::value_type* str, typename S::size_type n2, S expected) @@ -194,378 +211,379 @@ testR(S s, typename S::size_type pos, typename S::size_type n1, const typename S BOOST_TEST_THROWS((s.replace(pos, n1, str, n2)), std::out_of_range); return true; } -} - -// dpne -static -void -testConstruct() -{ - { - fixed_string<1> s; - BOOST_TEST(s.empty()); - BOOST_TEST(s.size() == 0); - BOOST_TEST(s == ""); - BOOST_TEST(*s.end() == 0); - } - { - fixed_string<4> s1(3, 'x'); - BOOST_TEST(! s1.empty()); - BOOST_TEST(s1.size() == 3); - BOOST_TEST(s1 == "xxx"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - (fixed_string<2>(3, 'x')), - std::length_error); - } - { - fixed_string<5> s1("12345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<3> s2(s1, 2); - BOOST_TEST(s2 == "345"); - BOOST_TEST(*s2.end() == 0); - fixed_string<0> s3(s1, 5); - BOOST_TEST(s3.empty()); - BOOST_TEST(s3.front() == 0); - BOOST_TEST(*s3.end() == 0); - } - { - fixed_string<5> s1("12345"); - fixed_string<2> s2(s1, 1, 2); - BOOST_TEST(s2 == "23"); - BOOST_TEST(*s2.end() == 0); - fixed_string<0> s3(s1, 5, 1); - BOOST_TEST(s3.empty()); - BOOST_TEST(s3.front() == 0); - BOOST_TEST(*s3.end() == 0); - BOOST_TEST_THROWS( - (fixed_string<5>(s1, 6)), - std::out_of_range); - } - { - fixed_string<5> s1("UVXYZ", 3); - BOOST_TEST(s1 == "UVX"); - BOOST_TEST(*s1.end() == 0); - fixed_string<5> s2("X\0""Y\0""Z", 3); - BOOST_TEST(std::memcmp( - s2.data(), "X\0""Y", 3) == 0); - BOOST_TEST(*s2.end() == 0); - } - { - fixed_string<5> s1("12345"); - fixed_string<3> s2( - s1.begin() + 1, s1.begin() + 3); - BOOST_TEST(s2 == "23"); - BOOST_TEST(*s2.end() == 0); - } - { - fixed_string<5> s1("12345"); - fixed_string<5> s2(s1); - BOOST_TEST(s2 == "12345"); - BOOST_TEST(*s2.end() == 0); - fixed_string<6> s3(s1); - BOOST_TEST(s3 == "12345"); - BOOST_TEST(*s3.end() == 0); - BOOST_TEST_THROWS( - (fixed_string<4>(s1)), - std::length_error); - } - { - fixed_string<3> s1({'1', '2', '3'}); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST( - fixed_string<0>({}) == fixed_string<0>()); - BOOST_TEST_THROWS( - (fixed_string<2>({'1', '2', '3'})), - std::length_error); - } - { - fixed_string<3> s1( - string_view("123")); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - (fixed_string<2>(string_view("123"))), - std::length_error); - } - { - fixed_string<5> s1( - std::string("12345"), 2, 2); - BOOST_TEST(s1 == "34"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - (fixed_string<2>(std::string("12345"), 1, 3)), - std::length_error); - } - { - BOOST_TEST_THROWS(fixed_string<5>("12345678"), std::length_error); - } -} - -//done -static -void -testAssignment() -{ - // assign(size_type count, CharT ch) - BOOST_TEST(fixed_string<3>{}.assign(1, '*') == "*"); - BOOST_TEST(fixed_string<3>{}.assign(3, '*') == "***"); - BOOST_TEST(fixed_string<3>{"abc"}.assign(3, '*') == "***"); - BOOST_TEST_THROWS(fixed_string<1>{"a"}.assign(2, '*'), std::length_error); - - // assign(fixed_string const& s) noexcept - BOOST_TEST(fixed_string<3>{}.assign(fixed_string<3>{"abc"}) == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<3>{"abc"}) == "abc"); - BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<3>{"abc"}) == "abc"); - - // assign(fixed_string const& s) - BOOST_TEST(fixed_string<3>{}.assign(fixed_string<5>{"abc"}) == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<5>{"abc"}) == "abc"); - BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<5>{"abc"}) == "abc"); - { - fixed_string<3> s("***"); - BOOST_TEST(s.assign(s) == s); - } - BOOST_TEST_THROWS(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}), std::length_error); - - // assign(fixed_string const& s, size_type pos, size_type count = npos) - BOOST_TEST(fixed_string<4>{}.assign(fixed_string<5>{"abcde"}, 1) == "bcde"); - BOOST_TEST(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); - BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); - BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); - BOOST_TEST_THROWS(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}, 0), std::length_error); - - // assign(CharT const* s, size_type count) - BOOST_TEST(fixed_string<3>{}.assign("abc", 3) == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign("abc", 3) == "abc"); - BOOST_TEST_THROWS(fixed_string<1>{}.assign("abc", 3), std::length_error); - - // assign(CharT const* s) - BOOST_TEST(fixed_string<3>{}.assign("abc") == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign("abc") == "abc"); - BOOST_TEST_THROWS(fixed_string<1>{}.assign("abc"), std::length_error); - - // assign(InputIt first, InputIt last) - { - fixed_string<4> const cs{"abcd"}; - fixed_string<4> s{"ad"}; - BOOST_TEST(fixed_string<4>{}.assign(cs.begin(), cs.end()) == "abcd"); - BOOST_TEST(fixed_string<4>{"*"}.assign(cs.begin(), cs.end()) == "abcd"); - BOOST_TEST_THROWS(fixed_string<2>{"*"}.assign(cs.begin(), cs.end()), std::length_error); - } - - // assign(std::initializer_list ilist) - BOOST_TEST(fixed_string<3>{}.assign({'a', 'b', 'c'}) == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign({'a', 'b', 'c'}) == "abc"); - BOOST_TEST(fixed_string<3>{"***"}.assign({'a', 'b', 'c'}) == "abc"); - BOOST_TEST_THROWS(fixed_string<1>{}.assign({'a', 'b', 'c'}), std::length_error); - - // assign(T const& t) - { - struct T - { - operator string_view() const noexcept - { - return "abc"; - } - }; - BOOST_TEST(fixed_string<3>{}.assign(T{}) == "abc"); - BOOST_TEST(fixed_string<3>{"*"}.assign(T{}) == "abc"); - BOOST_TEST(fixed_string<3>{"***"}.assign(T{}) == "abc"); - BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}), std::length_error); - } - - // assign(T const& t, size_type pos, size_type count = npos) - { - struct T - { - operator string_view() const noexcept - { - return "abcde"; - } - }; - BOOST_TEST(fixed_string<5>{}.assign(T{}, 0) == "abcde"); - BOOST_TEST(fixed_string<5>{}.assign(T{}, 0, 5) == "abcde"); - BOOST_TEST(fixed_string<5>{}.assign(T{}, 1, 3) == "bcd"); - BOOST_TEST(fixed_string<5>{"*"}.assign(T{}, 1) == "bcde"); - BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}, 6, 3), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}, 1, 3), std::length_error); - } - - //--- - - { - fixed_string<3> s1("123"); - fixed_string<3> s2; - s2 = s1; - BOOST_TEST(s2 == "123"); - BOOST_TEST(*s2.end() == 0); - } - { - fixed_string<3> s1("123"); - fixed_string<5> s2; - s2 = s1; - BOOST_TEST(s2 == "123"); - BOOST_TEST(*s2.end() == 0); - fixed_string<1> s3; - BOOST_TEST_THROWS( - s3 = s1, - std::length_error); - } - { - fixed_string<3> s1; - s1 = "123"; - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - fixed_string<1> s2; - BOOST_TEST_THROWS( - s2 = "123", - std::length_error); - } - { - fixed_string<1> s1; - s1 = 'x'; - BOOST_TEST(s1 == "x"); - BOOST_TEST(*s1.end() == 0); - fixed_string<0> s2; - BOOST_TEST_THROWS( - s2 = 'x', - std::length_error); - } - { - fixed_string<3> s1; - s1 = {'1', '2', '3'}; - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - fixed_string<1> s2; - BOOST_TEST_THROWS( - (s2 = {'1', '2', '3'}), - std::length_error); - } - { - fixed_string<3> s1; - s1 = string_view("123"); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - fixed_string<1> s2; - BOOST_TEST_THROWS( - s2 = string_view("123"), - std::length_error); - } - - { - fixed_string<4> s1; - s1.assign(3, 'x'); - BOOST_TEST(s1 == "xxx"); - BOOST_TEST(*s1.end() == 0); - fixed_string<2> s2; - BOOST_TEST_THROWS( - s2.assign(3, 'x'), - std::length_error); - } - { - fixed_string<5> s1("12345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<5> s2; - s2.assign(s1); - BOOST_TEST(s2 == "12345"); - BOOST_TEST(*s2.end() == 0); - } - { - fixed_string<5> s1("12345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<7> s2; - s2.assign(s1); - BOOST_TEST(s2 == "12345"); - BOOST_TEST(*s2.end() == 0); - fixed_string<3> s3; - BOOST_TEST_THROWS( - s3.assign(s1), - std::length_error); - } - { - fixed_string<5> s1("12345"); - fixed_string<5> s2; - s2.assign(s1, 1); - BOOST_TEST(s2 == "2345"); - BOOST_TEST(*s2.end() == 0); - s2.assign(s1, 1, 2); - BOOST_TEST(s2 == "23"); - BOOST_TEST(*s2.end() == 0); - s2.assign(s1, 1, 100); - BOOST_TEST(s2 == "2345"); - BOOST_TEST(*s2.end() == 0); - BOOST_TEST_THROWS( - (s2.assign(s1, 6)), - std::out_of_range); - fixed_string<3> s3; - BOOST_TEST_THROWS( - s3.assign(s1, 1), - std::length_error); - } - { - fixed_string<5> s1; - s1.assign("12"); - BOOST_TEST(s1 == "12"); - BOOST_TEST(*s1.end() == 0); - s1.assign("12345"); - BOOST_TEST(s1 == "12345"); - BOOST_TEST(*s1.end() == 0); - } - { - fixed_string<5> s1; - s1.assign("12345", 3); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - } - { - fixed_string<5> s1("12345"); - fixed_string<3> s2; - s2.assign(s1.begin(), s1.begin() + 2); - BOOST_TEST(s2 == "12"); - BOOST_TEST(*s2.end() == 0); - BOOST_TEST_THROWS( - (s2.assign(s1.begin(), s1.end())), - std::length_error); - } - { - fixed_string<5> s1; - s1.assign({'1', '2', '3'}); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - fixed_string<1> s2; - BOOST_TEST_THROWS( - (s2.assign({'1', '2', '3'})), - std::length_error); - } - { - fixed_string<5> s1; - s1.assign(string_view("123")); - BOOST_TEST(s1 == "123"); - BOOST_TEST(*s1.end() == 0); - s1.assign(string_view("12345")); - BOOST_TEST(s1 == "12345"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - s1.assign(string_view("1234567")), - std::length_error); - } - { - fixed_string<5> s1; - s1.assign(std::string("12345"), 2, 2); - BOOST_TEST(s1 == "34"); - BOOST_TEST(*s1.end() == 0); - s1.assign(std::string("12345"), 3); - BOOST_TEST(s1 == "45"); - BOOST_TEST(*s1.end() == 0); - fixed_string<2> s2; - BOOST_TEST_THROWS( - (s2.assign(std::string("12345"), 1, 3)), - std::length_error); - } - - using S = fixed_string<400>; +} + +// dpne +static +void +testConstruct() +{ + { + fixed_string<1> s; + BOOST_TEST(s.empty()); + BOOST_TEST(s.size() == 0); + BOOST_TEST(s == ""); + BOOST_TEST(*s.end() == 0); + } + { + fixed_string<4> s1(3, 'x'); + BOOST_TEST(! s1.empty()); + BOOST_TEST(s1.size() == 3); + BOOST_TEST(s1 == "xxx"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + (fixed_string<2>(3, 'x')), + std::length_error); + } + { + fixed_string<5> s1("12345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<3> s2(s1, 2); + BOOST_TEST(s2 == "345"); + BOOST_TEST(*s2.end() == 0); + fixed_string<0> s3(s1, 5); + BOOST_TEST(s3.empty()); + BOOST_TEST(s3.front() == 0); + BOOST_TEST(*s3.end() == 0); + } + { + fixed_string<5> s1("12345"); + fixed_string<2> s2(s1, 1, 2); + BOOST_TEST(s2 == "23"); + BOOST_TEST(*s2.end() == 0); + fixed_string<0> s3(s1, 5, 1); + BOOST_TEST(s3.empty()); + BOOST_TEST(s3.front() == 0); + BOOST_TEST(*s3.end() == 0); + BOOST_TEST_THROWS( + (fixed_string<5>(s1, 6)), + std::out_of_range); + } + { + fixed_string<5> s1("UVXYZ", 3); + BOOST_TEST(s1 == "UVX"); + BOOST_TEST(*s1.end() == 0); + fixed_string<5> s2("X\0""Y\0""Z", 3); + BOOST_TEST(std::memcmp( + s2.data(), "X\0""Y", 3) == 0); + BOOST_TEST(*s2.end() == 0); + } + { + fixed_string<5> s1("12345"); + fixed_string<3> s2( + s1.begin() + 1, s1.begin() + 3); + BOOST_TEST(s2 == "23"); + BOOST_TEST(*s2.end() == 0); + } + { + fixed_string<5> s1("12345"); + fixed_string<5> s2(s1); + BOOST_TEST(s2 == "12345"); + BOOST_TEST(*s2.end() == 0); + fixed_string<6> s3(s1); + BOOST_TEST(s3 == "12345"); + BOOST_TEST(*s3.end() == 0); + BOOST_TEST_THROWS( + (fixed_string<4>(s1)), + std::length_error); + } + { + fixed_string<3> s1({'1', '2', '3'}); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST( + fixed_string<0>({}) == fixed_string<0>()); + BOOST_TEST_THROWS( + (fixed_string<2>({'1', '2', '3'})), + std::length_error); + } + { + fixed_string<3> s1( + string_view("123")); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + (fixed_string<2>(string_view("123"))), + std::length_error); + } + { + fixed_string<5> s1( + std::string("12345"), 2, 2); + BOOST_TEST(s1 == "34"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + (fixed_string<2>(std::string("12345"), 1, 3)), + std::length_error); + } + { + BOOST_TEST_THROWS(fixed_string<5>("12345678"), std::length_error); + } +} + +//done +static +void +testAssignment() +{ + // assign(size_type count, CharT ch) + BOOST_TEST(fixed_string<3>{}.assign(1, '*') == "*"); + BOOST_TEST(fixed_string<3>{}.assign(3, '*') == "***"); + BOOST_TEST(fixed_string<3>{"abc"}.assign(3, '*') == "***"); + BOOST_TEST_THROWS(fixed_string<1>{"a"}.assign(2, '*'), std::length_error); + + // assign(fixed_string const& s) noexcept + BOOST_TEST(fixed_string<3>{}.assign(fixed_string<3>{"abc"}) == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<3>{"abc"}) == "abc"); + BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<3>{"abc"}) == "abc"); + + // assign(fixed_string const& s) + BOOST_TEST(fixed_string<3>{}.assign(fixed_string<5>{"abc"}) == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<5>{"abc"}) == "abc"); + BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<5>{"abc"}) == "abc"); + { + fixed_string<3> s("***"); + BOOST_TEST(s.assign(s) == s); + } + BOOST_TEST_THROWS(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}), std::length_error); + + // assign(fixed_string const& s, size_type pos, size_type count = npos) + BOOST_TEST(fixed_string<4>{}.assign(fixed_string<5>{"abcde"}, 1) == "bcde"); + BOOST_TEST(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); + BOOST_TEST(fixed_string<3>{"*"}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); + BOOST_TEST(fixed_string<3>{"***"}.assign(fixed_string<5>{"abcde"}, 1, 3) == "bcd"); + BOOST_TEST_THROWS(fixed_string<3>{}.assign(fixed_string<5>{"abcde"}, 0), std::length_error); + + // assign(CharT const* s, size_type count) + BOOST_TEST(fixed_string<3>{}.assign("abc", 3) == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign("abc", 3) == "abc"); + BOOST_TEST_THROWS(fixed_string<1>{}.assign("abc", 3), std::length_error); + + // assign(CharT const* s) + BOOST_TEST(fixed_string<3>{}.assign("abc") == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign("abc") == "abc"); + BOOST_TEST_THROWS(fixed_string<1>{}.assign("abc"), std::length_error); + + // assign(InputIt first, InputIt last) + { + fixed_string<4> const cs{"abcd"}; + fixed_string<4> s{"ad"}; + BOOST_TEST(fixed_string<4>{}.assign(cs.begin(), cs.end()) == "abcd"); + BOOST_TEST(fixed_string<4>{"*"}.assign(cs.begin(), cs.end()) == "abcd"); + BOOST_TEST_THROWS(fixed_string<2>{"*"}.assign(cs.begin(), cs.end()), std::length_error); + } + + // assign(std::initializer_list ilist) + BOOST_TEST(fixed_string<3>{}.assign({'a', 'b', 'c'}) == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign({'a', 'b', 'c'}) == "abc"); + BOOST_TEST(fixed_string<3>{"***"}.assign({'a', 'b', 'c'}) == "abc"); + BOOST_TEST_THROWS(fixed_string<1>{}.assign({'a', 'b', 'c'}), std::length_error); + + // assign(T const& t) + { + struct T + { + operator string_view() const noexcept + { + return "abc"; + } + }; + BOOST_TEST(fixed_string<3>{}.assign(T{}) == "abc"); + BOOST_TEST(fixed_string<3>{"*"}.assign(T{}) == "abc"); + BOOST_TEST(fixed_string<3>{"***"}.assign(T{}) == "abc"); + BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}), std::length_error); + } + + // assign(T const& t, size_type pos, size_type count = npos) + { + struct T + { + operator string_view() const noexcept + { + return "abcde"; + } + }; + BOOST_TEST(fixed_string<5>{}.assign(T{}, 0) == "abcde"); + BOOST_TEST(fixed_string<5>{}.assign(T{}, 0, 5) == "abcde"); + BOOST_TEST(fixed_string<5>{}.assign(T{}, 1, 3) == "bcd"); + BOOST_TEST(fixed_string<5>{"*"}.assign(T{}, 1) == "bcde"); + BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}, 6, 3), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<2>{"**"}.assign(T{}, 1, 3), std::length_error); + } + + //--- + + { + fixed_string<3> s1("123"); + fixed_string<3> s2; + s2 = s1; + BOOST_TEST(s2 == "123"); + BOOST_TEST(*s2.end() == 0); + } + { + fixed_string<3> s1("123"); + fixed_string<5> s2; + s2 = s1; + BOOST_TEST(s2 == "123"); + BOOST_TEST(*s2.end() == 0); + fixed_string<1> s3; + BOOST_TEST_THROWS( + s3 = s1, + std::length_error); + } + + { + fixed_string<3> s1; + s1 = "123"; + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + fixed_string<1> s2; + BOOST_TEST_THROWS( + s2 = "123", + std::length_error); + } + { + fixed_string<1> s1; + s1 = 'x'; + BOOST_TEST(s1 == "x"); + BOOST_TEST(*s1.end() == 0); + fixed_string<0> s2; + BOOST_TEST_THROWS( + s2 = 'x', + std::length_error); + } + { + fixed_string<3> s1; + s1 = {'1', '2', '3'}; + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + fixed_string<1> s2; + BOOST_TEST_THROWS( + (s2 = {'1', '2', '3'}), + std::length_error); + } + { + fixed_string<3> s1; + s1 = string_view("123"); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + fixed_string<1> s2; + BOOST_TEST_THROWS( + s2 = string_view("123"), + std::length_error); + } + + { + fixed_string<4> s1; + s1.assign(3, 'x'); + BOOST_TEST(s1 == "xxx"); + BOOST_TEST(*s1.end() == 0); + fixed_string<2> s2; + BOOST_TEST_THROWS( + s2.assign(3, 'x'), + std::length_error); + } + { + fixed_string<5> s1("12345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<5> s2; + s2.assign(s1); + BOOST_TEST(s2 == "12345"); + BOOST_TEST(*s2.end() == 0); + } + { + fixed_string<5> s1("12345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<7> s2; + s2.assign(s1); + BOOST_TEST(s2 == "12345"); + BOOST_TEST(*s2.end() == 0); + fixed_string<3> s3; + BOOST_TEST_THROWS( + s3.assign(s1), + std::length_error); + } + { + fixed_string<5> s1("12345"); + fixed_string<5> s2; + s2.assign(s1, 1); + BOOST_TEST(s2 == "2345"); + BOOST_TEST(*s2.end() == 0); + s2.assign(s1, 1, 2); + BOOST_TEST(s2 == "23"); + BOOST_TEST(*s2.end() == 0); + s2.assign(s1, 1, 100); + BOOST_TEST(s2 == "2345"); + BOOST_TEST(*s2.end() == 0); + BOOST_TEST_THROWS( + (s2.assign(s1, 6)), + std::out_of_range); + fixed_string<3> s3; + BOOST_TEST_THROWS( + s3.assign(s1, 1), + std::length_error); + } + { + fixed_string<5> s1; + s1.assign("12"); + BOOST_TEST(s1 == "12"); + BOOST_TEST(*s1.end() == 0); + s1.assign("12345"); + BOOST_TEST(s1 == "12345"); + BOOST_TEST(*s1.end() == 0); + } + { + fixed_string<5> s1; + s1.assign("12345", 3); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + } + { + fixed_string<5> s1("12345"); + fixed_string<3> s2; + s2.assign(s1.begin(), s1.begin() + 2); + BOOST_TEST(s2 == "12"); + BOOST_TEST(*s2.end() == 0); + BOOST_TEST_THROWS( + (s2.assign(s1.begin(), s1.end())), + std::length_error); + } + { + fixed_string<5> s1; + s1.assign({'1', '2', '3'}); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + fixed_string<1> s2; + BOOST_TEST_THROWS( + (s2.assign({'1', '2', '3'})), + std::length_error); + } + { + fixed_string<5> s1; + s1.assign(string_view("123")); + BOOST_TEST(s1 == "123"); + BOOST_TEST(*s1.end() == 0); + s1.assign(string_view("12345")); + BOOST_TEST(s1 == "12345"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + s1.assign(string_view("1234567")), + std::length_error); + } + { + fixed_string<5> s1; + s1.assign(std::string("12345"), 2, 2); + BOOST_TEST(s1 == "34"); + BOOST_TEST(*s1.end() == 0); + s1.assign(std::string("12345"), 3); + BOOST_TEST(s1 == "45"); + BOOST_TEST(*s1.end() == 0); + fixed_string<2> s2; + BOOST_TEST_THROWS( + (s2.assign(std::string("12345"), 1, 3)), + std::length_error); + } + + using S = fixed_string<400>; BOOST_TEST(testAS(S(), "", 0, S())); BOOST_TEST(testAS(S(), "12345", 3, S("123"))); BOOST_TEST(testAS(S(), "12345", 4, S("1234"))); @@ -611,502 +629,502 @@ testAssignment() BOOST_TEST(s_long == "Lorem ipsum dolor sit amet, consectetur/"); s_long.assign(s_long.data() + 2, 8); - BOOST_TEST(s_long == "rem ipsu"); -} - -// done -static -void -testElements() -{ - using cfs3 = fixed_string<3> const; - - // at(size_type pos) - BOOST_TEST(fixed_string<3>{"abc"}.at(0) == 'a'); - BOOST_TEST(fixed_string<3>{"abc"}.at(2) == 'c'); - BOOST_TEST_THROWS(fixed_string<3>{""}.at(0), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.at(4), std::out_of_range); - - // at(size_type pos) const - BOOST_TEST(cfs3{"abc"}.at(0) == 'a'); - BOOST_TEST(cfs3{"abc"}.at(2) == 'c'); - BOOST_TEST_THROWS(cfs3{""}.at(0), std::out_of_range); - BOOST_TEST_THROWS(cfs3{"abc"}.at(4), std::out_of_range); - - // operator[](size_type pos) - BOOST_TEST(fixed_string<3>{"abc"}[0] == 'a'); - BOOST_TEST(fixed_string<3>{"abc"}[2] == 'c'); - BOOST_TEST(fixed_string<3>{"abc"}[3] == 0); - BOOST_TEST(fixed_string<3>{""}[0] == 0); - - // operator[](size_type pos) const - BOOST_TEST(cfs3{"abc"}[0] == 'a'); - BOOST_TEST(cfs3{"abc"}[2] == 'c'); - BOOST_TEST(cfs3{"abc"}[3] == 0); - BOOST_TEST(cfs3{""}[0] == 0); - - // front() - BOOST_TEST(fixed_string<3>{"a"}.front() == 'a'); - BOOST_TEST(fixed_string<3>{"abc"}.front() == 'a'); - - // front() const - BOOST_TEST(cfs3{"a"}.front() == 'a'); - BOOST_TEST(cfs3{"abc"}.front() == 'a'); - - // back() - BOOST_TEST(fixed_string<3>{"a"}.back() == 'a'); - BOOST_TEST(fixed_string<3>{"abc"}.back() == 'c'); - - // back() const - BOOST_TEST(cfs3{"a"}.back() == 'a'); - BOOST_TEST(cfs3{"abc"}.back() == 'c'); - - // data() noexcept - // data() const noexcept - // c_str() const noexcept - // operator string_view_type() const noexcept - - //--- - - { - fixed_string<5> s("12345"); - BOOST_TEST(s.at(1) == '2'); - BOOST_TEST(s.at(4) == '5'); - BOOST_TEST_THROWS( - s.at(5) = 0, - std::out_of_range); - } - { - fixed_string<5> const s("12345"); - BOOST_TEST(s.at(1) == '2'); - BOOST_TEST(s.at(4) == '5'); - BOOST_TEST_THROWS( - s.at(5), - std::out_of_range); - } - { - fixed_string<5> s("12345"); - BOOST_TEST(s[1] == '2'); - BOOST_TEST(s[4] == '5'); - s[1] = '_'; - BOOST_TEST(s == "1_345"); - } - { - fixed_string<5> const s("12345"); - BOOST_TEST(s[1] == '2'); - BOOST_TEST(s[4] == '5'); - BOOST_TEST(s[5] == 0); - } - { - fixed_string<3> s("123"); - BOOST_TEST(s.front() == '1'); - BOOST_TEST(s.back() == '3'); - s.front() = '_'; - BOOST_TEST(s == "_23"); - s.back() = '_'; - BOOST_TEST(s == "_2_"); - } - { - fixed_string<3> const s("123"); - BOOST_TEST(s.front() == '1'); - BOOST_TEST(s.back() == '3'); - } - { - fixed_string<3> s("123"); - BOOST_TEST(std::memcmp( - s.data(), "123", 3) == 0); - } - { - fixed_string<3> const s("123"); - BOOST_TEST(std::memcmp( - s.data(), "123", 3) == 0); - } - { - fixed_string<3> s("123"); - BOOST_TEST(std::memcmp( - s.c_str(), "123\0", 4) == 0); - } - { - fixed_string<3> s("123"); - string_view sv = s; - BOOST_TEST(fixed_string<5>(sv) == "123"); - } -} - -// done -static -void -testIterators() -{ - { - fixed_string<3> s; - BOOST_TEST(std::distance(s.begin(), s.end()) == 0); - BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 0); - s = "123"; - BOOST_TEST(std::distance(s.begin(), s.end()) == 3); - BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 3); - } - { - fixed_string<3> const s("123"); - BOOST_TEST(std::distance(s.begin(), s.end()) == 3); - BOOST_TEST(std::distance(s.cbegin(), s.cend()) == 3); - BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 3); - BOOST_TEST(std::distance(s.crbegin(), s.crend()) == 3); - } -} - -// done -static -void -testCapacity() -{ - // empty() - BOOST_TEST(fixed_string<0>{}.empty()); - BOOST_TEST(fixed_string<1>{}.empty()); - BOOST_TEST(! fixed_string<1>{"a"}.empty()); - BOOST_TEST(! fixed_string<3>{"abc"}.empty()); - - // size() - BOOST_TEST(fixed_string<0>{}.size() == 0); - BOOST_TEST(fixed_string<1>{}.size() == 0); - BOOST_TEST(fixed_string<1>{"a"}.size() == 1); - BOOST_TEST(fixed_string<3>{"abc"}.size() == 3); - BOOST_TEST(fixed_string<5>{"abc"}.size() == 3); - - // length() - BOOST_TEST(fixed_string<0>{}.length() == 0); - BOOST_TEST(fixed_string<1>{}.length() == 0); - BOOST_TEST(fixed_string<1>{"a"}.length() == 1); - BOOST_TEST(fixed_string<3>{"abc"}.length() == 3); - BOOST_TEST(fixed_string<5>{"abc"}.length() == 3); - - // max_size() - BOOST_TEST(fixed_string<0>{}.max_size() == 0); - BOOST_TEST(fixed_string<1>{}.max_size() == 1); - BOOST_TEST(fixed_string<1>{"a"}.max_size() == 1); - BOOST_TEST(fixed_string<3>{"abc"}.max_size() == 3); - BOOST_TEST(fixed_string<5>{"abc"}.max_size() == 5); - - // reserve(std::size_t n) - fixed_string<3>{}.reserve(0); - fixed_string<3>{}.reserve(1); - fixed_string<3>{}.reserve(3); - BOOST_TEST_THROWS(fixed_string<0>{}.reserve(1), std::length_error); - BOOST_TEST_THROWS(fixed_string<3>{}.reserve(4), std::length_error); - - // capacity() - BOOST_TEST(fixed_string<0>{}.capacity() == 0); - BOOST_TEST(fixed_string<1>{}.capacity() == 1); - BOOST_TEST(fixed_string<1>{"a"}.capacity() == 1); - BOOST_TEST(fixed_string<3>{"abc"}.capacity() == 3); - BOOST_TEST(fixed_string<5>{"abc"}.capacity() == 5); - - //--- - - fixed_string<3> s; - BOOST_TEST(s.empty()); - BOOST_TEST(s.size() == 0); - BOOST_TEST(s.length() == 0); - BOOST_TEST(s.max_size() == 3); - BOOST_TEST(s.capacity() == 3); - s = "123"; - BOOST_TEST(! s.empty()); - BOOST_TEST(s.size() == 3); - BOOST_TEST(s.length() == 3); - s.reserve(0); - s.reserve(3); - BOOST_TEST_THROWS( - s.reserve(4), - std::length_error); - s.shrink_to_fit(); - BOOST_TEST(! s.empty()); - BOOST_TEST(s.size() == 3); - BOOST_TEST(s.length() == 3); - BOOST_TEST(*s.end() == 0); -} - -// done -static -void -testClear() -{ - // clear() - fixed_string<3> s("123"); - s.clear(); - BOOST_TEST(s.empty()); - BOOST_TEST(*s.end() == 0); -} - -// done -static -void -testInsert() -{ - using sv = string_view; - using S = fixed_string<100>; - - // insert(size_type index, size_type count, CharT ch) - // The overload resolution is ambiguous - // here because 0 is also a pointer type - //BOOST_TEST(fixed_string<3>{"bc"}.insert(0, 1, 'a') == "abc"); - BOOST_TEST(fixed_string<3>{"bc"}.insert(std::size_t(0), 1, 'a') == "abc"); - BOOST_TEST(fixed_string<3>{"ac"}.insert(1, 1, 'b') == "abc"); - BOOST_TEST(fixed_string<3>{"ab"}.insert(2, 1, 'c') == "abc"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, 1, '*'), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, 1, '*'), std::length_error); - - // insert(size_type index, CharT const* s) - BOOST_TEST(fixed_string<3>{"bc"}.insert(0, "a") == "abc"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, "*"), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, "*"), std::length_error); - - // insert(size_type index, CharT const* s, size_type count) - BOOST_TEST(fixed_string<4>{"ad"}.insert(1, "bcd", 2) == "abcd"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, "*"), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, "*"), std::length_error); - - // insert(size_type index, string_view_type sv) - BOOST_TEST(fixed_string<3>{"ac"}.insert(1, sv{"b"}) == "abc"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, sv{"*"}), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, sv{"*"}), std::length_error); - - // insert(size_type index, string_view_type sv, size_type index_str, size_type count = npos) - BOOST_TEST(fixed_string<4>{"ad"}.insert(1, sv{"abcd"}, 1, 2) == "abcd"); - BOOST_TEST(fixed_string<4>{"ad"}.insert(1, sv{"abc"}, 1) == "abcd"); - BOOST_TEST_THROWS((fixed_string<4>{"ad"}.insert(1, sv{"bc"}, 3, 0)), std::out_of_range); - BOOST_TEST_THROWS((fixed_string<3>{"ad"}.insert(1, sv{"bc"}, 0, 2)), std::length_error); - - // insert(const_iterator pos, CharT ch) - { - fixed_string<3> s{"ac"}; - BOOST_TEST(s.insert(s.begin() + 1, 'b') == s.begin() + 1); - BOOST_TEST(s == "abc"); - BOOST_TEST_THROWS(s.insert(s.begin() + 1, '*'), std::length_error); - } - - // insert(const_iterator pos, size_type count, CharT ch) - { - fixed_string<4> s{"ac"}; - BOOST_TEST(s.insert(s.begin() + 1, 2, 'b') == s.begin() + 1); - BOOST_TEST(s == "abbc"); - BOOST_TEST_THROWS(s.insert(s.begin() + 1, 2, '*'), std::length_error); - } - - // insert(const_iterator pos, InputIt first, InputIt last) - { - fixed_string<4> const cs{"abcd"}; - fixed_string<4> s{"ad"}; - BOOST_TEST(s.insert(s.begin() + 1, cs.begin() + 1, cs.begin() + 3) == s.begin() + 1); - BOOST_TEST(s == "abcd"); - } - - // insert(const_iterator pos, std::initializer_list ilist) - { - fixed_string<4> s{"ad"}; - BOOST_TEST(s.insert(s.begin() + 1, {'b', 'c'}) == s.begin() + 1); - BOOST_TEST(s == "abcd"); - } - - // insert(size_type index, T const& t) - { - struct T - { - operator string_view() const noexcept - { - return "b"; - } - }; - BOOST_TEST(fixed_string<3>{"ac"}.insert(1, T{}) == "abc"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, T{}), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, T{}), std::length_error); - } - - // insert(size_type index, T const& t, size_type index_str, size_type count = npos) - { - struct T - { - operator string_view() const noexcept - { - return "abcd"; - } - }; - BOOST_TEST(fixed_string<6>{"ae"}.insert(1, T{}, 1) == "abcde"); - BOOST_TEST(fixed_string<6>{"abe"}.insert(2, T{}, 2) == "abcde"); - BOOST_TEST(fixed_string<4>{"ac"}.insert(1, T{}, 1, 1) == "abc"); - BOOST_TEST(fixed_string<4>{"ad"}.insert(1, T{}, 1, 2) == "abcd"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, T{}), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, T{}), std::length_error); - } - - //--- - - { - // Using 7 as the size causes a miscompile in MSVC14.2 x64 Release - fixed_string<8> s1("12345"); - s1.insert(2, 2, '_'); - BOOST_TEST(s1 == "12__345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<6> s2("12345"); - BOOST_TEST_THROWS( - (s2.insert(2, 2, '_')), - std::length_error); - fixed_string<6> s3("12345"); - BOOST_TEST_THROWS( - (s3.insert(6, 2, '_')), - std::out_of_range); - } - { - fixed_string<7> s1("12345"); - s1.insert(2, "__"); - BOOST_TEST(s1 == "12__345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<6> s2("12345"); - BOOST_TEST_THROWS( - (s2.insert(2, "__")), - std::length_error); - fixed_string<6> s3("12345"); - BOOST_TEST_THROWS( - (s2.insert(6, "__")), - std::out_of_range); - } - { - fixed_string<7> s1("12345"); - s1.insert(2, "TUV", 2); - BOOST_TEST(s1 == "12TU345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<6> s2("12345"); - BOOST_TEST_THROWS( - (s2.insert(2, "TUV", 2)), - std::length_error); - fixed_string<6> s3("12345"); - BOOST_TEST_THROWS( - (s3.insert(6, "TUV", 2)), - std::out_of_range); - } - { - fixed_string<7> s1("12345"); - s1.insert(2, fixed_string<3>("TU")); - BOOST_TEST(s1 == "12TU345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<6> s2("12345"); - BOOST_TEST_THROWS( - (s2.insert(2, fixed_string<3>("TUV"))), - std::length_error); - fixed_string<6> s3("12345"); - BOOST_TEST_THROWS( - (s3.insert(6, fixed_string<3>("TUV"))), - std::out_of_range); - } - { - fixed_string<7> s1("12345"); - s1.insert(2, fixed_string<3>("TUV"), 1); - BOOST_TEST(s1 == "12UV345"); - BOOST_TEST(*s1.end() == 0); - s1 = "12345"; - s1.insert(2, fixed_string<3>("TUV"), 1, 1); - BOOST_TEST(s1 == "12U345"); - BOOST_TEST(*s1.end() == 0); - fixed_string<6> s2("12345"); - BOOST_TEST_THROWS( - (s2.insert(2, fixed_string<3>("TUV"), 1, 2)), - std::length_error); - fixed_string<6> s3("12345"); - BOOST_TEST_THROWS( - (s3.insert(6, fixed_string<3>("TUV"), 1, 2)), - std::out_of_range); - } - { - fixed_string<4> s1("123"); - s1.insert(s1.begin() + 1, '_'); - BOOST_TEST(s1 == "1_23"); - BOOST_TEST(*s1.end() == 0); - fixed_string<3> s2("123"); - BOOST_TEST_THROWS( - (s2.insert(s2.begin() + 1, '_')), - std::length_error); - } - { - fixed_string<4> s1("12"); - s1.insert(s1.begin() + 1, 2, '_'); - BOOST_TEST(s1 == "1__2"); - BOOST_TEST(*s1.end() == 0); - fixed_string<4> s2("123"); - BOOST_TEST_THROWS( - (s2.insert(s2.begin() + 1, 2, ' ')), - std::length_error); - } - { - fixed_string<3> s1("123"); - fixed_string<5> s2("UV"); - s2.insert(s2.begin() + 1, s1.begin(), s1.end()); - BOOST_TEST(s2 == "U123V"); - BOOST_TEST(*s2.end() == 0); - fixed_string<4> s3("UV"); - BOOST_TEST_THROWS( - (s3.insert(s3.begin() + 1, s1.begin(), s1.end())), - std::length_error); - } - { - fixed_string<5> s1("123"); - s1.insert(1, string_view("UV")); - BOOST_TEST(s1 == "1UV23"); - BOOST_TEST(*s1.end() == 0); - fixed_string<4> s2("123"); - BOOST_TEST_THROWS( - (s2.insert(1, string_view("UV"))), - std::length_error); - fixed_string<5> s3("123"); - BOOST_TEST_THROWS( - (s3.insert(5, string_view("UV"))), - std::out_of_range); - } - { - fixed_string<5> s1("123"); - s1.insert(1, std::string("UV")); - BOOST_TEST(s1 == "1UV23"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - (s1.insert(1, std::string("UV"))), - std::length_error); - } - { - fixed_string<6> s1("123"); - s1.insert(1, std::string("UVX"), 1); - BOOST_TEST(s1 == "1VX23"); - BOOST_TEST(*s1.end() == 0); - s1.insert(4, std::string("PQR"), 1, 1); - BOOST_TEST(s1 == "1VX2Q3"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - (s1.insert(4, std::string("PQR"), 1, 1)), - std::length_error); - } - // test insert with source inside self - - { - fixed_string<30> fs1 = "0123456789"; - BOOST_TEST(fs1.insert(0, fs1.data(), 4) == "01230123456789"); - } - { - fixed_string<30> fs1 = "0123456789"; - BOOST_TEST(fs1.insert(5, fs1.data(), 4) == "01234012356789"); - } - { - fixed_string<30> fs1 = "0123456789"; - BOOST_TEST(fs1.insert(5, fs1.data(), 10) == "01234012345678956789"); - } - { - fixed_string<30> fs1 = "0123456789"; - BOOST_TEST(fs1.insert(5, fs1.data() + 6, 3) == "0123467856789"); - } - + BOOST_TEST(s_long == "rem ipsu"); +} + +// done +static +void +testElements() +{ + using cfs3 = fixed_string<3> const; + + // at(size_type pos) + BOOST_TEST(fixed_string<3>{"abc"}.at(0) == 'a'); + BOOST_TEST(fixed_string<3>{"abc"}.at(2) == 'c'); + BOOST_TEST_THROWS(fixed_string<3>{""}.at(0), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.at(4), std::out_of_range); + + // at(size_type pos) const + BOOST_TEST(cfs3{"abc"}.at(0) == 'a'); + BOOST_TEST(cfs3{"abc"}.at(2) == 'c'); + BOOST_TEST_THROWS(cfs3{""}.at(0), std::out_of_range); + BOOST_TEST_THROWS(cfs3{"abc"}.at(4), std::out_of_range); + + // operator[](size_type pos) + BOOST_TEST(fixed_string<3>{"abc"}[0] == 'a'); + BOOST_TEST(fixed_string<3>{"abc"}[2] == 'c'); + BOOST_TEST(fixed_string<3>{"abc"}[3] == 0); + BOOST_TEST(fixed_string<3>{""}[0] == 0); + + // operator[](size_type pos) const + BOOST_TEST(cfs3{"abc"}[0] == 'a'); + BOOST_TEST(cfs3{"abc"}[2] == 'c'); + BOOST_TEST(cfs3{"abc"}[3] == 0); + BOOST_TEST(cfs3{""}[0] == 0); + + // front() + BOOST_TEST(fixed_string<3>{"a"}.front() == 'a'); + BOOST_TEST(fixed_string<3>{"abc"}.front() == 'a'); + + // front() const + BOOST_TEST(cfs3{"a"}.front() == 'a'); + BOOST_TEST(cfs3{"abc"}.front() == 'a'); + + // back() + BOOST_TEST(fixed_string<3>{"a"}.back() == 'a'); + BOOST_TEST(fixed_string<3>{"abc"}.back() == 'c'); + + // back() const + BOOST_TEST(cfs3{"a"}.back() == 'a'); + BOOST_TEST(cfs3{"abc"}.back() == 'c'); + + // data() noexcept + // data() const noexcept + // c_str() const noexcept + // operator string_view_type() const noexcept + + //--- + + { + fixed_string<5> s("12345"); + BOOST_TEST(s.at(1) == '2'); + BOOST_TEST(s.at(4) == '5'); + BOOST_TEST_THROWS( + s.at(5) = 0, + std::out_of_range); + } + { + fixed_string<5> const s("12345"); + BOOST_TEST(s.at(1) == '2'); + BOOST_TEST(s.at(4) == '5'); + BOOST_TEST_THROWS( + s.at(5), + std::out_of_range); + } + { + fixed_string<5> s("12345"); + BOOST_TEST(s[1] == '2'); + BOOST_TEST(s[4] == '5'); + s[1] = '_'; + BOOST_TEST(s == "1_345"); + } + { + fixed_string<5> const s("12345"); + BOOST_TEST(s[1] == '2'); + BOOST_TEST(s[4] == '5'); + BOOST_TEST(s[5] == 0); + } + { + fixed_string<3> s("123"); + BOOST_TEST(s.front() == '1'); + BOOST_TEST(s.back() == '3'); + s.front() = '_'; + BOOST_TEST(s == "_23"); + s.back() = '_'; + BOOST_TEST(s == "_2_"); + } + { + fixed_string<3> const s("123"); + BOOST_TEST(s.front() == '1'); + BOOST_TEST(s.back() == '3'); + } + { + fixed_string<3> s("123"); + BOOST_TEST(std::memcmp( + s.data(), "123", 3) == 0); + } + { + fixed_string<3> const s("123"); + BOOST_TEST(std::memcmp( + s.data(), "123", 3) == 0); + } + { + fixed_string<3> s("123"); + BOOST_TEST(std::memcmp( + s.c_str(), "123\0", 4) == 0); + } + { + fixed_string<3> s("123"); + string_view sv = s; + BOOST_TEST(fixed_string<5>(sv) == "123"); + } +} + +// done +static +void +testIterators() +{ + { + fixed_string<3> s; + BOOST_TEST(std::distance(s.begin(), s.end()) == 0); + BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 0); + s = "123"; + BOOST_TEST(std::distance(s.begin(), s.end()) == 3); + BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 3); + } + { + fixed_string<3> const s("123"); + BOOST_TEST(std::distance(s.begin(), s.end()) == 3); + BOOST_TEST(std::distance(s.cbegin(), s.cend()) == 3); + BOOST_TEST(std::distance(s.rbegin(), s.rend()) == 3); + BOOST_TEST(std::distance(s.crbegin(), s.crend()) == 3); + } +} + +// done +static +void +testCapacity() +{ + // empty() + BOOST_TEST(fixed_string<0>{}.empty()); + BOOST_TEST(fixed_string<1>{}.empty()); + BOOST_TEST(! fixed_string<1>{"a"}.empty()); + BOOST_TEST(! fixed_string<3>{"abc"}.empty()); + + // size() + BOOST_TEST(fixed_string<0>{}.size() == 0); + BOOST_TEST(fixed_string<1>{}.size() == 0); + BOOST_TEST(fixed_string<1>{"a"}.size() == 1); + BOOST_TEST(fixed_string<3>{"abc"}.size() == 3); + BOOST_TEST(fixed_string<5>{"abc"}.size() == 3); + + // length() + BOOST_TEST(fixed_string<0>{}.length() == 0); + BOOST_TEST(fixed_string<1>{}.length() == 0); + BOOST_TEST(fixed_string<1>{"a"}.length() == 1); + BOOST_TEST(fixed_string<3>{"abc"}.length() == 3); + BOOST_TEST(fixed_string<5>{"abc"}.length() == 3); + + // max_size() + BOOST_TEST(fixed_string<0>{}.max_size() == 0); + BOOST_TEST(fixed_string<1>{}.max_size() == 1); + BOOST_TEST(fixed_string<1>{"a"}.max_size() == 1); + BOOST_TEST(fixed_string<3>{"abc"}.max_size() == 3); + BOOST_TEST(fixed_string<5>{"abc"}.max_size() == 5); + + // reserve(std::size_t n) + fixed_string<3>{}.reserve(0); + fixed_string<3>{}.reserve(1); + fixed_string<3>{}.reserve(3); + BOOST_TEST_THROWS(fixed_string<0>{}.reserve(1), std::length_error); + BOOST_TEST_THROWS(fixed_string<3>{}.reserve(4), std::length_error); + + // capacity() + BOOST_TEST(fixed_string<0>{}.capacity() == 0); + BOOST_TEST(fixed_string<1>{}.capacity() == 1); + BOOST_TEST(fixed_string<1>{"a"}.capacity() == 1); + BOOST_TEST(fixed_string<3>{"abc"}.capacity() == 3); + BOOST_TEST(fixed_string<5>{"abc"}.capacity() == 5); + + //--- + + fixed_string<3> s; + BOOST_TEST(s.empty()); + BOOST_TEST(s.size() == 0); + BOOST_TEST(s.length() == 0); + BOOST_TEST(s.max_size() == 3); + BOOST_TEST(s.capacity() == 3); + s = "123"; + BOOST_TEST(! s.empty()); + BOOST_TEST(s.size() == 3); + BOOST_TEST(s.length() == 3); + s.reserve(0); + s.reserve(3); + BOOST_TEST_THROWS( + s.reserve(4), + std::length_error); + s.shrink_to_fit(); + BOOST_TEST(! s.empty()); + BOOST_TEST(s.size() == 3); + BOOST_TEST(s.length() == 3); + BOOST_TEST(*s.end() == 0); +} + +// done +static +void +testClear() +{ + // clear() + fixed_string<3> s("123"); + s.clear(); + BOOST_TEST(s.empty()); + BOOST_TEST(*s.end() == 0); +} + +// done +static +void +testInsert() +{ + using sv = string_view; + using S = fixed_string<100>; + + // insert(size_type index, size_type count, CharT ch) + // The overload resolution is ambiguous + // here because 0 is also a pointer type + //BOOST_TEST(fixed_string<3>{"bc"}.insert(0, 1, 'a') == "abc"); + BOOST_TEST(fixed_string<3>{"bc"}.insert(std::size_t(0), 1, 'a') == "abc"); + BOOST_TEST(fixed_string<3>{"ac"}.insert(1, 1, 'b') == "abc"); + BOOST_TEST(fixed_string<3>{"ab"}.insert(2, 1, 'c') == "abc"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, 1, '*'), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, 1, '*'), std::length_error); + + // insert(size_type index, CharT const* s) + BOOST_TEST(fixed_string<3>{"bc"}.insert(0, "a") == "abc"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, "*"), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, "*"), std::length_error); + + // insert(size_type index, CharT const* s, size_type count) + BOOST_TEST(fixed_string<4>{"ad"}.insert(1, "bcd", 2) == "abcd"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, "*"), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, "*"), std::length_error); + + // insert(size_type index, string_view_type sv) + BOOST_TEST(fixed_string<3>{"ac"}.insert(1, sv{"b"}) == "abc"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, sv{"*"}), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, sv{"*"}), std::length_error); + + // insert(size_type index, string_view_type sv, size_type index_str, size_type count = npos) + BOOST_TEST(fixed_string<4>{"ad"}.insert(1, sv{"abcd"}, 1, 2) == "abcd"); + BOOST_TEST(fixed_string<4>{"ad"}.insert(1, sv{"abc"}, 1) == "abcd"); + BOOST_TEST_THROWS((fixed_string<4>{"ad"}.insert(1, sv{"bc"}, 3, 0)), std::out_of_range); + BOOST_TEST_THROWS((fixed_string<3>{"ad"}.insert(1, sv{"bc"}, 0, 2)), std::length_error); + + // insert(const_iterator pos, CharT ch) + { + fixed_string<3> s{"ac"}; + BOOST_TEST(s.insert(s.begin() + 1, 'b') == s.begin() + 1); + BOOST_TEST(s == "abc"); + BOOST_TEST_THROWS(s.insert(s.begin() + 1, '*'), std::length_error); + } + + // insert(const_iterator pos, size_type count, CharT ch) + { + fixed_string<4> s{"ac"}; + BOOST_TEST(s.insert(s.begin() + 1, 2, 'b') == s.begin() + 1); + BOOST_TEST(s == "abbc"); + BOOST_TEST_THROWS(s.insert(s.begin() + 1, 2, '*'), std::length_error); + } + + // insert(const_iterator pos, InputIt first, InputIt last) + { + fixed_string<4> const cs{"abcd"}; + fixed_string<4> s{"ad"}; + BOOST_TEST(s.insert(s.begin() + 1, cs.begin() + 1, cs.begin() + 3) == s.begin() + 1); + BOOST_TEST(s == "abcd"); + } + + // insert(const_iterator pos, std::initializer_list ilist) + { + fixed_string<4> s{"ad"}; + BOOST_TEST(s.insert(s.begin() + 1, {'b', 'c'}) == s.begin() + 1); + BOOST_TEST(s == "abcd"); + } + + // insert(size_type index, T const& t) + { + struct T + { + operator string_view() const noexcept + { + return "b"; + } + }; + BOOST_TEST(fixed_string<3>{"ac"}.insert(1, T{}) == "abc"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, T{}), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, T{}), std::length_error); + } + + // insert(size_type index, T const& t, size_type index_str, size_type count = npos) + { + struct T + { + operator string_view() const noexcept + { + return "abcd"; + } + }; + BOOST_TEST(fixed_string<6>{"ae"}.insert(1, T{}, 1) == "abcde"); + BOOST_TEST(fixed_string<6>{"abe"}.insert(2, T{}, 2) == "abcde"); + BOOST_TEST(fixed_string<4>{"ac"}.insert(1, T{}, 1, 1) == "abc"); + BOOST_TEST(fixed_string<4>{"ad"}.insert(1, T{}, 1, 2) == "abcd"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.insert(4, T{}), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.insert(1, T{}), std::length_error); + } + + //--- + + { + // Using 7 as the size causes a miscompile in MSVC14.2 x64 Release + fixed_string<8> s1("12345"); + s1.insert(2, 2, '_'); + BOOST_TEST(s1 == "12__345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<6> s2("12345"); + BOOST_TEST_THROWS( + (s2.insert(2, 2, '_')), + std::length_error); + fixed_string<6> s3("12345"); + BOOST_TEST_THROWS( + (s3.insert(6, 2, '_')), + std::out_of_range); + } + { + fixed_string<7> s1("12345"); + s1.insert(2, "__"); + BOOST_TEST(s1 == "12__345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<6> s2("12345"); + BOOST_TEST_THROWS( + (s2.insert(2, "__")), + std::length_error); + fixed_string<6> s3("12345"); + BOOST_TEST_THROWS( + (s2.insert(6, "__")), + std::out_of_range); + } + { + fixed_string<7> s1("12345"); + s1.insert(2, "TUV", 2); + BOOST_TEST(s1 == "12TU345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<6> s2("12345"); + BOOST_TEST_THROWS( + (s2.insert(2, "TUV", 2)), + std::length_error); + fixed_string<6> s3("12345"); + BOOST_TEST_THROWS( + (s3.insert(6, "TUV", 2)), + std::out_of_range); + } + { + fixed_string<7> s1("12345"); + s1.insert(2, fixed_string<3>("TU")); + BOOST_TEST(s1 == "12TU345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<6> s2("12345"); + BOOST_TEST_THROWS( + (s2.insert(2, fixed_string<3>("TUV"))), + std::length_error); + fixed_string<6> s3("12345"); + BOOST_TEST_THROWS( + (s3.insert(6, fixed_string<3>("TUV"))), + std::out_of_range); + } + { + fixed_string<7> s1("12345"); + s1.insert(2, fixed_string<3>("TUV"), 1); + BOOST_TEST(s1 == "12UV345"); + BOOST_TEST(*s1.end() == 0); + s1 = "12345"; + s1.insert(2, fixed_string<3>("TUV"), 1, 1); + BOOST_TEST(s1 == "12U345"); + BOOST_TEST(*s1.end() == 0); + fixed_string<6> s2("12345"); + BOOST_TEST_THROWS( + (s2.insert(2, fixed_string<3>("TUV"), 1, 2)), + std::length_error); + fixed_string<6> s3("12345"); + BOOST_TEST_THROWS( + (s3.insert(6, fixed_string<3>("TUV"), 1, 2)), + std::out_of_range); + } + { + fixed_string<4> s1("123"); + s1.insert(s1.begin() + 1, '_'); + BOOST_TEST(s1 == "1_23"); + BOOST_TEST(*s1.end() == 0); + fixed_string<3> s2("123"); + BOOST_TEST_THROWS( + (s2.insert(s2.begin() + 1, '_')), + std::length_error); + } + { + fixed_string<4> s1("12"); + s1.insert(s1.begin() + 1, 2, '_'); + BOOST_TEST(s1 == "1__2"); + BOOST_TEST(*s1.end() == 0); + fixed_string<4> s2("123"); + BOOST_TEST_THROWS( + (s2.insert(s2.begin() + 1, 2, ' ')), + std::length_error); + } + { + fixed_string<3> s1("123"); + fixed_string<5> s2("UV"); + s2.insert(s2.begin() + 1, s1.begin(), s1.end()); + BOOST_TEST(s2 == "U123V"); + BOOST_TEST(*s2.end() == 0); + fixed_string<4> s3("UV"); + BOOST_TEST_THROWS( + (s3.insert(s3.begin() + 1, s1.begin(), s1.end())), + std::length_error); + } + { + fixed_string<5> s1("123"); + s1.insert(1, string_view("UV")); + BOOST_TEST(s1 == "1UV23"); + BOOST_TEST(*s1.end() == 0); + fixed_string<4> s2("123"); + BOOST_TEST_THROWS( + (s2.insert(1, string_view("UV"))), + std::length_error); + fixed_string<5> s3("123"); + BOOST_TEST_THROWS( + (s3.insert(5, string_view("UV"))), + std::out_of_range); + } + { + fixed_string<5> s1("123"); + s1.insert(1, std::string("UV")); + BOOST_TEST(s1 == "1UV23"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + (s1.insert(1, std::string("UV"))), + std::length_error); + } + { + fixed_string<6> s1("123"); + s1.insert(1, std::string("UVX"), 1); + BOOST_TEST(s1 == "1VX23"); + BOOST_TEST(*s1.end() == 0); + s1.insert(4, std::string("PQR"), 1, 1); + BOOST_TEST(s1 == "1VX2Q3"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + (s1.insert(4, std::string("PQR"), 1, 1)), + std::length_error); + } + // test insert with source inside self + + { + fixed_string<30> fs1 = "0123456789"; + BOOST_TEST(fs1.insert(0, fs1.data(), 4) == "01230123456789"); + } + { + fixed_string<30> fs1 = "0123456789"; + BOOST_TEST(fs1.insert(5, fs1.data(), 4) == "01234012356789"); + } + { + fixed_string<30> fs1 = "0123456789"; + BOOST_TEST(fs1.insert(5, fs1.data(), 10) == "01234012345678956789"); + } + { + fixed_string<30> fs1 = "0123456789"; + BOOST_TEST(fs1.insert(5, fs1.data() + 6, 3) == "0123467856789"); + } + S s_short = "123/"; S s_long = "Lorem ipsum dolor sit amet, consectetur/"; BOOST_TEST(s_short.insert(0, s_short.data(), s_short.size()) == "123/123/"); BOOST_TEST(s_short.insert(0, s_short.data(), s_short.size()) == "123/123/123/123/"); BOOST_TEST(s_short.insert(0, s_short.data(), s_short.size()) == "123/123/123/123/123/123/123/123/"); - BOOST_TEST(s_long.insert(0, s_long.data(), s_long.size()) == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + BOOST_TEST(s_long.insert(0, s_long.data(), s_long.size()) == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); BOOST_TEST(testI(S("abcde"), 6, "12345", 0, S("can't happen"))); BOOST_TEST(testI(S("abcde"), 6, "12345", 1, S("can't happen"))); @@ -1506,7 +1524,7 @@ testInsert() BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 20, "12345678901234567890", 1, S("abcdefghijklmnopqrst1"))); BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 20, "12345678901234567890", 10, S("abcdefghijklmnopqrst1234567890"))); BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 20, "12345678901234567890", 19, S("abcdefghijklmnopqrst1234567890123456789"))); - BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 20, "12345678901234567890", 20, S("abcdefghijklmnopqrst12345678901234567890"))); + BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 20, "12345678901234567890", 20, S("abcdefghijklmnopqrst12345678901234567890"))); BOOST_TEST(testI(S("abcde"), 6, "", 0, S("can't happen"))); BOOST_TEST(testI(S("abcde"), 6, "12345", 0, S("can't happen"))); BOOST_TEST(testI(S("abcde"), 6, "12345", 1, S("can't happen"))); @@ -1554,73 +1572,73 @@ testInsert() BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 1, S("can't happen"))); BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 10, S("can't happen"))); BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 19, S("can't happen"))); - BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"))); -} - -// done -static -void -testErase() -{ - // erase(size_type index = 0, size_type count = npos) - BOOST_TEST(fixed_string<3>{"abc"}.erase() == ""); - BOOST_TEST(fixed_string<3>{"abc"}.erase(1) == "a"); - BOOST_TEST(fixed_string<3>{"abc"}.erase(2) == "ab"); - BOOST_TEST(fixed_string<3>{"abc"}.erase(1, 1) == "ac"); - BOOST_TEST(fixed_string<3>{"abc"}.erase(0, 2) == "c"); - BOOST_TEST(fixed_string<3>{"abc"}.erase(3, 0) == "abc"); - BOOST_TEST(fixed_string<3>{"abc"}.erase(3, 4) == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.erase(4, 0), std::out_of_range); - - // erase(const_iterator pos) - { - fixed_string<3> s{"abc"}; - BOOST_TEST(s.erase(s.begin() + 1) == s.begin() + 1); - BOOST_TEST(s == "ac"); - } - { - fixed_string<3> s{"abc"}; - BOOST_TEST(s.erase(s.begin() + 3) == s.end()); - BOOST_TEST(s == "abc"); - } - - // erase(const_iterator first, const_iterator last) - { - fixed_string<4> s{"abcd"}; - BOOST_TEST(s.erase(s.begin() + 1, s.begin() + 3) == s.begin() + 1); - BOOST_TEST(s == "ad"); - } - - //--- - - { - fixed_string<9> s1("123456789"); - BOOST_TEST(s1.erase(1, 1) == "13456789"); - BOOST_TEST(s1 == "13456789"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST(s1.erase(5) == "13456"); - BOOST_TEST(s1 == "13456"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST_THROWS( - s1.erase(7), - std::out_of_range); - } - { - fixed_string<9> s1("123456789"); - BOOST_TEST(*s1.erase(s1.begin() + 5) == '7'); - BOOST_TEST(s1 == "12345789"); - BOOST_TEST(*s1.end() == 0); - } - { - fixed_string<9> s1("123456789"); - BOOST_TEST(*s1.erase( - s1.begin() + 5, s1.begin() + 7) == '8'); - BOOST_TEST(s1 == "1234589"); - BOOST_TEST(*s1.end() == 0); - } - - using S = fixed_string<400>; - + BOOST_TEST(testI(S("abcdefghijklmnopqrst"), 21, "12345678901234567890", 20, S("can't happen"))); +} + +// done +static +void +testErase() +{ + // erase(size_type index = 0, size_type count = npos) + BOOST_TEST(fixed_string<3>{"abc"}.erase() == ""); + BOOST_TEST(fixed_string<3>{"abc"}.erase(1) == "a"); + BOOST_TEST(fixed_string<3>{"abc"}.erase(2) == "ab"); + BOOST_TEST(fixed_string<3>{"abc"}.erase(1, 1) == "ac"); + BOOST_TEST(fixed_string<3>{"abc"}.erase(0, 2) == "c"); + BOOST_TEST(fixed_string<3>{"abc"}.erase(3, 0) == "abc"); + BOOST_TEST(fixed_string<3>{"abc"}.erase(3, 4) == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.erase(4, 0), std::out_of_range); + + // erase(const_iterator pos) + { + fixed_string<3> s{"abc"}; + BOOST_TEST(s.erase(s.begin() + 1) == s.begin() + 1); + BOOST_TEST(s == "ac"); + } + { + fixed_string<3> s{"abc"}; + BOOST_TEST(s.erase(s.begin() + 3) == s.end()); + BOOST_TEST(s == "abc"); + } + + // erase(const_iterator first, const_iterator last) + { + fixed_string<4> s{"abcd"}; + BOOST_TEST(s.erase(s.begin() + 1, s.begin() + 3) == s.begin() + 1); + BOOST_TEST(s == "ad"); + } + + //--- + + { + fixed_string<9> s1("123456789"); + BOOST_TEST(s1.erase(1, 1) == "13456789"); + BOOST_TEST(s1 == "13456789"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST(s1.erase(5) == "13456"); + BOOST_TEST(s1 == "13456"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST_THROWS( + s1.erase(7), + std::out_of_range); + } + { + fixed_string<9> s1("123456789"); + BOOST_TEST(*s1.erase(s1.begin() + 5) == '7'); + BOOST_TEST(s1 == "12345789"); + BOOST_TEST(*s1.end() == 0); + } + { + fixed_string<9> s1("123456789"); + BOOST_TEST(*s1.erase( + s1.begin() + 5, s1.begin() + 7) == '8'); + BOOST_TEST(s1 == "1234589"); + BOOST_TEST(*s1.end() == 0); + } + + using S = fixed_string<400>; + BOOST_TEST(testE(S(""), 0, 0, S(""))); BOOST_TEST(testE(S(""), 0, 1, S(""))); BOOST_TEST(testE(S(""), 1, 0, S("can't happen"))); @@ -1769,453 +1787,453 @@ testErase() BOOST_TEST(testE(S("abcdefghijklmnopqrst"), 19, 2, S("abcdefghijklmnopqrs"))); BOOST_TEST(testE(S("abcdefghijklmnopqrst"), 20, 0, S("abcdefghijklmnopqrst"))); BOOST_TEST(testE(S("abcdefghijklmnopqrst"), 20, 1, S("abcdefghijklmnopqrst"))); - BOOST_TEST(testE(S("abcdefghijklmnopqrst"), 21, 0, S("can't happen"))); -} + BOOST_TEST(testE(S("abcdefghijklmnopqrst"), 21, 0, S("can't happen"))); +} + +// done +static +void +testPushBack() +{ + // push_back(CharT ch); + { + fixed_string<2> s; + s.push_back('a'); + BOOST_TEST(s == "a"); + s.push_back('b'); + BOOST_TEST(s == "ab"); + BOOST_TEST_THROWS(s.push_back('c'), std::length_error); + } + + //--- + + { + fixed_string<3> s1("12"); + s1.push_back('3'); + BOOST_TEST(s1 == "123"); + BOOST_TEST_THROWS( + s1.push_back('4'), + std::length_error); + fixed_string<0> s2; + BOOST_TEST_THROWS( + s2.push_back('_'), + std::length_error); + } +} + +// done +static +void +testPopBack() +{ + // pop_back() + { + fixed_string<3> s{"abc"}; + BOOST_TEST(*s.end() == 0); + s.pop_back(); + BOOST_TEST(s == "ab"); + BOOST_TEST(*s.end() == 0); + s.pop_back(); + BOOST_TEST(s == "a"); + BOOST_TEST(*s.end() == 0); + s.pop_back(); + BOOST_TEST(s.empty()); + BOOST_TEST(*s.end() == 0); + } + + //--- + + { + fixed_string<3> s1("123"); + s1.pop_back(); + BOOST_TEST(s1 == "12"); + BOOST_TEST(*s1.end() == 0); + s1.pop_back(); + BOOST_TEST(s1 == "1"); + BOOST_TEST(*s1.end() == 0); + s1.pop_back(); + BOOST_TEST(s1.empty()); + BOOST_TEST(*s1.end() == 0); + } +} + +// done +static +void +testAppend() +{ + using S = fixed_string<400>; + using sv = string_view; + + // append(size_type count, CharT ch) + BOOST_TEST(fixed_string<1>{}.append(1, 'a') == "a"); + BOOST_TEST(fixed_string<2>{}.append(2, 'a') == "aa"); + BOOST_TEST(fixed_string<2>{"a"}.append(1, 'b') == "ab"); + BOOST_TEST_THROWS(fixed_string<2>{"ab"}.append(1, 'c'), std::length_error); + + // append(string_view_type sv) + BOOST_TEST(fixed_string<3>{"a"}.append(sv{"bc"}) == "abc"); + BOOST_TEST(fixed_string<3>{"ab"}.append(sv{"c"}) == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"*"}), std::length_error); + + // append(string_view_type sv, size_type pos, size_type count = npos) + BOOST_TEST(fixed_string<3>{"a"}.append(sv{"abc"}, 1) == "abc"); + BOOST_TEST(fixed_string<3>{"a"}.append(sv{"abc"}, 1, 2) == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"a"}, 2, 1), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"abcd"}, 1, 2), std::length_error); + + // append(CharT const* s, size_type count) + BOOST_TEST(fixed_string<3>{"a"}.append("bc", 0) == "a"); + BOOST_TEST(fixed_string<3>{"a"}.append("bc", 2) == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append("bc", 2), std::length_error); + + // append(CharT const* s) + BOOST_TEST(fixed_string<3>{"a"}.append("bc") == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append("bc"), std::length_error); + + // append(InputIt first, InputIt last) + { + fixed_string<4> const cs{"abcd"}; + fixed_string<4> s{"ad"}; + BOOST_TEST(fixed_string<4>{"ab"}.append( + cs.begin() + 2, cs.begin() + 4) == "abcd"); + BOOST_TEST_THROWS(fixed_string<2>{"ab"}.append( + cs.begin() + 2, cs.begin() + 4), std::length_error); + } + + // append(std::initializer_list ilist) + BOOST_TEST(fixed_string<4>{"ab"}.append({'c', 'd'}) == "abcd"); + BOOST_TEST_THROWS(fixed_string<3>{"ab"}.append({'c', 'd'}), std::length_error); + + // append(T const& t) + { + struct T + { + operator string_view() const noexcept + { + return "c"; + } + }; + BOOST_TEST(fixed_string<3>{"ab"}.append(T{}) == "abc"); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(T{}), std::length_error); + } + + // append(T const& t, size_type pos, size_type count = npos) + { + struct T + { + operator string_view() const noexcept + { + return "abcd"; + } + }; + BOOST_TEST(fixed_string<4>{"ab"}.append(T{}, 2) == "abcd"); + BOOST_TEST(fixed_string<3>{"a"}.append(T{}, 1, 2) == "abc"); + BOOST_TEST_THROWS(fixed_string<4>{"abc"}.append(T{}, 5), std::out_of_range); + BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(T{}, 3, 1), std::length_error); + } + + //--- + + { + fixed_string<3> s1("1"); + s1.append(2, '_'); + BOOST_TEST(s1 == "1__"); + BOOST_TEST(*s1.end() == 0); + fixed_string<2> s2("1"); + BOOST_TEST_THROWS( + (s2.append(2, '_')), + std::length_error); + } + { + fixed_string<2> s1("__"); + fixed_string<3> s2("1"); + s2.append(s1); + BOOST_TEST(s2 == "1__"); + BOOST_TEST(*s2.end() == 0); + fixed_string<2> s3("1"); + BOOST_TEST_THROWS( + s3.append(s1), + std::length_error); + } + { + fixed_string<3> s1("XYZ"); + fixed_string<4> s2("12"); + s2.append(s1, 1); + BOOST_TEST(s2 == "12YZ"); + BOOST_TEST(*s2.end() == 0); + fixed_string<3> s3("12"); + s3.append(s1, 1, 1); + BOOST_TEST(s3 == "12Y"); + BOOST_TEST(*s3.end() == 0); + fixed_string<3> s4("12"); + BOOST_TEST_THROWS( + (s4.append(s1, 4)), + std::out_of_range); + fixed_string<3> s5("12"); + BOOST_TEST_THROWS( + (s5.append(s1, 1)), + std::length_error); + } + { + fixed_string<4> s1("12"); + s1.append("XYZ", 2); + BOOST_TEST(s1 == "12XY"); + BOOST_TEST(*s1.end() == 0); + fixed_string<3> s3("12"); + BOOST_TEST_THROWS( + (s3.append("XYZ", 2)), + std::length_error); + } + { + fixed_string<5> s1("12"); + s1.append("XYZ"); + BOOST_TEST(s1 == "12XYZ"); + BOOST_TEST(*s1.end() == 0); + fixed_string<4> s2("12"); + BOOST_TEST_THROWS( + s2.append("XYZ"), + std::length_error); + } + { + fixed_string<3> s1("XYZ"); + fixed_string<5> s2("12"); + s2.append(s1.begin(), s1.end()); + BOOST_TEST(s2 == "12XYZ"); + BOOST_TEST(*s2.end() == 0); + fixed_string<4> s3("12"); + BOOST_TEST_THROWS( + s3.append(s1.begin(), s1.end()), + std::length_error); + } + { + fixed_string<5> s1("123"); + s1.append({'X', 'Y'}); + BOOST_TEST(s1 == "123XY"); + BOOST_TEST(*s1.end() == 0); + fixed_string<4> s2("123"); + BOOST_TEST_THROWS( + s2.append({'X', 'Y'}), + std::length_error); + } + { + string_view s1("XYZ"); + fixed_string<5> s2("12"); + s2.append(s1); + BOOST_TEST(s2 == "12XYZ"); + BOOST_TEST(*s2.end() == 0); + fixed_string<4> s3("12"); + BOOST_TEST_THROWS( + s3.append(s1), + std::length_error); + } + { + fixed_string<6> s1("123"); + s1.append(std::string("UVX"), 1); + BOOST_TEST(s1 == "123VX"); + BOOST_TEST(*s1.end() == 0); + s1.append(std::string("PQR"), 1, 1); + BOOST_TEST(s1 == "123VXQ"); + BOOST_TEST(*s1.end() == 0); + fixed_string<3> s2("123"); + BOOST_TEST_THROWS( + (s2.append(std::string("PQR"), 1, 1)), + std::length_error); + } + BOOST_TEST(testA(S(), "", 0, S())); + BOOST_TEST(testA(S(), "12345", 3, S("123"))); + BOOST_TEST(testA(S(), "12345", 4, S("1234"))); + BOOST_TEST(testA(S(), "12345678901234567890", 0, S())); + BOOST_TEST(testA(S(), "12345678901234567890", 1, S("1"))); + BOOST_TEST(testA(S(), "12345678901234567890", 3, S("123"))); + BOOST_TEST(testA(S(), "12345678901234567890", 20, S("12345678901234567890"))); -// done -static -void -testPushBack() -{ - // push_back(CharT ch); - { - fixed_string<2> s; - s.push_back('a'); - BOOST_TEST(s == "a"); - s.push_back('b'); - BOOST_TEST(s == "ab"); - BOOST_TEST_THROWS(s.push_back('c'), std::length_error); - } + BOOST_TEST(testA(S("12345"), "", 0, S("12345"))); + BOOST_TEST(testA(S("12345"), "12345", 5, S("1234512345"))); + BOOST_TEST(testA(S("12345"), "1234567890", 10, S("123451234567890"))); - //--- + BOOST_TEST(testA(S("12345678901234567890"), "", 0, S("12345678901234567890"))); + BOOST_TEST(testA(S("12345678901234567890"), "12345", 5, S("1234567890123456789012345"))); + BOOST_TEST(testA(S("12345678901234567890"), "12345678901234567890", 20, + S("1234567890123456789012345678901234567890"))); + + S s_short = "123/"; + S s_long = "Lorem ipsum dolor sit amet, consectetur/"; - { - fixed_string<3> s1("12"); - s1.push_back('3'); - BOOST_TEST(s1 == "123"); - BOOST_TEST_THROWS( - s1.push_back('4'), - std::length_error); - fixed_string<0> s2; - BOOST_TEST_THROWS( - s2.push_back('_'), - std::length_error); - } -} - -// done -static -void -testPopBack() -{ - // pop_back() - { - fixed_string<3> s{"abc"}; - BOOST_TEST(*s.end() == 0); - s.pop_back(); - BOOST_TEST(s == "ab"); - BOOST_TEST(*s.end() == 0); - s.pop_back(); - BOOST_TEST(s == "a"); - BOOST_TEST(*s.end() == 0); - s.pop_back(); - BOOST_TEST(s.empty()); - BOOST_TEST(*s.end() == 0); - } - - //--- - - { - fixed_string<3> s1("123"); - s1.pop_back(); - BOOST_TEST(s1 == "12"); - BOOST_TEST(*s1.end() == 0); - s1.pop_back(); - BOOST_TEST(s1 == "1"); - BOOST_TEST(*s1.end() == 0); - s1.pop_back(); - BOOST_TEST(s1.empty()); - BOOST_TEST(*s1.end() == 0); - } -} - -// done -static -void -testAppend() -{ - using S = fixed_string<400>; - using sv = string_view; - - // append(size_type count, CharT ch) - BOOST_TEST(fixed_string<1>{}.append(1, 'a') == "a"); - BOOST_TEST(fixed_string<2>{}.append(2, 'a') == "aa"); - BOOST_TEST(fixed_string<2>{"a"}.append(1, 'b') == "ab"); - BOOST_TEST_THROWS(fixed_string<2>{"ab"}.append(1, 'c'), std::length_error); - - // append(string_view_type sv) - BOOST_TEST(fixed_string<3>{"a"}.append(sv{"bc"}) == "abc"); - BOOST_TEST(fixed_string<3>{"ab"}.append(sv{"c"}) == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"*"}), std::length_error); - - // append(string_view_type sv, size_type pos, size_type count = npos) - BOOST_TEST(fixed_string<3>{"a"}.append(sv{"abc"}, 1) == "abc"); - BOOST_TEST(fixed_string<3>{"a"}.append(sv{"abc"}, 1, 2) == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"a"}, 2, 1), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(sv{"abcd"}, 1, 2), std::length_error); - - // append(CharT const* s, size_type count) - BOOST_TEST(fixed_string<3>{"a"}.append("bc", 0) == "a"); - BOOST_TEST(fixed_string<3>{"a"}.append("bc", 2) == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append("bc", 2), std::length_error); - - // append(CharT const* s) - BOOST_TEST(fixed_string<3>{"a"}.append("bc") == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append("bc"), std::length_error); - - // append(InputIt first, InputIt last) - { - fixed_string<4> const cs{"abcd"}; - fixed_string<4> s{"ad"}; - BOOST_TEST(fixed_string<4>{"ab"}.append( - cs.begin() + 2, cs.begin() + 4) == "abcd"); - BOOST_TEST_THROWS(fixed_string<2>{"ab"}.append( - cs.begin() + 2, cs.begin() + 4), std::length_error); - } - - // append(std::initializer_list ilist) - BOOST_TEST(fixed_string<4>{"ab"}.append({'c', 'd'}) == "abcd"); - BOOST_TEST_THROWS(fixed_string<3>{"ab"}.append({'c', 'd'}), std::length_error); - - // append(T const& t) - { - struct T - { - operator string_view() const noexcept - { - return "c"; - } - }; - BOOST_TEST(fixed_string<3>{"ab"}.append(T{}) == "abc"); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(T{}), std::length_error); - } - - // append(T const& t, size_type pos, size_type count = npos) - { - struct T - { - operator string_view() const noexcept - { - return "abcd"; - } - }; - BOOST_TEST(fixed_string<4>{"ab"}.append(T{}, 2) == "abcd"); - BOOST_TEST(fixed_string<3>{"a"}.append(T{}, 1, 2) == "abc"); - BOOST_TEST_THROWS(fixed_string<4>{"abc"}.append(T{}, 5), std::out_of_range); - BOOST_TEST_THROWS(fixed_string<3>{"abc"}.append(T{}, 3, 1), std::length_error); - } - - //--- - - { - fixed_string<3> s1("1"); - s1.append(2, '_'); - BOOST_TEST(s1 == "1__"); - BOOST_TEST(*s1.end() == 0); - fixed_string<2> s2("1"); - BOOST_TEST_THROWS( - (s2.append(2, '_')), - std::length_error); - } - { - fixed_string<2> s1("__"); - fixed_string<3> s2("1"); - s2.append(s1); - BOOST_TEST(s2 == "1__"); - BOOST_TEST(*s2.end() == 0); - fixed_string<2> s3("1"); - BOOST_TEST_THROWS( - s3.append(s1), - std::length_error); - } - { - fixed_string<3> s1("XYZ"); - fixed_string<4> s2("12"); - s2.append(s1, 1); - BOOST_TEST(s2 == "12YZ"); - BOOST_TEST(*s2.end() == 0); - fixed_string<3> s3("12"); - s3.append(s1, 1, 1); - BOOST_TEST(s3 == "12Y"); - BOOST_TEST(*s3.end() == 0); - fixed_string<3> s4("12"); - BOOST_TEST_THROWS( - (s4.append(s1, 4)), - std::out_of_range); - fixed_string<3> s5("12"); - BOOST_TEST_THROWS( - (s5.append(s1, 1)), - std::length_error); - } - { - fixed_string<4> s1("12"); - s1.append("XYZ", 2); - BOOST_TEST(s1 == "12XY"); - BOOST_TEST(*s1.end() == 0); - fixed_string<3> s3("12"); - BOOST_TEST_THROWS( - (s3.append("XYZ", 2)), - std::length_error); - } - { - fixed_string<5> s1("12"); - s1.append("XYZ"); - BOOST_TEST(s1 == "12XYZ"); - BOOST_TEST(*s1.end() == 0); - fixed_string<4> s2("12"); - BOOST_TEST_THROWS( - s2.append("XYZ"), - std::length_error); - } - { - fixed_string<3> s1("XYZ"); - fixed_string<5> s2("12"); - s2.append(s1.begin(), s1.end()); - BOOST_TEST(s2 == "12XYZ"); - BOOST_TEST(*s2.end() == 0); - fixed_string<4> s3("12"); - BOOST_TEST_THROWS( - s3.append(s1.begin(), s1.end()), - std::length_error); - } - { - fixed_string<5> s1("123"); - s1.append({'X', 'Y'}); - BOOST_TEST(s1 == "123XY"); - BOOST_TEST(*s1.end() == 0); - fixed_string<4> s2("123"); - BOOST_TEST_THROWS( - s2.append({'X', 'Y'}), - std::length_error); - } - { - string_view s1("XYZ"); - fixed_string<5> s2("12"); - s2.append(s1); - BOOST_TEST(s2 == "12XYZ"); - BOOST_TEST(*s2.end() == 0); - fixed_string<4> s3("12"); - BOOST_TEST_THROWS( - s3.append(s1), - std::length_error); - } - { - fixed_string<6> s1("123"); - s1.append(std::string("UVX"), 1); - BOOST_TEST(s1 == "123VX"); - BOOST_TEST(*s1.end() == 0); - s1.append(std::string("PQR"), 1, 1); - BOOST_TEST(s1 == "123VXQ"); - BOOST_TEST(*s1.end() == 0); - fixed_string<3> s2("123"); - BOOST_TEST_THROWS( - (s2.append(std::string("PQR"), 1, 1)), - std::length_error); - } - BOOST_TEST(testA(S(), "", 0, S())); - BOOST_TEST(testA(S(), "12345", 3, S("123"))); - BOOST_TEST(testA(S(), "12345", 4, S("1234"))); - BOOST_TEST(testA(S(), "12345678901234567890", 0, S())); - BOOST_TEST(testA(S(), "12345678901234567890", 1, S("1"))); - BOOST_TEST(testA(S(), "12345678901234567890", 3, S("123"))); - BOOST_TEST(testA(S(), "12345678901234567890", 20, S("12345678901234567890"))); - - BOOST_TEST(testA(S("12345"), "", 0, S("12345"))); - BOOST_TEST(testA(S("12345"), "12345", 5, S("1234512345"))); - BOOST_TEST(testA(S("12345"), "1234567890", 10, S("123451234567890"))); - - BOOST_TEST(testA(S("12345678901234567890"), "", 0, S("12345678901234567890"))); - BOOST_TEST(testA(S("12345678901234567890"), "12345", 5, S("1234567890123456789012345"))); - BOOST_TEST(testA(S("12345678901234567890"), "12345678901234567890", 20, - S("1234567890123456789012345678901234567890"))); - - S s_short = "123/"; - S s_long = "Lorem ipsum dolor sit amet, consectetur/"; - - s_short.append(s_short.data(), s_short.size()); - BOOST_TEST(s_short == "123/123/"); - s_short.append(s_short.data(), s_short.size()); - BOOST_TEST(s_short == "123/123/123/123/"); - s_short.append(s_short.data(), s_short.size()); - BOOST_TEST(s_short == "123/123/123/123/123/123/123/123/"); -} - -// done -static -void -testPlusEquals() -{ - using sv = string_view; - - // operator+=(CharT ch) - BOOST_TEST((fixed_string<3>{"ab"} += 'c') == "abc"); - BOOST_TEST_THROWS((fixed_string<3>{"abc"} += '*'), std::length_error); - - // operator+=(CharT const* s) - BOOST_TEST((fixed_string<3>{"a"} += "bc") == "abc"); - BOOST_TEST_THROWS((fixed_string<3>{"abc"} += "*"), std::length_error); - - // operator+=(std::initializer_list init) - BOOST_TEST((fixed_string<3>{"a"} += {'b', 'c'}) == "abc"); - BOOST_TEST_THROWS((fixed_string<3>{"abc"} += {'*', '*'}), std::length_error); - - // operator+=(string_view_type const& s) - BOOST_TEST((fixed_string<3>{"a"} += sv{"bc"}) == "abc"); - BOOST_TEST_THROWS((fixed_string<3>{"abc"} += sv{"*"}), std::length_error); - - //--- - - { - fixed_string<2> s1("__"); - fixed_string<3> s2("1"); - s2 += s1; - BOOST_TEST(s2 == "1__"); - BOOST_TEST(*s2.end() == 0); - fixed_string<2> s3("1"); - BOOST_TEST_THROWS( - s3 += s1, - std::length_error); - } - { - fixed_string<3> s1("12"); - s1 += '3'; - BOOST_TEST(s1 == "123"); - BOOST_TEST_THROWS( - s1 += '4', - std::length_error); - } - { - fixed_string<4> s1("12"); - s1 += "34"; - BOOST_TEST(s1 == "1234"); - BOOST_TEST_THROWS( - s1 += "5", - std::length_error); - } - { - fixed_string<4> s1("12"); - s1 += {'3', '4'}; - BOOST_TEST(s1 == "1234"); - BOOST_TEST_THROWS( - (s1 += {'5'}), - std::length_error); - } - { - string_view s1("34"); - fixed_string<4> s2("12"); - s2 += s1; - BOOST_TEST(s2 == "1234"); - BOOST_TEST_THROWS( - s2 += s1, - std::length_error); - } -} - -// done -void -testCompare() -{ - using str1 = fixed_string<1>; - using str2 = fixed_string<2>; - { - str1 s1; - str2 s2; - s1 = "1"; - s2 = "22"; - BOOST_TEST(s1.compare(s2) < 0); - BOOST_TEST(s2.compare(s1) > 0); - BOOST_TEST(s1 < "10"); - BOOST_TEST(s2 > "1"); - BOOST_TEST("10" > s1); - BOOST_TEST("1" < s2); - BOOST_TEST(s1 < "20"); - BOOST_TEST(s2 > "1"); - BOOST_TEST(s2 > "2"); - } - { - str2 s1("x"); - str2 s2("x"); - BOOST_TEST(s1 == s2); - BOOST_TEST(s1 <= s2); - BOOST_TEST(s1 >= s2); - BOOST_TEST(! (s1 < s2)); - BOOST_TEST(! (s1 > s2)); - BOOST_TEST(! (s1 != s2)); - } - { - str1 s1("x"); - str2 s2("x"); - BOOST_TEST(s1 == s2); - BOOST_TEST(s1 <= s2); - BOOST_TEST(s1 >= s2); - BOOST_TEST(! (s1 < s2)); - BOOST_TEST(! (s1 > s2)); - BOOST_TEST(! (s1 != s2)); - } - { - str2 s("x"); - BOOST_TEST(s == "x"); - BOOST_TEST(s <= "x"); - BOOST_TEST(s >= "x"); - BOOST_TEST(! (s < "x")); - BOOST_TEST(! (s > "x")); - BOOST_TEST(! (s != "x")); - BOOST_TEST("x" == s); - BOOST_TEST("x" <= s); - BOOST_TEST("x" >= s); - BOOST_TEST(! ("x" < s)); - BOOST_TEST(! ("x" > s)); - BOOST_TEST(! ("x" != s)); - } - { - str2 s("x"); - BOOST_TEST(s <= "y"); - BOOST_TEST(s < "y"); - BOOST_TEST(s != "y"); - BOOST_TEST(! (s == "y")); - BOOST_TEST(! (s >= "y")); - BOOST_TEST(! (s > "x")); - BOOST_TEST("y" >= s); - BOOST_TEST("y" > s); - BOOST_TEST("y" != s); - BOOST_TEST(! ("y" == s)); - BOOST_TEST(! ("y" <= s)); - BOOST_TEST(! ("y" < s)); - } - { - str1 s1("x"); - str2 s2("y"); - BOOST_TEST(s1 <= s2); - BOOST_TEST(s1 < s2); - BOOST_TEST(s1 != s2); - BOOST_TEST(! (s1 == s2)); - BOOST_TEST(! (s1 >= s2)); - BOOST_TEST(! (s1 > s2)); - } - { - str1 s1("x"); - str2 s2("xx"); - BOOST_TEST(s1 < s2); - BOOST_TEST(s2 > s1); - } - { - str1 s1("x"); - str2 s2("yy"); - BOOST_TEST(s1 < s2); - BOOST_TEST(s2 > s1); - } - - using S = fixed_string<400>; + s_short.append(s_short.data(), s_short.size()); + BOOST_TEST(s_short == "123/123/"); + s_short.append(s_short.data(), s_short.size()); + BOOST_TEST(s_short == "123/123/123/123/"); + s_short.append(s_short.data(), s_short.size()); + BOOST_TEST(s_short == "123/123/123/123/123/123/123/123/"); +} + +// done +static +void +testPlusEquals() +{ + using sv = string_view; + + // operator+=(CharT ch) + BOOST_TEST((fixed_string<3>{"ab"} += 'c') == "abc"); + BOOST_TEST_THROWS((fixed_string<3>{"abc"} += '*'), std::length_error); + + // operator+=(CharT const* s) + BOOST_TEST((fixed_string<3>{"a"} += "bc") == "abc"); + BOOST_TEST_THROWS((fixed_string<3>{"abc"} += "*"), std::length_error); + + // operator+=(std::initializer_list init) + BOOST_TEST((fixed_string<3>{"a"} += {'b', 'c'}) == "abc"); + BOOST_TEST_THROWS((fixed_string<3>{"abc"} += {'*', '*'}), std::length_error); + + // operator+=(string_view_type const& s) + BOOST_TEST((fixed_string<3>{"a"} += sv{"bc"}) == "abc"); + BOOST_TEST_THROWS((fixed_string<3>{"abc"} += sv{"*"}), std::length_error); + + //--- + + { + fixed_string<2> s1("__"); + fixed_string<3> s2("1"); + s2 += s1; + BOOST_TEST(s2 == "1__"); + BOOST_TEST(*s2.end() == 0); + fixed_string<2> s3("1"); + BOOST_TEST_THROWS( + s3 += s1, + std::length_error); + } + { + fixed_string<3> s1("12"); + s1 += '3'; + BOOST_TEST(s1 == "123"); + BOOST_TEST_THROWS( + s1 += '4', + std::length_error); + } + { + fixed_string<4> s1("12"); + s1 += "34"; + BOOST_TEST(s1 == "1234"); + BOOST_TEST_THROWS( + s1 += "5", + std::length_error); + } + { + fixed_string<4> s1("12"); + s1 += {'3', '4'}; + BOOST_TEST(s1 == "1234"); + BOOST_TEST_THROWS( + (s1 += {'5'}), + std::length_error); + } + { + string_view s1("34"); + fixed_string<4> s2("12"); + s2 += s1; + BOOST_TEST(s2 == "1234"); + BOOST_TEST_THROWS( + s2 += s1, + std::length_error); + } +} + +// done +void +testCompare() +{ + using str1 = fixed_string<1>; + using str2 = fixed_string<2>; + { + str1 s1; + str2 s2; + s1 = "1"; + s2 = "22"; + BOOST_TEST(s1.compare(s2) < 0); + BOOST_TEST(s2.compare(s1) > 0); + BOOST_TEST(s1 < "10"); + BOOST_TEST(s2 > "1"); + BOOST_TEST("10" > s1); + BOOST_TEST("1" < s2); + BOOST_TEST(s1 < "20"); + BOOST_TEST(s2 > "1"); + BOOST_TEST(s2 > "2"); + } + { + str2 s1("x"); + str2 s2("x"); + BOOST_TEST(s1 == s2); + BOOST_TEST(s1 <= s2); + BOOST_TEST(s1 >= s2); + BOOST_TEST(! (s1 < s2)); + BOOST_TEST(! (s1 > s2)); + BOOST_TEST(! (s1 != s2)); + } + { + str1 s1("x"); + str2 s2("x"); + BOOST_TEST(s1 == s2); + BOOST_TEST(s1 <= s2); + BOOST_TEST(s1 >= s2); + BOOST_TEST(! (s1 < s2)); + BOOST_TEST(! (s1 > s2)); + BOOST_TEST(! (s1 != s2)); + } + { + str2 s("x"); + BOOST_TEST(s == "x"); + BOOST_TEST(s <= "x"); + BOOST_TEST(s >= "x"); + BOOST_TEST(! (s < "x")); + BOOST_TEST(! (s > "x")); + BOOST_TEST(! (s != "x")); + BOOST_TEST("x" == s); + BOOST_TEST("x" <= s); + BOOST_TEST("x" >= s); + BOOST_TEST(! ("x" < s)); + BOOST_TEST(! ("x" > s)); + BOOST_TEST(! ("x" != s)); + } + { + str2 s("x"); + BOOST_TEST(s <= "y"); + BOOST_TEST(s < "y"); + BOOST_TEST(s != "y"); + BOOST_TEST(! (s == "y")); + BOOST_TEST(! (s >= "y")); + BOOST_TEST(! (s > "x")); + BOOST_TEST("y" >= s); + BOOST_TEST("y" > s); + BOOST_TEST("y" != s); + BOOST_TEST(! ("y" == s)); + BOOST_TEST(! ("y" <= s)); + BOOST_TEST(! ("y" < s)); + } + { + str1 s1("x"); + str2 s2("y"); + BOOST_TEST(s1 <= s2); + BOOST_TEST(s1 < s2); + BOOST_TEST(s1 != s2); + BOOST_TEST(! (s1 == s2)); + BOOST_TEST(! (s1 >= s2)); + BOOST_TEST(! (s1 > s2)); + } + { + str1 s1("x"); + str2 s2("xx"); + BOOST_TEST(s1 < s2); + BOOST_TEST(s2 > s1); + } + { + str1 s1("x"); + str2 s2("yy"); + BOOST_TEST(s1 < s2); + BOOST_TEST(s2 > s1); + } + + using S = fixed_string<400>; BOOST_TEST(testC(S(""), 0, 0, "", 0, 0)); BOOST_TEST(testC(S(""), 0, 0, "abcde", 0, 0)); BOOST_TEST(testC(S(""), 0, 0, "abcde", 1, -1)); @@ -3399,225 +3417,225 @@ testCompare() BOOST_TEST(testC(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 1, 0)); BOOST_TEST(testC(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 10, 0)); BOOST_TEST(testC(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 19, 0)); - BOOST_TEST(testC(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 20, 0)); -} - -// done -void -testSwap() -{ - { - fixed_string<3> s1("123"); - fixed_string<3> s2("XYZ"); - swap(s1, s2); - BOOST_TEST(s1 == "XYZ"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST(s2 == "123"); - BOOST_TEST(*s2.end() == 0); - fixed_string<3> s3("UV"); - swap(s2, s3); - BOOST_TEST(s2 == "UV"); - BOOST_TEST(*s2.end() == 0); - BOOST_TEST(s3 == "123"); - BOOST_TEST(*s3.end() == 0); - } - { - fixed_string<5> s1("123"); - fixed_string<7> s2("XYZ"); - swap(s1, s2); - BOOST_TEST(s1 == "XYZ"); - BOOST_TEST(*s1.end() == 0); - BOOST_TEST(s2 == "123"); - BOOST_TEST(*s2.end() == 0); - fixed_string<3> s3("UV"); - swap(s2, s3); - BOOST_TEST(s2 == "UV"); - BOOST_TEST(*s2.end() == 0); - BOOST_TEST(s3 == "123"); - BOOST_TEST(*s3.end() == 0); - { - fixed_string<5> s4("12345"); - fixed_string<3> s5("XYZ"); - BOOST_TEST_THROWS( - (swap(s4, s5)), - std::length_error); - } - { - fixed_string<3> s4("XYZ"); - fixed_string<5> s5("12345"); - BOOST_TEST_THROWS( - (swap(s4, s5)), - std::length_error); - } - } -} - -void -testGeneral() -{ - using str1 = fixed_string<1>; - using str2 = fixed_string<2>; - { - str1 s1; - BOOST_TEST(s1 == ""); - BOOST_TEST(s1.empty()); - BOOST_TEST(s1.size() == 0); - BOOST_TEST(s1.max_size() == 1); - BOOST_TEST(s1.capacity() == 1); - BOOST_TEST(s1.begin() == s1.end()); - BOOST_TEST(s1.cbegin() == s1.cend()); - BOOST_TEST(s1.rbegin() == s1.rend()); - BOOST_TEST(s1.crbegin() == s1.crend()); - BOOST_TEST_THROWS( - s1.at(0), - std::out_of_range); - BOOST_TEST(s1.data()[0] == 0); - BOOST_TEST(*s1.c_str() == 0); - BOOST_TEST(std::distance(s1.begin(), s1.end()) == 0); - BOOST_TEST(std::distance(s1.cbegin(), s1.cend()) == 0); - BOOST_TEST(std::distance(s1.rbegin(), s1.rend()) == 0); - BOOST_TEST(std::distance(s1.crbegin(), s1.crend()) == 0); - BOOST_TEST(s1.compare(s1) == 0); - } - { - str1 const s1; - BOOST_TEST(s1 == ""); - BOOST_TEST(s1.empty()); - BOOST_TEST(s1.size() == 0); - BOOST_TEST(s1.max_size() == 1); - BOOST_TEST(s1.capacity() == 1); - BOOST_TEST(s1.begin() == s1.end()); - BOOST_TEST(s1.cbegin() == s1.cend()); - BOOST_TEST(s1.rbegin() == s1.rend()); - BOOST_TEST(s1.crbegin() == s1.crend()); - BOOST_TEST_THROWS( - s1.at(0), - std::out_of_range); - BOOST_TEST(s1.data()[0] == 0); - BOOST_TEST(*s1.c_str() == 0); - BOOST_TEST(std::distance(s1.begin(), s1.end()) == 0); - BOOST_TEST(std::distance(s1.cbegin(), s1.cend()) == 0); - BOOST_TEST(std::distance(s1.rbegin(), s1.rend()) == 0); - BOOST_TEST(std::distance(s1.crbegin(), s1.crend()) == 0); - BOOST_TEST(s1.compare(s1) == 0); - } - { - str1 s1; - str1 s2("x"); - BOOST_TEST(s2 == "x"); - BOOST_TEST(s2[0] == 'x'); - BOOST_TEST(s2.at(0) == 'x'); - BOOST_TEST(s2.front() == 'x'); - BOOST_TEST(s2.back() == 'x'); - str1 const s3(s2); - BOOST_TEST(s3 == "x"); - BOOST_TEST(s3[0] == 'x'); - BOOST_TEST(s3.at(0) == 'x'); - BOOST_TEST(s3.front() == 'x'); - BOOST_TEST(s3.back() == 'x'); - s2 = "y"; - BOOST_TEST(s2 == "y"); - BOOST_TEST(s3 == "x"); - s1 = s2; - BOOST_TEST(s1 == "y"); - s1.clear(); - BOOST_TEST(s1.empty()); - BOOST_TEST(s1.size() == 0); - } - { - str2 s1("x"); - str1 s2(s1); - BOOST_TEST(s2 == "x"); - str1 s3; - s3 = s2; - BOOST_TEST(s3 == "x"); - s1 = "xy"; - BOOST_TEST(s1.size() == 2); - BOOST_TEST(s1[0] == 'x'); - BOOST_TEST(s1[1] == 'y'); - BOOST_TEST(s1.at(0) == 'x'); - BOOST_TEST(s1.at(1) == 'y'); - BOOST_TEST(s1.front() == 'x'); - BOOST_TEST(s1.back() == 'y'); - auto const s4 = s1; - BOOST_TEST(s4[0] == 'x'); - BOOST_TEST(s4[1] == 'y'); - BOOST_TEST(s4.at(0) == 'x'); - BOOST_TEST(s4.at(1) == 'y'); - BOOST_TEST(s4.front() == 'x'); - BOOST_TEST(s4.back() == 'y'); - BOOST_TEST_THROWS( - s3 = s1, - std::length_error); - BOOST_TEST_THROWS( - str1{s1}, - std::length_error); - } - { - str1 s1("x"); - str2 s2; - s2 = s1; - BOOST_TEST_THROWS( - s1.resize(2), - std::length_error); - } -} - -// done -void -testToStaticString() -{ - BOOST_TEST(to_fixed_string(0) == "0"); - BOOST_TEST(to_fixed_string(1) == "1"); - BOOST_TEST(to_fixed_string(0xffff) == "65535"); - BOOST_TEST(to_fixed_string(0x10000) == "65536"); - BOOST_TEST(to_fixed_string(0xffffffff) == "4294967295"); - - BOOST_TEST(to_fixed_string(-1) == "-1"); - BOOST_TEST(to_fixed_string(-65535) == "-65535"); - BOOST_TEST(to_fixed_string(-65536) == "-65536"); - BOOST_TEST(to_fixed_string(-4294967295ll) == "-4294967295"); - - BOOST_TEST(to_fixed_string(0) == "0"); - BOOST_TEST(to_fixed_string(1) == "1"); - BOOST_TEST(to_fixed_string(0xffff) == "65535"); - BOOST_TEST(to_fixed_string(0x10000) == "65536"); - BOOST_TEST(to_fixed_string(0xffffffff) == "4294967295"); -} - -// done -void -testFind() -{ - const char* cs1 = "12345"; - const char* cs2 = "2345"; - string_view v1 = cs1; - string_view v2 = cs2; - fixed_string<5> fs1 = cs1; - fixed_string<4> fs2 = cs2; - using S = fixed_string<400>; - - - // find - BOOST_TEST(fs1.find(v1) == 0); - BOOST_TEST(fs1.find(v2) == 1); - BOOST_TEST(fs1.find(fs1) == 0); - BOOST_TEST(fs1.find(fs2) == 1); - - BOOST_TEST(fs1.find(cs1) == 0); - BOOST_TEST(fs1.find(cs2) == 1); - - BOOST_TEST(fs1.find(cs1, 0) == 0); - BOOST_TEST(fs1.find(cs2, 0) == 1); - - BOOST_TEST(fs1.find(cs2, 0, 2) == 1); - - BOOST_TEST(fs1.find(cs1, 4) == -1); - BOOST_TEST(fs1.find(cs2, 4) == -1); - - BOOST_TEST(fs1.find('1') == 0); - BOOST_TEST(fs1.find('1', 4) == -1); - + BOOST_TEST(testC(S("abcdefghijklmnopqrst"), 21, 0, "abcdefghijklmnopqrst", 20, 0)); +} + +// done +void +testSwap() +{ + { + fixed_string<3> s1("123"); + fixed_string<3> s2("XYZ"); + swap(s1, s2); + BOOST_TEST(s1 == "XYZ"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST(s2 == "123"); + BOOST_TEST(*s2.end() == 0); + fixed_string<3> s3("UV"); + swap(s2, s3); + BOOST_TEST(s2 == "UV"); + BOOST_TEST(*s2.end() == 0); + BOOST_TEST(s3 == "123"); + BOOST_TEST(*s3.end() == 0); + } + { + fixed_string<5> s1("123"); + fixed_string<7> s2("XYZ"); + swap(s1, s2); + BOOST_TEST(s1 == "XYZ"); + BOOST_TEST(*s1.end() == 0); + BOOST_TEST(s2 == "123"); + BOOST_TEST(*s2.end() == 0); + fixed_string<3> s3("UV"); + swap(s2, s3); + BOOST_TEST(s2 == "UV"); + BOOST_TEST(*s2.end() == 0); + BOOST_TEST(s3 == "123"); + BOOST_TEST(*s3.end() == 0); + { + fixed_string<5> s4("12345"); + fixed_string<3> s5("XYZ"); + BOOST_TEST_THROWS( + (swap(s4, s5)), + std::length_error); + } + { + fixed_string<3> s4("XYZ"); + fixed_string<5> s5("12345"); + BOOST_TEST_THROWS( + (swap(s4, s5)), + std::length_error); + } + } +} + +void +testGeneral() +{ + using str1 = fixed_string<1>; + using str2 = fixed_string<2>; + { + str1 s1; + BOOST_TEST(s1 == ""); + BOOST_TEST(s1.empty()); + BOOST_TEST(s1.size() == 0); + BOOST_TEST(s1.max_size() == 1); + BOOST_TEST(s1.capacity() == 1); + BOOST_TEST(s1.begin() == s1.end()); + BOOST_TEST(s1.cbegin() == s1.cend()); + BOOST_TEST(s1.rbegin() == s1.rend()); + BOOST_TEST(s1.crbegin() == s1.crend()); + BOOST_TEST_THROWS( + s1.at(0), + std::out_of_range); + BOOST_TEST(s1.data()[0] == 0); + BOOST_TEST(*s1.c_str() == 0); + BOOST_TEST(std::distance(s1.begin(), s1.end()) == 0); + BOOST_TEST(std::distance(s1.cbegin(), s1.cend()) == 0); + BOOST_TEST(std::distance(s1.rbegin(), s1.rend()) == 0); + BOOST_TEST(std::distance(s1.crbegin(), s1.crend()) == 0); + BOOST_TEST(s1.compare(s1) == 0); + } + { + str1 const s1; + BOOST_TEST(s1 == ""); + BOOST_TEST(s1.empty()); + BOOST_TEST(s1.size() == 0); + BOOST_TEST(s1.max_size() == 1); + BOOST_TEST(s1.capacity() == 1); + BOOST_TEST(s1.begin() == s1.end()); + BOOST_TEST(s1.cbegin() == s1.cend()); + BOOST_TEST(s1.rbegin() == s1.rend()); + BOOST_TEST(s1.crbegin() == s1.crend()); + BOOST_TEST_THROWS( + s1.at(0), + std::out_of_range); + BOOST_TEST(s1.data()[0] == 0); + BOOST_TEST(*s1.c_str() == 0); + BOOST_TEST(std::distance(s1.begin(), s1.end()) == 0); + BOOST_TEST(std::distance(s1.cbegin(), s1.cend()) == 0); + BOOST_TEST(std::distance(s1.rbegin(), s1.rend()) == 0); + BOOST_TEST(std::distance(s1.crbegin(), s1.crend()) == 0); + BOOST_TEST(s1.compare(s1) == 0); + } + { + str1 s1; + str1 s2("x"); + BOOST_TEST(s2 == "x"); + BOOST_TEST(s2[0] == 'x'); + BOOST_TEST(s2.at(0) == 'x'); + BOOST_TEST(s2.front() == 'x'); + BOOST_TEST(s2.back() == 'x'); + str1 const s3(s2); + BOOST_TEST(s3 == "x"); + BOOST_TEST(s3[0] == 'x'); + BOOST_TEST(s3.at(0) == 'x'); + BOOST_TEST(s3.front() == 'x'); + BOOST_TEST(s3.back() == 'x'); + s2 = "y"; + BOOST_TEST(s2 == "y"); + BOOST_TEST(s3 == "x"); + s1 = s2; + BOOST_TEST(s1 == "y"); + s1.clear(); + BOOST_TEST(s1.empty()); + BOOST_TEST(s1.size() == 0); + } + { + str2 s1("x"); + str1 s2(s1); + BOOST_TEST(s2 == "x"); + str1 s3; + s3 = s2; + BOOST_TEST(s3 == "x"); + s1 = "xy"; + BOOST_TEST(s1.size() == 2); + BOOST_TEST(s1[0] == 'x'); + BOOST_TEST(s1[1] == 'y'); + BOOST_TEST(s1.at(0) == 'x'); + BOOST_TEST(s1.at(1) == 'y'); + BOOST_TEST(s1.front() == 'x'); + BOOST_TEST(s1.back() == 'y'); + auto const s4 = s1; + BOOST_TEST(s4[0] == 'x'); + BOOST_TEST(s4[1] == 'y'); + BOOST_TEST(s4.at(0) == 'x'); + BOOST_TEST(s4.at(1) == 'y'); + BOOST_TEST(s4.front() == 'x'); + BOOST_TEST(s4.back() == 'y'); + BOOST_TEST_THROWS( + s3 = s1, + std::length_error); + BOOST_TEST_THROWS( + str1{s1}, + std::length_error); + } + { + str1 s1("x"); + str2 s2; + s2 = s1; + BOOST_TEST_THROWS( + s1.resize(2), + std::length_error); + } +} + +// done +void +testToStaticString() +{ + BOOST_TEST(to_fixed_string(0) == "0"); + BOOST_TEST(to_fixed_string(1) == "1"); + BOOST_TEST(to_fixed_string(0xffff) == "65535"); + BOOST_TEST(to_fixed_string(0x10000) == "65536"); + BOOST_TEST(to_fixed_string(0xffffffff) == "4294967295"); + + BOOST_TEST(to_fixed_string(-1) == "-1"); + BOOST_TEST(to_fixed_string(-65535) == "-65535"); + BOOST_TEST(to_fixed_string(-65536) == "-65536"); + BOOST_TEST(to_fixed_string(-4294967295ll) == "-4294967295"); + + BOOST_TEST(to_fixed_string(0) == "0"); + BOOST_TEST(to_fixed_string(1) == "1"); + BOOST_TEST(to_fixed_string(0xffff) == "65535"); + BOOST_TEST(to_fixed_string(0x10000) == "65536"); + BOOST_TEST(to_fixed_string(0xffffffff) == "4294967295"); +} + +// done +void +testFind() +{ + const char* cs1 = "12345"; + const char* cs2 = "2345"; + string_view v1 = cs1; + string_view v2 = cs2; + fixed_string<5> fs1 = cs1; + fixed_string<4> fs2 = cs2; + using S = fixed_string<400>; + + + // find + BOOST_TEST(fs1.find(v1) == 0); + BOOST_TEST(fs1.find(v2) == 1); + BOOST_TEST(fs1.find(fs1) == 0); + BOOST_TEST(fs1.find(fs2) == 1); + + BOOST_TEST(fs1.find(cs1) == 0); + BOOST_TEST(fs1.find(cs2) == 1); + + BOOST_TEST(fs1.find(cs1, 0) == 0); + BOOST_TEST(fs1.find(cs2, 0) == 1); + + BOOST_TEST(fs1.find(cs2, 0, 2) == 1); + + BOOST_TEST(fs1.find(cs1, 4) == -1); + BOOST_TEST(fs1.find(cs2, 4) == -1); + + BOOST_TEST(fs1.find('1') == 0); + BOOST_TEST(fs1.find('1', 4) == -1); + BOOST_TEST(testF(S(""), "", 0, 0, 0)); BOOST_TEST(testF(S(""), "abcde", 0, 0, 0)); BOOST_TEST(testF(S(""), "abcde", 0, 1, S::npos)); @@ -3917,45 +3935,45 @@ testFind() BOOST_TEST(testF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 5, S::npos)); BOOST_TEST(testF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 9, S::npos)); BOOST_TEST(testF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 10, S::npos)); - BOOST_TEST(testF(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 20, 0, 20)); - - - - - - - - - - - - - - - - - - // rfind - - BOOST_TEST(fs1.rfind(v1) == 0); - BOOST_TEST(fs1.rfind(v2) == 1); - - BOOST_TEST(fs1.rfind(fs1) == 0); - BOOST_TEST(fs1.rfind(fs2) == 1); - - BOOST_TEST(fs1.rfind(cs1) == 0); - BOOST_TEST(fs1.rfind(cs2) == 1); - - BOOST_TEST(fs1.rfind(cs1, 0) == 0); - BOOST_TEST(fs1.rfind(cs2, 0) == -1); - - BOOST_TEST(fs1.rfind(cs2, 0, 2) == -1); - BOOST_TEST(fs1.rfind(cs1, 4) == 0); - - BOOST_TEST(fs1.rfind('1') == 0); - BOOST_TEST(fs1.rfind('1', 4) == 0); - - + BOOST_TEST(testF(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 20, 0, 20)); + + + + + + + + + + + + + + + + + + // rfind + + BOOST_TEST(fs1.rfind(v1) == 0); + BOOST_TEST(fs1.rfind(v2) == 1); + + BOOST_TEST(fs1.rfind(fs1) == 0); + BOOST_TEST(fs1.rfind(fs2) == 1); + + BOOST_TEST(fs1.rfind(cs1) == 0); + BOOST_TEST(fs1.rfind(cs2) == 1); + + BOOST_TEST(fs1.rfind(cs1, 0) == 0); + BOOST_TEST(fs1.rfind(cs2, 0) == -1); + + BOOST_TEST(fs1.rfind(cs2, 0, 2) == -1); + BOOST_TEST(fs1.rfind(cs1, 4) == 0); + + BOOST_TEST(fs1.rfind('1') == 0); + BOOST_TEST(fs1.rfind('1', 4) == 0); + + BOOST_TEST(testRF(S(""), "", 0, 0, 0)); BOOST_TEST(testRF(S(""), "abcde", 0, 0, 0)); BOOST_TEST(testRF(S(""), "abcde", 0, 1, S::npos)); @@ -4255,38 +4273,38 @@ testFind() BOOST_TEST(testRF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 5, 15)); BOOST_TEST(testRF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 9, 10)); BOOST_TEST(testRF(S("abcdeabcdeabcdeabcde"), "abcdeabcde", 20, 10, 10)); - BOOST_TEST(testRF(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 20, 0, 20)); - - - - - - - - - - - // find_first_of - - BOOST_TEST(fs1.find_first_of(v1) == 0); - BOOST_TEST(fs1.find_first_of(v2) == 1); - BOOST_TEST(fs1.find_first_of(fs1) == 0); - BOOST_TEST(fs1.find_first_of(fs2) == 1); - - BOOST_TEST(fs1.find_first_of(cs1) == 0); - BOOST_TEST(fs1.find_first_of(cs2) == 1); - - BOOST_TEST(fs1.find_first_of(cs1, 0) == 0); - BOOST_TEST(fs1.find_first_of(cs2, 0) == 1); - - BOOST_TEST(fs1.find_first_of(cs2, 0, 2) == 1); - - BOOST_TEST(fs1.find_first_of(cs1, 4) == 4); - BOOST_TEST(fs1.find_first_of(cs2, 4) == 4); - - BOOST_TEST(fs1.find_first_of('1') == 0); - BOOST_TEST(fs1.find_first_of('1', 4) == -1); - + BOOST_TEST(testRF(S("abcdeabcdeabcdeabcde"), "abcdeabcdeabcdeabcde", 20, 0, 20)); + + + + + + + + + + + // find_first_of + + BOOST_TEST(fs1.find_first_of(v1) == 0); + BOOST_TEST(fs1.find_first_of(v2) == 1); + BOOST_TEST(fs1.find_first_of(fs1) == 0); + BOOST_TEST(fs1.find_first_of(fs2) == 1); + + BOOST_TEST(fs1.find_first_of(cs1) == 0); + BOOST_TEST(fs1.find_first_of(cs2) == 1); + + BOOST_TEST(fs1.find_first_of(cs1, 0) == 0); + BOOST_TEST(fs1.find_first_of(cs2, 0) == 1); + + BOOST_TEST(fs1.find_first_of(cs2, 0, 2) == 1); + + BOOST_TEST(fs1.find_first_of(cs1, 4) == 4); + BOOST_TEST(fs1.find_first_of(cs2, 4) == 4); + + BOOST_TEST(fs1.find_first_of('1') == 0); + BOOST_TEST(fs1.find_first_of('1', 4) == -1); + BOOST_TEST(testFF(S(""), "", 0, 0, S::npos)); BOOST_TEST(testFF(S(""), "irkhs", 0, 0, S::npos)); BOOST_TEST(testFF(S(""), "kante", 0, 1, S::npos)); @@ -4586,36 +4604,36 @@ testFind() BOOST_TEST(testFF(S("rhqdspkmebiflcotnjga"), "acfhdenops", 20, 5, S::npos)); BOOST_TEST(testFF(S("rahdtmsckfboqlpniegj"), "jopdeamcrk", 20, 9, S::npos)); BOOST_TEST(testFF(S("fbkeiopclstmdqranjhg"), "trqncbkgmh", 20, 10, S::npos)); - BOOST_TEST(testFF(S("lifhpdgmbconstjeqark"), "tomglrkencbsfjqpihda", 20, 0, S::npos)); - - - - - - - - - // find_last_of - - BOOST_TEST(fs1.find_last_of(v1) == 4); - BOOST_TEST(fs1.find_last_of(v2) == 4); - BOOST_TEST(fs1.find_last_of(fs1) == 4); - BOOST_TEST(fs1.find_last_of(fs2) == 4); - - BOOST_TEST(fs1.find_last_of(cs1) == 4); - BOOST_TEST(fs1.find_last_of(cs2) == 4); - - BOOST_TEST(fs1.find_last_of(cs1, 0) == 0); - BOOST_TEST(fs1.find_last_of(cs2, 0) == -1); - - BOOST_TEST(fs1.find_last_of(cs2, 0, 2) == -1); - - BOOST_TEST(fs1.find_last_of(cs1, 4) == 4); - BOOST_TEST(fs1.find_last_of(cs2, 4) == 4); - - BOOST_TEST(fs1.find_last_of('1') == 0); - BOOST_TEST(fs1.find_last_of('5', 3) == -1); - + BOOST_TEST(testFF(S("lifhpdgmbconstjeqark"), "tomglrkencbsfjqpihda", 20, 0, S::npos)); + + + + + + + + + // find_last_of + + BOOST_TEST(fs1.find_last_of(v1) == 4); + BOOST_TEST(fs1.find_last_of(v2) == 4); + BOOST_TEST(fs1.find_last_of(fs1) == 4); + BOOST_TEST(fs1.find_last_of(fs2) == 4); + + BOOST_TEST(fs1.find_last_of(cs1) == 4); + BOOST_TEST(fs1.find_last_of(cs2) == 4); + + BOOST_TEST(fs1.find_last_of(cs1, 0) == 0); + BOOST_TEST(fs1.find_last_of(cs2, 0) == -1); + + BOOST_TEST(fs1.find_last_of(cs2, 0, 2) == -1); + + BOOST_TEST(fs1.find_last_of(cs1, 4) == 4); + BOOST_TEST(fs1.find_last_of(cs2, 4) == 4); + + BOOST_TEST(fs1.find_last_of('1') == 0); + BOOST_TEST(fs1.find_last_of('5', 3) == -1); + BOOST_TEST(testFL(S(""), "", 0, 0, S::npos)); BOOST_TEST(testFL(S(""), "irkhs", 0, 0, S::npos)); BOOST_TEST(testFL(S(""), "kante", 0, 1, S::npos)); @@ -4935,46 +4953,46 @@ testFind() BOOST_TEST(testFL(S("qjidealmtpskrbfhocng"), "ctpmdahebfqjgknloris", 21, 1, 17)); BOOST_TEST(testFL(S("qeindtagmokpfhsclrbj"), "apnkeqthrmlbfodiscgj", 21, 10, 17)); BOOST_TEST(testFL(S("kpfegbjhsrnodltqciam"), "jdgictpframeoqlsbknh", 21, 19, 19)); - BOOST_TEST(testFL(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, 19)); - - - - - - - - // find_first_not_of - - const char* cs3 = "12456"; - const char* cs4 = "2356"; - string_view v3 = cs3; - string_view v4 = cs4; - fixed_string<5> fs3 = cs3; - fixed_string<4> fs4 = cs4; - - BOOST_TEST(fs1.find_first_not_of(v3) == 2); - BOOST_TEST(fs1.find_first_not_of(v4) == 0); - BOOST_TEST(fs1.find_first_not_of(fs3) == 2); - BOOST_TEST(fs1.find_first_not_of(fs4) == 0); - - BOOST_TEST(fs1.find_first_not_of(cs3) == 2); - BOOST_TEST(fs1.find_first_not_of(cs4) == 0); - - BOOST_TEST(fs1.find_first_not_of(cs3, 0) == 2); - BOOST_TEST(fs1.find_first_not_of(cs4, 0) == 0); - - BOOST_TEST(fs1.find_first_not_of(cs4, 0, 2) == 0); - - BOOST_TEST(fs1.find_first_not_of(cs3, 4) == -1); - BOOST_TEST(fs1.find_first_not_of(cs4, 4) == -1); - - BOOST_TEST(fs1.find_first_not_of('1') == 1); - BOOST_TEST(fs1.find_first_not_of('1', 3) == 3); - - - - - + BOOST_TEST(testFL(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, 19)); + + + + + + + + // find_first_not_of + + const char* cs3 = "12456"; + const char* cs4 = "2356"; + string_view v3 = cs3; + string_view v4 = cs4; + fixed_string<5> fs3 = cs3; + fixed_string<4> fs4 = cs4; + + BOOST_TEST(fs1.find_first_not_of(v3) == 2); + BOOST_TEST(fs1.find_first_not_of(v4) == 0); + BOOST_TEST(fs1.find_first_not_of(fs3) == 2); + BOOST_TEST(fs1.find_first_not_of(fs4) == 0); + + BOOST_TEST(fs1.find_first_not_of(cs3) == 2); + BOOST_TEST(fs1.find_first_not_of(cs4) == 0); + + BOOST_TEST(fs1.find_first_not_of(cs3, 0) == 2); + BOOST_TEST(fs1.find_first_not_of(cs4, 0) == 0); + + BOOST_TEST(fs1.find_first_not_of(cs4, 0, 2) == 0); + + BOOST_TEST(fs1.find_first_not_of(cs3, 4) == -1); + BOOST_TEST(fs1.find_first_not_of(cs4, 4) == -1); + + BOOST_TEST(fs1.find_first_not_of('1') == 1); + BOOST_TEST(fs1.find_first_not_of('1', 3) == 3); + + + + + BOOST_TEST(testFFN(S(""), "", 0, 0, S::npos)); BOOST_TEST(testFFN(S(""), "irkhs", 0, 0, S::npos)); BOOST_TEST(testFFN(S(""), "kante", 0, 1, S::npos)); @@ -5294,30 +5312,30 @@ testFind() BOOST_TEST(testFFN(S("qjidealmtpskrbfhocng"), "ctpmdahebfqjgknloris", 21, 1, S::npos)); BOOST_TEST(testFFN(S("qeindtagmokpfhsclrbj"), "apnkeqthrmlbfodiscgj", 21, 10, S::npos)); BOOST_TEST(testFFN(S("kpfegbjhsrnodltqciam"), "jdgictpframeoqlsbknh", 21, 19, S::npos)); - BOOST_TEST(testFFN(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos)); - - // find_last_not_of - - BOOST_TEST(fs1.find_last_not_of(v3) == 2); - BOOST_TEST(fs1.find_last_not_of(v4) == 3); - BOOST_TEST(fs1.find_last_not_of(fs3) == 2); - BOOST_TEST(fs1.find_last_not_of(fs4) == 3); - - BOOST_TEST(fs1.find_last_not_of(cs3) == 2); - BOOST_TEST(fs1.find_last_not_of(cs4) == 3); - - BOOST_TEST(fs1.find_last_not_of(cs3, 0) == -1); - BOOST_TEST(fs1.find_last_not_of(cs4, 0) == 0); - - BOOST_TEST(fs1.find_last_not_of(cs4, 0, 2) == 0); - - BOOST_TEST(fs1.find_last_not_of(cs3, 4) == 2); - BOOST_TEST(fs1.find_last_not_of(cs4, 4) == 3); - - BOOST_TEST(fs1.find_last_not_of('1') == 4); - BOOST_TEST(fs1.find_last_not_of('1', 3) == 3); - - + BOOST_TEST(testFFN(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos)); + + // find_last_not_of + + BOOST_TEST(fs1.find_last_not_of(v3) == 2); + BOOST_TEST(fs1.find_last_not_of(v4) == 3); + BOOST_TEST(fs1.find_last_not_of(fs3) == 2); + BOOST_TEST(fs1.find_last_not_of(fs4) == 3); + + BOOST_TEST(fs1.find_last_not_of(cs3) == 2); + BOOST_TEST(fs1.find_last_not_of(cs4) == 3); + + BOOST_TEST(fs1.find_last_not_of(cs3, 0) == -1); + BOOST_TEST(fs1.find_last_not_of(cs4, 0) == 0); + + BOOST_TEST(fs1.find_last_not_of(cs4, 0, 2) == 0); + + BOOST_TEST(fs1.find_last_not_of(cs3, 4) == 2); + BOOST_TEST(fs1.find_last_not_of(cs4, 4) == 3); + + BOOST_TEST(fs1.find_last_not_of('1') == 4); + BOOST_TEST(fs1.find_last_not_of('1', 3) == 3); + + BOOST_TEST(testFLN(S(""), "", 0, 0, S::npos)); BOOST_TEST(testFLN(S(""), "irkhs", 0, 0, S::npos)); BOOST_TEST(testFLN(S(""), "kante", 0, 1, S::npos)); @@ -5637,145 +5655,145 @@ testFind() BOOST_TEST(testFLN(S("qjidealmtpskrbfhocng"), "ctpmdahebfqjgknloris", 21, 1, 19)); BOOST_TEST(testFLN(S("qeindtagmokpfhsclrbj"), "apnkeqthrmlbfodiscgj", 21, 10, 19)); BOOST_TEST(testFLN(S("kpfegbjhsrnodltqciam"), "jdgictpframeoqlsbknh", 21, 19, 7)); - BOOST_TEST(testFLN(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos)); -} - -// done -void -testReplace() -{ - // replace(size_type pos1, size_type n1, const charT* s, size_type n2); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(5, 2, fs1.data() + 1, 8) == "helloelloworlrld"); - } - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(3, 2, fs1.data() + 2, 2) == "helllworld"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(5, 2, fs2.data(), 2) == "0123401789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(1, 3, fs2.data() + 1, 5) == "012345456789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(0, 5, fs2.data(), 5) == "0123456789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(0, 5, fs2.data() + 5, 5) == "5678956789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(5, 2, fs2.data() + 3, 5) == "0123434567789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(5, 2, fs2.data() + 7, 3) == "01234789789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(3, 5, fs2.data() + 4, 2) == "0124589"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(3, 5, fs2.data() + 1, 3) == "01212389"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(0, 10, fs2.data(), 10) == "0123456789"); - } - { - fixed_string<20> fs2 = "0123456789"; - BOOST_TEST(fs2.replace(0, 10, fs2.data(), 5) == "01234"); - } - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(4, 3, fs1.data() + 1, 3) == "hellellrld"); - } - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST_EQ(fs1.replace(0, 1, fs1.data() + 4, 4), fixed_string<20>("oworelloworld")); - } - // replace(size_type pos1, size_type n1, const basic_string& str); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), fs1) == "helloworld"); - } - // replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), fs1, 0, fs1.size()) == "helloworld"); - } - // replace(size_type pos1, size_type n1, const T& t); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), string_view(fs1)) == "helloworld"); - } - // replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), string_view(fs1), 0, fs1.size()) == "helloworld"); - } - // replace(size_type pos, size_type n, const charT * s); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), fs1.data()) == "helloworld"); - } - // replace(size_type pos1, size_type n1, size_type n2, charT c);] - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(0, fs1.size(), fs1.size(), 'a') == "aaaaaaaaaa"); - } - // replace(const_iterator i1, const_iterator i2, const basic_string& str); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1) == "helloworld"); - } - // replace(const_iterator i1, const_iterator i2, const T& t); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), string_view(fs1)) == "helloworld"); - } - // replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.data(), fs1.size()) == "helloworld"); - } - // replace(const_iterator i1, const_iterator i2, const charT* s); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.data()) == "helloworld"); - } - // replace(const_iterator i1, const_iterator i2, size_type n, charT c); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.size(), 'a') == "aaaaaaaaaa"); - } - // replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.begin(), fs1.end()) == "helloworld"); - } - // replace(const_iterator i1, const_iterator i2, initializer_list il); - { - fixed_string<20> fs1 = "helloworld"; - BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}) == "helloworld"); - } - - using S = fixed_string<400>; + BOOST_TEST(testFLN(S("hnbrcplsjfgiktoedmaq"), "qprlsfojamgndekthibc", 21, 20, S::npos)); +} + +// done +void +testReplace() +{ + // replace(size_type pos1, size_type n1, const charT* s, size_type n2); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(5, 2, fs1.data() + 1, 8) == "helloelloworlrld"); + } + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(3, 2, fs1.data() + 2, 2) == "helllworld"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(5, 2, fs2.data(), 2) == "0123401789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(1, 3, fs2.data() + 1, 5) == "012345456789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(0, 5, fs2.data(), 5) == "0123456789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(0, 5, fs2.data() + 5, 5) == "5678956789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(5, 2, fs2.data() + 3, 5) == "0123434567789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(5, 2, fs2.data() + 7, 3) == "01234789789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(3, 5, fs2.data() + 4, 2) == "0124589"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(3, 5, fs2.data() + 1, 3) == "01212389"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(0, 10, fs2.data(), 10) == "0123456789"); + } + { + fixed_string<20> fs2 = "0123456789"; + BOOST_TEST(fs2.replace(0, 10, fs2.data(), 5) == "01234"); + } + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(4, 3, fs1.data() + 1, 3) == "hellellrld"); + } + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST_EQ(fs1.replace(0, 1, fs1.data() + 4, 4), fixed_string<20>("oworelloworld")); + } + // replace(size_type pos1, size_type n1, const basic_string& str); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), fs1) == "helloworld"); + } + // replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), fs1, 0, fs1.size()) == "helloworld"); + } + // replace(size_type pos1, size_type n1, const T& t); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), string_view(fs1)) == "helloworld"); + } + // replace(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), string_view(fs1), 0, fs1.size()) == "helloworld"); + } + // replace(size_type pos, size_type n, const charT * s); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), fs1.data()) == "helloworld"); + } + // replace(size_type pos1, size_type n1, size_type n2, charT c);] + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(0, fs1.size(), fs1.size(), 'a') == "aaaaaaaaaa"); + } + // replace(const_iterator i1, const_iterator i2, const basic_string& str); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1) == "helloworld"); + } + // replace(const_iterator i1, const_iterator i2, const T& t); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), string_view(fs1)) == "helloworld"); + } + // replace(const_iterator i1, const_iterator i2, const charT* s, size_type n); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.data(), fs1.size()) == "helloworld"); + } + // replace(const_iterator i1, const_iterator i2, const charT* s); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.data()) == "helloworld"); + } + // replace(const_iterator i1, const_iterator i2, size_type n, charT c); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.size(), 'a') == "aaaaaaaaaa"); + } + // replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), fs1.begin(), fs1.end()) == "helloworld"); + } + // replace(const_iterator i1, const_iterator i2, initializer_list il); + { + fixed_string<20> fs1 = "helloworld"; + BOOST_TEST(fs1.replace(fs1.begin(), fs1.end(), {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}) == "helloworld"); + } + + using S = fixed_string<400>; S s_short = "123/"; S s_long = "Lorem ipsum dolor sit amet, consectetur/"; - BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/"); - BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/123/123/"); - BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/123/123/123/123/123/123/"); - BOOST_TEST(s_long.replace(s_long.begin(), s_long.begin(), s_long.begin(), s_long.end()) == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); - + BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/"); + BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/123/123/"); + BOOST_TEST(s_short.replace(s_short.begin(), s_short.begin(), s_short.begin(), s_short.end()) == "123/123/123/123/123/123/123/123/"); + BOOST_TEST(s_long.replace(s_long.begin(), s_long.begin(), s_long.begin(), s_long.end()) == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/"); + BOOST_TEST(testR(S(""), 0, 0, "", S(""))); BOOST_TEST(testR(S(""), 0, 0, "12345", S("12345"))); BOOST_TEST(testR(S(""), 0, 0, "1234567890", S("1234567890"))); @@ -5875,7 +5893,7 @@ testReplace() BOOST_TEST(testR(S("abcdefghij"), 1, 1, "", S("acdefghij"))); BOOST_TEST(testR(S("abcdefghij"), 1, 1, "12345", S("a12345cdefghij"))); BOOST_TEST(testR(S("abcdefghij"), 1, 1, "1234567890", S("a1234567890cdefghij"))); - BOOST_TEST(testR(S("abcdefghij"), 1, 1, "12345678901234567890", S("a12345678901234567890cdefghij"))); + BOOST_TEST(testR(S("abcdefghij"), 1, 1, "12345678901234567890", S("a12345678901234567890cdefghij"))); BOOST_TEST(testR(S(""), 0, 0, 0, '2', S(""))); BOOST_TEST(testR(S(""), 0, 0, 5, '2', S("22222"))); BOOST_TEST(testR(S(""), 0, 0, 10, '2', S("2222222222"))); @@ -5974,8 +5992,8 @@ testReplace() BOOST_TEST(testR(S("abcde"), 5, 1, 0, '2', S("abcde"))); BOOST_TEST(testR(S("abcde"), 5, 1, 5, '2', S("abcde22222"))); BOOST_TEST(testR(S("abcde"), 5, 1, 10, '2', S("abcde2222222222"))); - BOOST_TEST(testR(S("abcde"), 5, 1, 20, '2', S("abcde22222222222222222222"))); - + BOOST_TEST(testR(S("abcde"), 5, 1, 20, '2', S("abcde22222222222222222222"))); + BOOST_TEST(testR(S("abcde"), 0, 4, "12345", 4, S("1234e"))); BOOST_TEST(testR(S("abcde"), 0, 4, "12345", 5, S("12345e"))); BOOST_TEST(testR(S("abcde"), 0, 4, "1234567890", 0, S("e"))); @@ -6175,7 +6193,7 @@ testReplace() BOOST_TEST(testR(S("abcdefghij"), 5, 6, "1234567890", 5, S("abcde12345"))); BOOST_TEST(testR(S("abcdefghij"), 5, 6, "1234567890", 9, S("abcde123456789"))); BOOST_TEST(testR(S("abcdefghij"), 5, 6, "1234567890", 10, S("abcde1234567890"))); - BOOST_TEST(testR(S("abcdefghij"), 5, 6, "12345678901234567890", 0, S("abcde"))); + BOOST_TEST(testR(S("abcdefghij"), 5, 6, "12345678901234567890", 0, S("abcde"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 0, 0, "", 0, S("abcdefghijklmnopqrst"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 0, 0, "12345", 0, S("abcdefghijklmnopqrst"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 0, 0, "12345", 1, S("1abcdefghijklmnopqrst"))); @@ -6475,7 +6493,7 @@ testReplace() BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 19, 0, "1234567890", 5, S("abcdefghijklmnopqrs12345t"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 19, 0, "1234567890", 9, S("abcdefghijklmnopqrs123456789t"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 19, 0, "1234567890", 10, S("abcdefghijklmnopqrs1234567890t"))); - BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 19, 0, "12345678901234567890", 0, S("abcdefghijklmnopqrst"))); + BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 19, 0, "12345678901234567890", 0, S("abcdefghijklmnopqrst"))); BOOST_TEST(testR(S(""), 1, 0, "12345", 0, S("can't happen"))); BOOST_TEST(testR(S(""), 1, 0, "12345", 1, S("can't happen"))); BOOST_TEST(testR(S(""), 1, 0, "12345", 2, S("can't happen"))); @@ -6606,14 +6624,14 @@ testReplace() BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 20, 1, "12345678901234567890", 1, S("abcdefghijklmnopqrst1"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 20, 1, "12345678901234567890", 10, S("abcdefghijklmnopqrst1234567890"))); BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 20, 1, "12345678901234567890", 19, S("abcdefghijklmnopqrst1234567890123456789"))); - BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 20, 1, "12345678901234567890", 20, S("abcdefghijklmnopqrst12345678901234567890"))); -} - -// done -void -testSubstr() -{ - using S = fixed_string<400>; + BOOST_TEST(testR(S("abcdefghijklmnopqrst"), 20, 1, "12345678901234567890", 20, S("abcdefghijklmnopqrst12345678901234567890"))); +} + +// done +void +testSubstr() +{ + using S = fixed_string<400>; BOOST_TEST(testS(S(""), 0, 0)); BOOST_TEST(testS(S(""), 1, 0)); BOOST_TEST(testS(S("pniot"), 0, 0)); @@ -6729,69 +6747,222 @@ testSubstr() BOOST_TEST(testS(S("lgjqketopbfahrmnsicd"), 19, 0)); BOOST_TEST(testS(S("ktsrmnqagdecfhijpobl"), 19, 1)); BOOST_TEST(testS(S("lsaijeqhtrbgcdmpfkno"), 20, 0)); - BOOST_TEST(testS(S("dplqartnfgejichmoskb"), 21, 0)); -} - -// done -void -testStartsEnds() -{ - using S = fixed_string<400>; - BOOST_TEST(S("1234567890").starts_with('1')); - BOOST_TEST(S("1234567890").starts_with("123")); - BOOST_TEST(S("1234567890").starts_with("1234567890")); - BOOST_TEST(!S("1234567890").starts_with("234")); - BOOST_TEST(!S("1234567890").starts_with("12345678900")); - BOOST_TEST(S("1234567890").starts_with(string_view("1234567890"))); - - BOOST_TEST(S("1234567890").ends_with('0')); - BOOST_TEST(S("1234567890").ends_with("890")); - BOOST_TEST(S("1234567890").ends_with("1234567890")); - BOOST_TEST(!S("1234567890").ends_with("234")); - BOOST_TEST(!S("1234567890").ends_with("12345678900")); - BOOST_TEST(S("1234567890").ends_with(string_view("1234567890"))); -} - -int -runTests() -{ - testConstruct(); - - testAssignment(); - - testElements(); - - testIterators(); - - testCapacity(); - - testClear(); - testInsert(); - testErase(); - testPushBack(); - testPopBack(); - testAppend(); - testPlusEquals(); - - testCompare(); - testSwap(); - testGeneral(); - testToStaticString(); - - testFind(); - - testReplace(); - testSubstr(); - testStartsEnds(); - - return report_errors(); -} - -} // fixed_string -} // boost - -int -main() -{ - return boost::fixed_string::runTests(); -} + BOOST_TEST(testS(S("dplqartnfgejichmoskb"), 21, 0)); +} + +// done +void +testSubview() +{ + using S = fixed_string<400>; + BOOST_TEST(testSV(S(""), 0, 0)); + BOOST_TEST(testSV(S(""), 1, 0)); + BOOST_TEST(testSV(S("pniot"), 0, 0)); + BOOST_TEST(testSV(S("htaob"), 0, 1)); + BOOST_TEST(testSV(S("fodgq"), 0, 2)); + BOOST_TEST(testSV(S("hpqia"), 0, 4)); + BOOST_TEST(testSV(S("qanej"), 0, 5)); + BOOST_TEST(testSV(S("dfkap"), 1, 0)); + BOOST_TEST(testSV(S("clbao"), 1, 1)); + BOOST_TEST(testSV(S("ihqrf"), 1, 2)); + BOOST_TEST(testSV(S("mekdn"), 1, 3)); + BOOST_TEST(testSV(S("ngtjf"), 1, 4)); + BOOST_TEST(testSV(S("srdfq"), 2, 0)); + BOOST_TEST(testSV(S("qkdrs"), 2, 1)); + BOOST_TEST(testSV(S("ikcrq"), 2, 2)); + BOOST_TEST(testSV(S("cdaih"), 2, 3)); + BOOST_TEST(testSV(S("dmajb"), 4, 0)); + BOOST_TEST(testSV(S("karth"), 4, 1)); + BOOST_TEST(testSV(S("lhcdo"), 5, 0)); + BOOST_TEST(testSV(S("acbsj"), 6, 0)); + BOOST_TEST(testSV(S("pbsjikaole"), 0, 0)); + BOOST_TEST(testSV(S("pcbahntsje"), 0, 1)); + BOOST_TEST(testSV(S("mprdjbeiak"), 0, 5)); + BOOST_TEST(testSV(S("fhepcrntko"), 0, 9)); + BOOST_TEST(testSV(S("eqmpaidtls"), 0, 10)); + BOOST_TEST(testSV(S("joidhalcmq"), 1, 0)); + BOOST_TEST(testSV(S("omigsphflj"), 1, 1)); + BOOST_TEST(testSV(S("kocgbphfji"), 1, 4)); + BOOST_TEST(testSV(S("onmjekafbi"), 1, 8)); + BOOST_TEST(testSV(S("fbslrjiqkm"), 1, 9)); + BOOST_TEST(testSV(S("oqmrjahnkg"), 5, 0)); + BOOST_TEST(testSV(S("jeidpcmalh"), 5, 1)); + BOOST_TEST(testSV(S("schfalibje"), 5, 2)); + BOOST_TEST(testSV(S("crliponbqe"), 5, 4)); + BOOST_TEST(testSV(S("igdscopqtm"), 5, 5)); + BOOST_TEST(testSV(S("qngpdkimlc"), 9, 0)); + BOOST_TEST(testSV(S("thdjgafrlb"), 9, 1)); + BOOST_TEST(testSV(S("hcjitbfapl"), 10, 0)); + BOOST_TEST(testSV(S("mgojkldsqh"), 11, 0)); + BOOST_TEST(testSV(S("gfshlcmdjreqipbontak"), 0, 0)); + BOOST_TEST(testSV(S("nadkhpfemgclosibtjrq"), 0, 1)); + BOOST_TEST(testSV(S("nkodajteqplrbifhmcgs"), 0, 10)); + BOOST_TEST(testSV(S("ofdrqmkeblthacpgijsn"), 0, 19)); + BOOST_TEST(testSV(S("gbmetiprqdoasckjfhln"), 0, 20)); + BOOST_TEST(testSV(S("bdfjqgatlksriohemnpc"), 1, 0)); + BOOST_TEST(testSV(S("crnklpmegdqfiashtojb"), 1, 1)); + BOOST_TEST(testSV(S("ejqcnahdrkfsmptilgbo"), 1, 9)); + BOOST_TEST(testSV(S("jsbtafedocnirgpmkhql"), 1, 18)); + BOOST_TEST(testSV(S("prqgnlbaejsmkhdctoif"), 1, 19)); + BOOST_TEST(testSV(S("qnmodrtkebhpasifgcjl"), 10, 0)); + BOOST_TEST(testSV(S("pejafmnokrqhtisbcdgl"), 10, 1)); + BOOST_TEST(testSV(S("cpebqsfmnjdolhkratgi"), 10, 5)); + BOOST_TEST(testSV(S("odnqkgijrhabfmcestlp"), 10, 9)); + BOOST_TEST(testSV(S("lmofqdhpkibagnrcjste"), 10, 10)); + BOOST_TEST(testSV(S("lgjqketopbfahrmnsicd"), 19, 0)); + BOOST_TEST(testSV(S("ktsrmnqagdecfhijpobl"), 19, 1)); + BOOST_TEST(testSV(S("lsaijeqhtrbgcdmpfkno"), 20, 0)); + BOOST_TEST(testSV(S("dplqartnfgejichmoskb"), 21, 0)); + BOOST_TEST(testSV(S(""), 0, 0)); + BOOST_TEST(testSV(S(""), 1, 0)); + BOOST_TEST(testSV(S("pniot"), 0, 0)); + BOOST_TEST(testSV(S("htaob"), 0, 1)); + BOOST_TEST(testSV(S("fodgq"), 0, 2)); + BOOST_TEST(testSV(S("hpqia"), 0, 4)); + BOOST_TEST(testSV(S("qanej"), 0, 5)); + BOOST_TEST(testSV(S("dfkap"), 1, 0)); + BOOST_TEST(testSV(S("clbao"), 1, 1)); + BOOST_TEST(testSV(S("ihqrf"), 1, 2)); + BOOST_TEST(testSV(S("mekdn"), 1, 3)); + BOOST_TEST(testSV(S("ngtjf"), 1, 4)); + BOOST_TEST(testSV(S("srdfq"), 2, 0)); + BOOST_TEST(testSV(S("qkdrs"), 2, 1)); + BOOST_TEST(testSV(S("ikcrq"), 2, 2)); + BOOST_TEST(testSV(S("cdaih"), 2, 3)); + BOOST_TEST(testSV(S("dmajb"), 4, 0)); + BOOST_TEST(testSV(S("karth"), 4, 1)); + BOOST_TEST(testSV(S("lhcdo"), 5, 0)); + BOOST_TEST(testSV(S("acbsj"), 6, 0)); + BOOST_TEST(testSV(S("pbsjikaole"), 0, 0)); + BOOST_TEST(testSV(S("pcbahntsje"), 0, 1)); + BOOST_TEST(testSV(S("mprdjbeiak"), 0, 5)); + BOOST_TEST(testSV(S("fhepcrntko"), 0, 9)); + BOOST_TEST(testSV(S("eqmpaidtls"), 0, 10)); + BOOST_TEST(testSV(S("joidhalcmq"), 1, 0)); + BOOST_TEST(testSV(S("omigsphflj"), 1, 1)); + BOOST_TEST(testSV(S("kocgbphfji"), 1, 4)); + BOOST_TEST(testSV(S("onmjekafbi"), 1, 8)); + BOOST_TEST(testSV(S("fbslrjiqkm"), 1, 9)); + BOOST_TEST(testSV(S("oqmrjahnkg"), 5, 0)); + BOOST_TEST(testSV(S("jeidpcmalh"), 5, 1)); + BOOST_TEST(testSV(S("schfalibje"), 5, 2)); + BOOST_TEST(testSV(S("crliponbqe"), 5, 4)); + BOOST_TEST(testSV(S("igdscopqtm"), 5, 5)); + BOOST_TEST(testSV(S("qngpdkimlc"), 9, 0)); + BOOST_TEST(testSV(S("thdjgafrlb"), 9, 1)); + BOOST_TEST(testSV(S("hcjitbfapl"), 10, 0)); + BOOST_TEST(testSV(S("mgojkldsqh"), 11, 0)); + BOOST_TEST(testSV(S("gfshlcmdjreqipbontak"), 0, 0)); + BOOST_TEST(testSV(S("nadkhpfemgclosibtjrq"), 0, 1)); + BOOST_TEST(testSV(S("nkodajteqplrbifhmcgs"), 0, 10)); + BOOST_TEST(testSV(S("ofdrqmkeblthacpgijsn"), 0, 19)); + BOOST_TEST(testSV(S("gbmetiprqdoasckjfhln"), 0, 20)); + BOOST_TEST(testSV(S("bdfjqgatlksriohemnpc"), 1, 0)); + BOOST_TEST(testSV(S("crnklpmegdqfiashtojb"), 1, 1)); + BOOST_TEST(testSV(S("ejqcnahdrkfsmptilgbo"), 1, 9)); + BOOST_TEST(testSV(S("jsbtafedocnirgpmkhql"), 1, 18)); + BOOST_TEST(testSV(S("prqgnlbaejsmkhdctoif"), 1, 19)); + BOOST_TEST(testSV(S("qnmodrtkebhpasifgcjl"), 10, 0)); + BOOST_TEST(testSV(S("pejafmnokrqhtisbcdgl"), 10, 1)); + BOOST_TEST(testSV(S("cpebqsfmnjdolhkratgi"), 10, 5)); + BOOST_TEST(testSV(S("odnqkgijrhabfmcestlp"), 10, 9)); + BOOST_TEST(testSV(S("lmofqdhpkibagnrcjste"), 10, 10)); + BOOST_TEST(testSV(S("lgjqketopbfahrmnsicd"), 19, 0)); + BOOST_TEST(testSV(S("ktsrmnqagdecfhijpobl"), 19, 1)); + BOOST_TEST(testSV(S("lsaijeqhtrbgcdmpfkno"), 20, 0)); + BOOST_TEST(testSV(S("dplqartnfgejichmoskb"), 21, 0)); +} + +// done +void +testStartsEnds() +{ + using S = fixed_string<400>; + BOOST_TEST(S("1234567890").starts_with('1')); + BOOST_TEST(S("1234567890").starts_with("123")); + BOOST_TEST(S("1234567890").starts_with("1234567890")); + BOOST_TEST(!S("1234567890").starts_with("234")); + BOOST_TEST(!S("1234567890").starts_with("12345678900")); + BOOST_TEST(S("1234567890").starts_with(string_view("1234567890"))); + + BOOST_TEST(S("1234567890").ends_with('0')); + BOOST_TEST(S("1234567890").ends_with("890")); + BOOST_TEST(S("1234567890").ends_with("1234567890")); + BOOST_TEST(!S("1234567890").ends_with("234")); + BOOST_TEST(!S("1234567890").ends_with("12345678900")); + BOOST_TEST(S("1234567890").ends_with(string_view("1234567890"))); +} + +void testHash() +{ + using U = fixed_string<30>; + std::hash hasher; + BOOST_TEST(hasher(U("1")) != hasher(U("123456789"))); + BOOST_TEST(hasher(U("1234567890")) == hasher(U("1234567890"))); +} + +int +runTests() +{ + testConstruct(); + + testAssignment(); + + testElements(); + + testIterators(); + + testCapacity(); + + testClear(); + testInsert(); + testErase(); + testPushBack(); + testPopBack(); + testAppend(); + testPlusEquals(); + + testCompare(); + testSwap(); + testGeneral(); + testToStaticString(); + + testFind(); + + testReplace(); + testSubstr(); + testStartsEnds(); + + testHash(); + + return report_errors(); +} + +static_assert(std::is_base_of< + detail::fixed_string_base_zero<0, char, std::char_traits>, + fixed_string<0>>::value, + "the zero size optimization shall be used for N = 0"); + +//static_assert(std::is_base_of< +// detail::fixed_string_base_null<1, char, std::char_traits>, +// fixed_string<1>>::value, +// "the null terminator optimization shall be used for N <= (std::numeric_limits::max)()"); +// +//static_assert(std::is_base_of< +// detail::fixed_string_base_null<(std::numeric_limits::max)(), char, std::char_traits>, +// fixed_string<(std::numeric_limits::max)()>>::value, +// "the null terminator optimization shall be used for N <= std::numeric_limits::max()"); + +static_assert(std::is_base_of< + detail::fixed_string_base_zero<(std::numeric_limits::max)() + 1, char, std::char_traits>, + fixed_string<(std::numeric_limits::max)() + 1>>::value, + "the minimum size type optimization shall be used for N > std::numeric_limits::max()"); + +} // fixed_string +} // boost + +int +main() +{ + return boost::fixed_string::runTests(); +} \ No newline at end of file