// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // Copyright (c) 2019-2020 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/static_string // #ifndef BOOST_STATIC_STRING_STATIC_STRING_HPP #define BOOST_STATIC_STRING_STATIC_STRING_HPP #if defined(__GNUC__) && __GNUC__ >= 8 #pragma GCC diagnostic push #pragma GCC system_header // false positives #pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Wrestrict" #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnoexcept-type" #endif // External include guard #ifndef BOOST_STATIC_STRING_CONFIG_HPP #include #include #endif #include #include #include #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) #include #endif #include #include #include #include #include #include namespace boost { namespace static_strings { #ifndef BOOST_STATIC_STRING_DOCS template class basic_static_string; //------------------------------------------------------------------------------ // // Aliases // //------------------------------------------------------------------------------ template using static_string = basic_static_string>; #ifdef BOOST_STATIC_STRING_HAS_WCHAR template using static_wstring = basic_static_string>; #endif template using static_u16string = basic_static_string>; template using static_u32string = basic_static_string>; #ifdef __cpp_char8_t template using static_u8string = basic_static_string>; #endif //-------------------------------------------------------------------------- // // Detail // //-------------------------------------------------------------------------- namespace detail { // 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, std::size_t>::type>::type>::type>::type>::type; // std::is_nothrow_convertible is C++20 template void is_nothrow_convertible_helper(To) noexcept; // MSVC is unable to parse this as a single expression, so a helper is needed template(std::declval()))> struct is_nothrow_convertible_msvc_helper { static const bool value = noexcept(is_nothrow_convertible_helper(std::declval())); }; template struct is_nothrow_convertible : std::false_type { }; template struct is_nothrow_convertible::value>::type> : std::true_type { }; // GCC 4.8, 4.9 workaround for void_t to make the defining-type-id dependant template struct void_t_helper { using type = void; }; // void_t for c++11 template using void_t = typename void_t_helper::type; template struct is_string_like : std::false_type {}; template struct is_string_like< T, CharT, void_t< decltype(std::declval() = std::declval().data()), decltype(std::declval() = std::declval().size())>> : std::true_type {}; // Check if a type can be used for templated // overloads string_view_type // This will be used by overloads that accept the string_view types // directly and other convertible types such as std::string. // When no string_view type is available, then we check for the // data and size member functions, and use them directly for assignments. // Types convertible to basic_static_string are not considered viewable // to prevent any ambiguity during overload resolution. template struct enable_if_viewable { }; template struct enable_if_viewable::value && !std::is_convertible&>::value #elif defined(BOOST_STATIC_STRING_STANDALONE) std::is_convertible>::value && !std::is_convertible::value && !std::is_convertible&>::value #else ( std::is_convertible>::value || std::is_convertible>::value ) && !std::is_convertible::value && !std::is_convertible&>::value #endif >::type> { using type = void; }; template using enable_if_viewable_t = typename enable_if_viewable::type; // The common string_view type used in private operations with enable_if_viewable_t // - T const& itself when no string_view type is available // - basic_string_view (boost::string_view or std::string_view) when in // standalone because core::detail::string_view is unavailable // - core::detail::basic_string_view otherwise because it's convertible // to and from most types, including std::string_view // After converting a parameter to a common_string_view_type reference, we // can use the data() and size() member functions. #if !defined(BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW) template using common_string_view_type = T const&; #elif defined(BOOST_STATIC_STRING_STANDALONE) template using common_string_view_type = basic_string_view; #else template struct common_string_view_type_impl {}; template struct common_string_view_type_impl< T, CharT, Traits, typename std::enable_if< is_string_like::value && !std::is_convertible>::value && !std::is_convertible>::value>::type> { using type = T const&; }; template struct common_string_view_type_impl< T, CharT, Traits, typename std::enable_if< std::is_convertible>::value && !std::is_convertible>::value>::type> { using type = basic_string_view; }; template struct common_string_view_type_impl< T, CharT, Traits, typename std::enable_if< std::is_convertible>::value>::type> { using type = core::basic_string_view; }; template using common_string_view_type = typename common_string_view_type_impl::type; #endif // Simplified check for if a type is an iterator template struct is_iterator : std::false_type { }; template struct is_iterator::value, void_t>::type> : std::true_type { }; template struct is_iterator : std::true_type { }; template struct is_input_iterator : std::false_type { }; template struct is_input_iterator::value && std::is_convertible::iterator_category, std::input_iterator_tag>::value>::type> : std::true_type { }; template struct is_forward_iterator : std::false_type { }; template struct is_forward_iterator::value && std::is_convertible::iterator_category, std::forward_iterator_tag>::value>::type> : std::true_type { }; template struct is_subtractable : std::false_type { }; template struct is_subtractable() - std::declval())>> : std::true_type { }; // constexpr distance for c++14 template< typename ForwardIt, typename std::enable_if::value>::type* = nullptr> BOOST_STATIC_STRING_CPP14_CONSTEXPR std::size_t distance(ForwardIt first, ForwardIt last) { std::size_t dist = 0; for (; first != last; ++first, ++dist); return dist; } template< typename RandomIt, typename std::enable_if::value>::type* = nullptr> BOOST_STATIC_STRING_CPP14_CONSTEXPR std::size_t distance(RandomIt first, RandomIt last) { return last - first; } // Copy using traits, respecting iterator rules template BOOST_STATIC_STRING_CPP14_CONSTEXPR void copy_with_traits( InputIt first, InputIt last, CharT* out) { for (; first != last; ++first, ++out) Traits::assign(*out, *first); } // Optimization for using the smallest possible type template class static_string_base { private: using size_type = smallest_width; using value_type = typename Traits::char_type; using pointer = value_type*; using const_pointer = const value_type*; public: BOOST_STATIC_STRING_CPP11_CONSTEXPR static_string_base() noexcept { }; BOOST_STATIC_STRING_CPP14_CONSTEXPR pointer data_impl() noexcept { return data_; } BOOST_STATIC_STRING_CPP14_CONSTEXPR const_pointer data_impl() const noexcept { return data_; } BOOST_STATIC_STRING_CPP11_CONSTEXPR std::size_t size_impl() const noexcept { return size_; } BOOST_STATIC_STRING_CPP14_CONSTEXPR std::size_t set_size(std::size_t n) noexcept { // Functions that set size will throw // if the new size would exceed max_size() // therefore we can guarantee that this will // not lose data. return size_ = size_type(n); } BOOST_STATIC_STRING_CPP14_CONSTEXPR void term_impl() noexcept { Traits::assign(data_[size_], value_type()); } size_type size_ = 0; value_type data_[N + 1]{}; }; // Optimization for when the size is 0 template class static_string_base<0, CharT, Traits> { private: using value_type = typename Traits::char_type; using pointer = value_type*; public: BOOST_STATIC_STRING_CPP11_CONSTEXPR static_string_base() noexcept { } // Modifying the null terminator is UB BOOST_STATIC_STRING_CPP11_CONSTEXPR pointer data_impl() const noexcept { return const_cast(&null_); } BOOST_STATIC_STRING_CPP11_CONSTEXPR std::size_t size_impl() const noexcept { return 0; } BOOST_STATIC_STRING_CPP11_CONSTEXPR std::size_t set_size(std::size_t) const noexcept { return 0; } BOOST_STATIC_STRING_CPP14_CONSTEXPR void term_impl() const noexcept { } private: static constexpr const value_type null_{}; }; // This is only needed in C++14 and lower. // see http://eel.is/c++draft/depr.static.constexpr #ifndef BOOST_STATIC_STRING_CPP17 template constexpr const typename static_string_base<0, CharT, Traits>::value_type static_string_base<0, CharT, Traits>:: null_; #endif template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline int lexicographical_compare( const CharT* s1, std::size_t n1, const CharT* s2, std::size_t n2) noexcept { if(n1 < n2) return Traits::compare( s1, s2, n1) <= 0 ? -1 : 1; if(n1 > n2) return Traits::compare( s1, s2, n2) >= 0 ? 1 : -1; return Traits::compare(s1, s2, n1); } template inline char* integer_to_string( char* str_end, Integer value, std::true_type) noexcept { if (value == 0) { Traits::assign(*--str_end, '0'); return str_end; } if (value < 0) { const bool is_min = value == (std::numeric_limits::min)(); // negation of a min value cannot be represented if (is_min) value = (std::numeric_limits::max)(); else value = -value; const auto last_char = str_end - 1; for (; value > 0; value /= 10) Traits::assign(*--str_end, "0123456789"[value % 10]); // minimum values are powers of 2, so it will // never terminate with a 9. if (is_min) Traits::assign(*last_char, Traits::to_char_type( Traits::to_int_type(*last_char) + 1)); Traits::assign(*--str_end, '-'); return str_end; } for (; value > 0; value /= 10) Traits::assign(*--str_end, "0123456789"[value % 10]); return str_end; } template inline char* integer_to_string( char* str_end, Integer value, std::false_type) noexcept { if (value == 0) { Traits::assign(*--str_end, '0'); return str_end; } for (; value > 0; value /= 10) Traits::assign(*--str_end, "0123456789"[value % 10]); return str_end; } template inline wchar_t* integer_to_wstring( wchar_t* str_end, Integer value, std::true_type) noexcept { if (value == 0) { Traits::assign(*--str_end, L'0'); return str_end; } if (value < 0) { const bool is_min = value == (std::numeric_limits::min)(); // negation of a min value cannot be represented if (is_min) value = (std::numeric_limits::max)(); else value = -value; const auto last_char = str_end - 1; for (; value > 0; value /= 10) Traits::assign(*--str_end, L"0123456789"[value % 10]); // minimum values are powers of 2, so it will // never terminate with a 9. if (is_min) Traits::assign(*last_char, Traits::to_char_type( Traits::to_int_type(*last_char) + 1)); Traits::assign(*--str_end, L'-'); return str_end; } for (; value > 0; value /= 10) Traits::assign(*--str_end, L"0123456789"[value % 10]); return str_end; } template inline wchar_t* integer_to_wstring( wchar_t* str_end, Integer value, std::false_type) noexcept { if (value == 0) { Traits::assign(*--str_end, L'0'); return str_end; } for (; value > 0; value /= 10) Traits::assign(*--str_end, L"0123456789"[value % 10]); return str_end; } template inline static_string to_static_string_int_impl(Integer value) noexcept { using size_type = typename static_string::size_type; static_string result; result.resize_and_overwrite( N, [&](char* buffer, size_type) -> size_type { char* const digits_end = buffer + N; char* const digits_begin = integer_to_string, Integer>( digits_end, value, std::is_signed{}); const size_type len = digits_end - digits_begin; std::char_traits::move(buffer, digits_begin, len); return len; } ); return result; } #ifdef BOOST_STATIC_STRING_HAS_WCHAR template inline static_wstring to_static_wstring_int_impl(Integer value) noexcept { using size_type = typename static_wstring::size_type; static_wstring result; result.resize_and_overwrite( N, [&](wchar_t* buffer, size_type) -> size_type { wchar_t* const digits_end = buffer + N; wchar_t* const digits_begin = integer_to_wstring, Integer>( digits_end, value, std::is_signed{}); const size_type len = digits_end - digits_begin; std::char_traits::move(buffer, digits_begin, len); return len; } ); return result; } #endif BOOST_STATIC_STRING_CPP11_CONSTEXPR inline int count_digits(std::size_t value) { return value < 10 ? 1 : count_digits(value / 10) + 1; } // Ignore -Wformat-truncation, we know what // we are doing here. The version check does // not need to be extremely precise. #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-truncation" #endif #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) template inline static_string cpp26_to_static_string(FloatingPoint value) noexcept { using size_type = typename static_string::size_type; static_string result; result.resize_and_overwrite( N, [&](char* buffer, size_type) -> size_type { const auto formatted = std::format_to_n(buffer, N, "{}", value); return formatted.size; } ); return result; } #endif template inline static_string to_static_string_float_impl(double value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_string(value); #else using size_type = typename static_string::size_type; static_string result; // we have to assume here that no reasonable implementation // will require more than 2^63 chars to represent a float value. const long long narrow = static_cast(N); result.resize_and_overwrite( N, [&](char* buffer, size_type) -> size_type { // we know that a formatting error will not occur, so // we assume that the result is always positive std::size_t length = std::snprintf(buffer, N + 1, "%f", value); if (length > N) { // the + 4 is for the decimal, 'e', // its sign, and the sign of the integral portion const int reserved_count = (std::max)(2, count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = narrow > reserved_count ? N - reserved_count : 0; // switch to scientific notation length = std::snprintf(buffer, N + 1, "%.*e", precision, value); } return length; } ); return result; #endif } template inline static_string to_static_string_float_impl(float value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_string(value); #else return to_static_string_float_impl(static_cast(value)); #endif } template inline static_string to_static_string_float_impl(long double value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_string(value); #else using size_type = typename static_string::size_type; static_string result; // we have to assume here that no reasonable implementation // will require more than 2^63 chars to represent a float value. const long long narrow = static_cast(N); result.resize_and_overwrite( N, [&](char* buffer, size_type)->size_type { // snprintf returns the number of characters // that would have been written // we know that a formatting error will not occur, so // we assume that the result is always positive std::size_t length = std::snprintf(buffer, N + 1, "%Lf", value); if (length > N) { // the + 4 is for the decimal, 'e', // its sign, and the sign of the integral portion const int reserved_count = (std::max)(2, count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = narrow > reserved_count ? N - reserved_count : 0; // switch to scientific notation length = std::snprintf(buffer, N + 1, "%.*Le", precision, value); } return length; } ); return result; #endif } #ifdef BOOST_STATIC_STRING_HAS_WCHAR #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) template inline static_wstring cpp26_to_static_wstring(FloatingPoint value) noexcept { using size_type = typename static_wstring::size_type; static_wstring result; result.resize_and_overwrite( N, [&](wchar_t* buffer, size_type) -> size_type { const auto formatted = std::format_to_n(buffer, N, L"{}", value); return formatted.size; } ); return result; } #endif template inline static_wstring to_static_wstring_float_impl(double value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_wstring(value); #else using size_type = typename static_wstring::size_type; static_wstring result; // we have to assume here that no reasonable implementation // will require more than 2^63 chars to represent a float value. const long long narrow = static_cast(N); result.resize_and_overwrite( N, [&](wchar_t* buffer, size_type) -> size_type { // swprintf returns a negative number if it can't // fit all the characters in the buffer. // mingw has a non-standard swprintf, so // this just covers all the bases. short // circuit evaluation will ensure that the // second operand is not evaluated on conforming // implementations. int num_written = std::swprintf(buffer, N + 1, L"%f", value); if (num_written < 0 || num_written > narrow) { // the + 4 is for the decimal, 'e', // its sign, and the sign of the integral portion const int reserved_count = (std::max)(2, count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = narrow > reserved_count ? N - reserved_count : 0; // switch to scientific notation num_written = std::swprintf(buffer, N + 1, L"%.*e", precision, value); } return num_written; } ); return result; #endif } template inline static_wstring to_static_wstring_float_impl(float value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_wstring(value); #else return to_static_wstring_float_impl(static_cast(value)); #endif } template inline static_wstring to_static_wstring_float_impl(long double value) noexcept { #if defined(BOOST_STATIC_STRING_USE_STD_FORMAT) return cpp26_to_static_wstring(value); #else using size_type = typename static_wstring::size_type; static_wstring result; // we have to assume here that no reasonable implementation // will require more than 2^63 chars to represent a float value. const long long narrow = static_cast(N); result.resize_and_overwrite( N, [&](wchar_t* buffer, size_type) -> size_type { // swprintf returns a negative number if it can't // fit all the characters in the buffer. // mingw has a non-standard swprintf, so // this just covers all the bases. short // circuit evaluation will ensure that the // second operand is not evaluated on conforming // implementations. int num_written = std::swprintf(buffer, N + 1, L"%Lf", value); if (num_written < 0 || num_written > narrow) { // the + 4 is for the decimal, 'e', // its sign, and the sign of the integral portion const int reserved_count = (std::max)(2, count_digits( std::numeric_limits::max_exponent10)) + 4; const int precision = narrow > reserved_count ? N - reserved_count : 0; // switch to scientific notation num_written = std::swprintf(buffer, N + 1, L"%.*Le", precision, value); } return num_written; } ); return result; #endif } #endif #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic pop #endif template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline ForwardIterator find_not_of( ForwardIterator first, ForwardIterator last, const CharT* str, std::size_t n) noexcept { for (; first != last; ++first) if (!Traits::find(str, n, *first)) return first; return last; } // constexpr search for C++14 template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline ForwardIt1 search( ForwardIt1 first, ForwardIt1 last, ForwardIt2 s_first, ForwardIt2 s_last, BinaryPredicate p) { for (; ; ++first) { ForwardIt1 it = first; for (ForwardIt2 s_it = s_first; ; ++it, ++s_it) { if (s_it == s_last) return first; if (it == last) return last; if (!p(*it, *s_it)) break; } } } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline InputIt find_first_of( InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinaryPredicate p) { for (; first != last; ++first) for (ForwardIt it = s_first; it != s_last; ++it) if (p(*first, *it)) return first; return last; } // KRYSTIAN TODO: add a constexpr rotate // Check if a pointer lies within the range {src_first, src_last) // without unspecified behavior, allowing it to be used // in a constant evaluation. template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool ptr_in_range( const T* src_first, const T* src_last, const T* ptr) { #if defined(BOOST_STATIC_STRING_CPP14) && \ defined(BOOST_STATIC_STRING_IS_CONST_EVAL) // Our second best option is to use is_constant_evaluated // and a loop that checks for equality, since equality for // pointer to object types is never unspecified in this case. if (BOOST_STATIC_STRING_IS_CONST_EVAL) { for (; src_first != src_last; ++src_first) if (ptr == src_first) return true; return false; } #endif // We want to make this usable in constant expressions as much as possible // while retaining the guarentee that the comparison has a strict total ordering. // We also want this to be fast. Since different compilers have differing levels // of conformance, we will settle for the best option that is available. // We don't care about this in C++11, since this function would have // no applications in constant expressions. #if defined(BOOST_STATIC_STRING_CPP14) && \ defined(BOOST_STATIC_STRING_NO_PTR_COMP_FUNCTIONS) // If library comparison functions don't work, // we can use try builtin comparison operators instead. return ptr >= src_first && ptr < src_last; #else // Use the library comparison functions if we can't use // is_constant_evaluated or if we don't need to. return std::greater_equal()(ptr, src_first) && std::less()(ptr, src_last); #endif } // This workaround is for gcc 5, // which prohibits throw expressions in constexpr // functions, but for some reason permits them in // constructors. #ifdef BOOST_STATIC_STRING_GCC5_BAD_CONSTEXPR template struct throw_exception { BOOST_STATIC_STRING_NORETURN BOOST_STATIC_STRING_CPP14_CONSTEXPR throw_exception(const char* msg) { BOOST_STATIC_STRING_THROW(Exception(msg)); } }; #else template BOOST_STATIC_STRING_NORETURN inline void throw_exception(const char* msg) { BOOST_STATIC_STRING_THROW(Exception(msg)); } #endif } // detail #endif //-------------------------------------------------------------------------- // // static_string // //-------------------------------------------------------------------------- /** A fixed-capacity string. These objects behave like `std::string` except that the storage is not dynamically allocated but rather fixed in size, and stored in the object itself. These strings offer performance advantages when an algorithm can execute with a reasonable upper limit on the size of a value. @par Aliases The following alias templates are provided for convenience: @code template using static_string = basic_static_string>; @endcode @code template using static_wstring = basic_static_string>; @endcode @code template using static_u16string = basic_static_string>; @endcode @code template using static_u32string = basic_static_string>; @endcode Addtionally, the alias template `static_u8string` is provided in C++20 @code template using static_u8string = basic_static_string>; @endcode @see @ref to_static_string. */ template> class basic_static_string #ifndef BOOST_STATIC_STRING_DOCS : private detail::static_string_base #endif { private: template friend class basic_static_string; public: //-------------------------------------------------------------------------- // // Member types // //-------------------------------------------------------------------------- /// The traits type. using traits_type = Traits; /// The character type. using value_type = typename traits_type::char_type; /// The size type. using size_type = std::size_t; /// The difference type. using difference_type = std::ptrdiff_t; /// The pointer type. using pointer = value_type*; /// The reference type. using reference = value_type&; /// The constant pointer type. using const_pointer = const value_type*; /// The constant reference type. using const_reference = const value_type&; /// The iterator type. using iterator = value_type*; /// The constant iterator type. using const_iterator = const value_type*; /// The reverse iterator type. using reverse_iterator = std::reverse_iterator; /// The constant reverse iterator type. using const_reverse_iterator = std::reverse_iterator; #ifdef BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW /// The string view type. using string_view_type = basic_string_view; #endif //-------------------------------------------------------------------------- // // Constants // //-------------------------------------------------------------------------- /// Maximum size of the string excluding any null terminator static constexpr size_type static_capacity = N; /// A special index static constexpr size_type npos = size_type(-1); //-------------------------------------------------------------------------- // // Construction // //-------------------------------------------------------------------------- /** Constructor. Construct an empty string */ BOOST_STATIC_STRING_CPP11_CONSTEXPR basic_static_string() noexcept { #ifdef BOOST_STATIC_STRING_CPP20 term(); #endif } /** Constructor. Construct the string with `count` copies of character `ch`. The behavior is undefined if `count >= npos` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( size_type count, value_type ch) { assign(count, ch); } /** Constructor. Construct with a substring (pos, other.size()) of `other`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( const basic_static_string& other, size_type pos) { assign(other, pos); } /** Constructor. Construct with a substring (pos, count) of `other`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( const basic_static_string& other, size_type pos, size_type count) { assign(other, pos, count); } /** Constructor. Construct with the first `count` characters of `s`, including nulls. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( const_pointer s, size_type count) { assign(s, count); } /** Constructor. Construct from a null terminated string. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string(const_pointer s) { assign(s); } /** Constructor. Construct from a range of characters */ template ::value>::type* = nullptr #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( InputIterator first, InputIterator last) { // KRYSTIAN TODO: we can use a better algorithm if this is a forward iterator assign(first, last); } /** Constructor. Copy constructor. */ basic_static_string(const basic_static_string& other) = default; /** Constructor. Copy constructor. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( const basic_static_string& other) { assign(other); } /** Constructor. Construct from an initializer list */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string(std::initializer_list init) { assign(init.begin(), init.size()); } /** Constructor. Construct from a object convertible to `string_view_type` */ template #endif > explicit BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string(const T& t) { assign(t); } /** Constructor. Construct from any object convertible to `string_view_type`. The range (pos, n) is extracted from the value obtained by converting `t` to `string_view_type`, and used to construct the string. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string( const T& t, size_type pos, size_type n) { assign(t, pos, n); } //-------------------------------------------------------------------------- // // Assignment // //-------------------------------------------------------------------------- /** Assign to the string. Replaces the contents with those of the string `s`. @par Complexity Linear in `s.size()`. @par Exception Safety Strong guarantee. @return `*this` @param s The string to replace the contents with. @throw std::length_error `s.size() > max_size()`. */ basic_static_string& operator=(const basic_static_string& s) = default; /** Assign to the string. Replaces the contents with those of the string `s`. @par Complexity Linear in `s.size()`. @par Exception Safety Strong guarantee. @tparam M The size of the other string. @return `*this` @param s The string to replace the contents with. @throw std::length_error `s.size() > max_size()`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator=(const basic_static_string& s) { return assign(s); } /** Assign to the string. Replaces the contents with those of `{s, s + traits_type::length(s))`. @par Complexity Linear in `count`. @par Exception Safety Strong guarantee. @return `*this` @param s A pointer to the string to copy from. @throw std::length_error `traits_type::length(s) > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator=(const_pointer s) { return assign(s); } /** Assign to the string. Replaces the contents with a single copy of the character `ch`. @par Complexity Constant. @par Exception Safety Strong guarantee. @return `*this` @param ch The character to assign to. @throw std::length_error `count > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator=(value_type ch) { return assign_char(ch, std::integral_constant 0)>{}); } /** Assign to the string. Replaces the contents with those of the initializer list `ilist`. @par Complexity Linear in `init.size()`. @par Exception Safety Strong guarantee. @return `*this` @param ilist The initializer list to copy from. @throw std::length_error `ilist.size() > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator=(std::initializer_list ilist) { return assign(ilist); } /** Assign to the string. Replaces the contents with those of `sv`, where `sv` is `string_view_type(t)`. @par Complexity Linear in `sv.size()`. @par Exception Safety Strong guarantee. @note The view can contain null characters. @tparam T A type convertible to `string_view_type`. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The object to assign from. @throw std::length_error `sv.size() > max_size()`. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator=(const T& t) { return assign(t); } /** Assign to the string. Replaces the contents with `count` copies of character `ch`. @par Complexity Linear in `count`. @par Exception Safety Strong guarantee. @return `*this` @param count The size of the resulting string. @param ch The value to initialize characters of the string with. @throw std::length_error `count > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign( size_type count, value_type ch); /** Assign to the string. Replaces the contents with those of the string `s`. @par Complexity Linear in `s.size()`. @par Exception Safety Strong guarantee. @tparam M The size of the other string. @return `*this` @param s The string to replace the contents with. @throw std::length_error `s.size() > max_size()`. */ template::type* = nullptr #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign(const basic_static_string& s) { return assign_unchecked(s.data(), s.size()); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign(const basic_static_string& s) noexcept { if (data() == s.data()) return *this; return assign_unchecked(s.data(), s.size()); } template N)>::type* = nullptr> BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign(const basic_static_string& s) { return assign(s.data(), s.size()); } #endif /** Assign to the string. Replaces the contents with those of the string `sub`, where `sub` is `s.substr(pos, count)`. @par Complexity Linear in `sub.size()`. @par Exception Safety Strong guarantee. @tparam M The capacity of the other string. @return `*this` @param s The string to replace the contents with. @param pos The index at which to begin the substring. @param count The size of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `sub.size() > max_size()`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign( const basic_static_string& s, size_type pos, size_type count = npos) { return assign(s.data() + pos, s.capped_length(pos, count)); } /** Assign to the string. Replaces the contents with those of `{s, s + count)`. @par Complexity Linear in `count`. @par Exception Safety Strong guarantee. @note The range can contain null characters. @return `*this` @param count The number of characters to copy. @param s A pointer to the string to copy from. @throw std::length_error `count > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign( const_pointer s, size_type count); /** Assign to the string. Replaces the contents with those of `{s, s + traits_type::length(s))`. @par Complexity Linear in `count`. @par Exception Safety Strong guarantee. @return `*this` @param s A pointer to the string to copy from. @throw std::length_error `traits_type::length(s) > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign(const_pointer s) { return assign(s, traits_type::length(s)); } /** Assign to the string. Replaces the contents with the characters in the range `{first, last)`. @par Complexity Linear in `std::distance(first, last)`. @par Exception Safety Strong guarantee. @tparam InputIterator The type of the iterators. @par Constraints `InputIterator` satisfies __InputIterator__. @return `*this` @param first An iterator referring to the first character to assign. @param last An iterator past the end of the range to assign from. @throw std::length_error `std::distance(first, last) > max_size()`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR #ifdef BOOST_STATIC_STRING_DOCS basic_static_string& #else typename std::enable_if< detail::is_input_iterator::value, basic_static_string&>::type #endif assign( InputIterator first, InputIterator last); /** Assign to the string. Replaces the contents with those of the initializer list `ilist`. @par Complexity Linear in `init.size()`. @par Exception Safety Strong guarantee. @return `*this` @param ilist The initializer list to copy from. @throw std::length_error `ilist.size() > max_size()`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign( std::initializer_list ilist) { return assign(ilist.begin(), ilist.end()); } /** Assign to the string. Replaces the contents with those of `sv`, where `sv` is `string_view_type(t)`. @par Complexity Linear in `sv.size()`. @par Exception Safety Strong guarantee. @note The view can contain null characters. @tparam T A type convertible to `string_view_type`. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The object to assign from. @throw std::length_error `sv.size() > max_size()`. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign(const T& t) { detail::common_string_view_type sv = t; return assign(sv.data(), sv.size()); } /** Assign to the string. Replaces the contents with those of the substring `sv`, where `sv` is `string_view_type(t).substr(pos, count)`. @par Complexity Linear in `sv.size()`. @par Exception Safety Strong guarantee. @note The view can contain null characters. @tparam T A type convertible to `string_view_type`. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The object to assign from. @param pos The index at which to begin the substring. @param count The size of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `sv.size() > max_size()`. */ template #endif > basic_static_string& assign( const T& t, size_type pos, size_type count = npos) { detail::common_string_view_type sv = t; if( pos > sv.size() ) detail::throw_exception( "pos >= t.size()"); std::size_t rlen = (std::min)( count, sv.size() - pos ); return assign(sv.data() + pos, rlen); } //-------------------------------------------------------------------------- // // Element access // //-------------------------------------------------------------------------- /** Access a character with bounds checking. Returns a reference to the character at index `pos`. @par Complexity Constant. @par Exception Safety Strong guarantee. @param pos The index to access. @throw std::out_of_range `pos >= size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR reference at(size_type pos) { if (pos >= size()) detail::throw_exception( "pos >= size()"); return data()[pos]; } /** Access a character with bounds checking. Returns a reference to the character at index `pos`. @par Complexity Constant. @par Exception Safety Strong guarantee. @param pos The index to access. @throw std::out_of_range `pos >= size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_reference at(size_type pos) const { if (pos >= size()) detail::throw_exception( "pos >= size()"); return data()[pos]; } /** Access a character. Returns a reference to the character at index `pos`. @par Complexity Constant. @par Precondition `pos >= size` @param pos The index to access. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR reference operator[](size_type pos) noexcept { return data()[pos]; } /** Access a character. Returns a reference to the character at index `pos`. @par Complexity Constant. @par Precondition `pos >= size` @param pos The index to access. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_reference operator[](size_type pos) const noexcept { return data()[pos]; } /** Return the first character. Returns a reference to the first character. @par Complexity Constant. @par Precondition `not empty()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR reference front() noexcept { return data()[0]; } /** Return the first character. Returns a reference to the first character. @par Complexity Constant. @par Precondition `not empty()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_reference front() const noexcept { return data()[0]; } /** Return the last character. Returns a reference to the last character. @par Complexity Constant. @par Precondition `not empty()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR reference back() noexcept { return data()[size() - 1]; } /** Return the last character. Returns a reference to the last character. @par Complexity Constant. @par Precondition `not empty()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_reference back() const noexcept { return data()[size() - 1]; } /** Return a pointer to the string. Returns a pointer to the underlying array serving as storage. The value returned is such that the range `{data(), data() + size())` is always a valid range, even if the container is empty. @par Complexity Constant. @note The value returned from this function is never never a null pointer value. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR pointer data() noexcept { return this->data_impl(); } /** Return a pointer to the string. Returns a pointer to the underlying array serving as storage. The value returned is such that the range `{data(), data() + size())` is always a valid range, even if the container is empty. @par Complexity Constant. @note The value returned from this function is never never a null pointer value. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_pointer data() const noexcept { return this->data_impl(); } /** Return a pointer to the string. Returns a pointer to the underlying array serving as storage. The value returned is such that the range `{c_str(), c_str() + size())` is always a valid range, even if the container is empty. @par Complexity Constant. @note The value returned from this function is never never a null pointer value. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR const_pointer c_str() const noexcept { return data(); } #ifdef BOOST_STATIC_STRING_DOCS /** Convert to a string view referring to the string. Returns a string view referring to the underlying character string. @par Complexity Constant. */ BOOST_STATIC_STRING_CPP11_CONSTEXPR operator string_view_type() const noexcept { return string_view_type(data(), size()); } #else #ifdef BOOST_STATIC_STRING_HAS_STD_STRING_VIEW BOOST_STATIC_STRING_CPP11_CONSTEXPR operator std::basic_string_view() const noexcept { return std::basic_string_view(data(), size()); } #endif #ifndef BOOST_STATIC_STRING_STANDALONE BOOST_STATIC_STRING_CPP11_CONSTEXPR operator ::boost::basic_string_view() const noexcept { return ::boost::basic_string_view(data(), size()); } BOOST_STATIC_STRING_CPP11_CONSTEXPR operator ::boost::core::basic_string_view() const noexcept { return ::boost::core::basic_string_view(data(), size()); } #endif #endif //-------------------------------------------------------------------------- // // Iterators // //-------------------------------------------------------------------------- /// Return an iterator to the beginning. BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator begin() noexcept { return data(); } /// Return an iterator to the beginning. BOOST_STATIC_STRING_CPP14_CONSTEXPR const_iterator begin() const noexcept { return data(); } /// Return an iterator to the beginning. BOOST_STATIC_STRING_CPP14_CONSTEXPR const_iterator cbegin() const noexcept { return data(); } /// Return an iterator to the end. BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator end() noexcept { return data() + size(); } /// Return an iterator to the end. BOOST_STATIC_STRING_CPP14_CONSTEXPR const_iterator end() const noexcept { return data() + size(); } /// Return an iterator to the end. BOOST_STATIC_STRING_CPP14_CONSTEXPR const_iterator cend() const noexcept { return data() + size(); } /// Return a reverse iterator to the beginning. BOOST_STATIC_STRING_CPP17_CONSTEXPR reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; } /// Return a reverse iterator to the beginning. BOOST_STATIC_STRING_CPP17_CONSTEXPR const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{cend()}; } /// Return a reverse iterator to the beginning. BOOST_STATIC_STRING_CPP17_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; } /// Return a reverse iterator to the end. BOOST_STATIC_STRING_CPP17_CONSTEXPR reverse_iterator rend() noexcept { return reverse_iterator{begin()}; } /// Return a reverse iterator to the end. BOOST_STATIC_STRING_CPP17_CONSTEXPR const_reverse_iterator rend() const noexcept { return const_reverse_iterator{cbegin()}; } /// Return a reverse iterator to the end. BOOST_STATIC_STRING_CPP17_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; } //-------------------------------------------------------------------------- // // Capacity // //-------------------------------------------------------------------------- /** Return if the string is empty. Returns whether the string contains no characters. @par Complexity Constant. @return `size() == 0` */ BOOST_STATIC_STRING_NODISCARD BOOST_STATIC_STRING_CPP11_CONSTEXPR bool empty() const noexcept { return size() == 0; } /** Return the size of the string. Returns the number of characters stored in the string, excluding the null terminator. @par Complexity Constant. */ BOOST_STATIC_STRING_CPP11_CONSTEXPR size_type size() const noexcept { return this->size_impl(); } /** Return the size of the string. Returns the number of characters stored in the string, excluding the null terminator. @par Complexity Constant. */ BOOST_STATIC_STRING_CPP11_CONSTEXPR size_type length() const noexcept { return size(); } /** Return the number of characters that can be stored. Returns the maximum size of the string, excluding the null terminator. The returned value is always `N`. @par Complexity Constant. */ BOOST_STATIC_STRING_CPP11_CONSTEXPR size_type max_size() const noexcept { return N; } /** Increase the capacity. This function has no effect. @throw std::length_error `n > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void reserve(size_type n) { if (n > max_size()) detail::throw_exception( "n > max_size()"); } /** Return the number of characters that can be stored. Returns the maximum size of the string, excluding the null terminator. The returned value is always `N`. @par Complexity Constant. */ BOOST_STATIC_STRING_CPP11_CONSTEXPR size_type capacity() const noexcept { return max_size(); } /** Request the removal of unused capacity. This function has no effect. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void shrink_to_fit() noexcept { } //-------------------------------------------------------------------------- // // Operations // //-------------------------------------------------------------------------- /** Clear the contents. Erases all characters from the string. After this call, @ref size() returns zero. @par Complexity Linear in @ref size(). @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void clear() noexcept { this->set_size(0); term(); } /** Insert into the string. Inserts `count` copies of `ch` at the position `index`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param index The index to insert at. @param count The number of characters to insert. @param ch The character to insert. @throw std::length_error `size() + count > max_size()` @throw std::out_of_range `index > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, size_type count, value_type ch) { if (index > size()) detail::throw_exception( "index > size()"); insert(begin() + index, count, ch); return *this; } /** Insert into the string. Inserts the null-terminated character string pointed to by `s` of length `count` at the position `index` where `count` is `traits_type::length(s)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param index The index to insert at. @param s The string to insert. @throw std::length_error `size() + count > max_size()` @throw std::out_of_range `index > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const_pointer s) { return insert(index, s, traits_type::length(s)); } /** Insert into the string. Inserts `count` characters of the string pointed to by `s` at the position `index`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param index The index to insert at. @param s The string to insert. @param count The length of the string to insert. @throw std::length_error `size() + count > max_size()` @throw std::out_of_range `index > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const_pointer s, size_type count) { if (index > size()) detail::throw_exception( "index > size()"); insert(data() + index, s, s + count); return *this; } /** Insert into the string. Inserts the string `str` at the position `index`. @par Exception Safety Strong guarantee. @note The insertion is done unchecked when the capacity of `str` differs from that of the string the function is called on. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam M The size of the input string. @return `*this` @param index The index to insert at. @param str The string to insert. @throw std::length_error `size() + str.size() > max_size()` @throw std::out_of_range `index > size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const basic_static_string& str) { return insert_unchecked(index, str.data(), str.size()); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const basic_static_string& str) { return insert(index, str.data(), str.size()); } #endif /** Insert into the string. Inserts a string, obtained by `str.substr(index_str, count)` at the position `index`. @par Exception Safety Strong guarantee. @note The insertion is done unchecked when the capacity of `str` differs from that of the string the function is called on. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam M The size of the input string. @return `*this` @param index The index to insert at. @param str The string from which to insert. @param index_str The index in `str` to start inserting from. @param count The number of characters to insert. The default argument for this parameter is @ref npos. @throw std::length_error `size() + str.substr(index_str, count).size() > max_size()` @throw std::out_of_range `index > size()` @throw std::out_of_range `index_str > str.size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const basic_static_string& str, size_type index_str, size_type count = npos) { return insert_unchecked(index, str.data() + index_str, str.capped_length(index_str, count)); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const basic_static_string& str, size_type index_str, size_type count = npos) { return insert(index, str.data() + index_str, str.capped_length(index_str, count)); } #endif /** Insert into the string. Inserts the character `ch` before the character pointed by `pos`. @par Precondition `pos` shall be vaild within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return An iterator which refers to the first inserted character or `pos` if no characters were inserted @param pos The index to insert at. @param ch The character to insert. @throw std::length_error `size() + 1 > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator insert( const_iterator pos, value_type ch) { return insert(pos, 1, ch); } /** Insert into the string. Inserts `count` copies of `ch` before the character pointed by `pos`. @par Precondition `pos` shall be valid within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return An iterator which refers to the first inserted character or `pos` if no characters were inserted @param pos The position to insert at. @param count The number of characters to insert. @param ch The character to insert. @throw std::length_error `size() + count > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator insert( const_iterator pos, size_type count, value_type ch); /** Insert into the string. Inserts characters from the range `{first, last)` before the character pointed to by `pos`. @par Precondition `pos` shall be valid within `{data(), data() + size()}`, `{first, last)` shall be a valid range @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam InputIterator The type of the iterators. @par Constraints `InputIterator` satisfies __InputIterator__ and does not satisfy __ForwardIterator__. @return An iterator which refers to the first inserted character or `pos` if no characters were inserted @param pos The position to insert at. @param first An iterator representing the first character to insert. @param last An iterator representing one past the last character to insert. @throw std::length_error `size() + insert_count > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR #ifdef BOOST_STATIC_STRING_DOCS iterator #else typename std::enable_if< detail::is_input_iterator< InputIterator>::value && !detail::is_forward_iterator< InputIterator>::value, iterator>::type #endif insert( const_iterator pos, InputIterator first, InputIterator last); #ifndef BOOST_STATIC_STRING_DOCS template BOOST_STATIC_STRING_CPP14_CONSTEXPR typename std::enable_if< detail::is_forward_iterator< ForwardIterator>::value, iterator>::type insert( const_iterator pos, ForwardIterator first, ForwardIterator last); #endif /** Insert into the string. Inserts characters from `ilist` before `pos`. @par Precondition `pos` shall be valid within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return An iterator which refers to the first inserted character or `pos` if no characters were inserted @param pos The position to insert at. @param ilist The initializer list from which to insert. @throw std::length_error `size() + ilist.size() > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator insert( const_iterator pos, std::initializer_list ilist) { return insert_unchecked(pos, ilist.begin(), ilist.size()); } /** Insert into the string. Constructs a temporary `string_view_type` object `sv` from `t` and inserts `{sv.begin(), sv.end())` at `index`. @par Precondition `index` shall be valid within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @param index The index to insert at. @param t The string to insert from. @throw std::length_error `size() + sv.size() > max_size()` @throw std::out_of_range `index > size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const T& t) { detail::common_string_view_type sv = t; return insert(index, sv.data(), sv.size()); } /** Insert into the string. Constructs a temporary `string_view_type` object `sv` from `t` and inserts `sv.substr(index_str, count)` at `index`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return `*this` @param index The index to insert at. @param t The string to insert from. @param index_str The index in the temporary `string_view_type` object to start the substring from. @param count The number of characters to insert. @throw std::length_error `size() + sv.size() > max_size()` @throw std::out_of_range `index > size()` @throw std::out_of_range `index_str > sv.size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert( size_type index, const T& t, size_type index_str, size_type count = npos) { detail::common_string_view_type sv(t); if ( index_str > sv.size() ) detail::throw_exception("index_str > t.size()"); return insert(index, sv.data() + index_str, (std::min)(sv.size() - index_str, count)); } /** Erase from the string. Erases `num` characters from the string, starting at `index`. `num` is determined as the smaller of `count` and `size() - index`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param index The index to erase at. The default argument for this parameter is `0`. @param count The number of characters to erase. The default argument for this parameter is @ref npos. @throw std::out_of_range `index > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& erase( size_type index = 0, size_type count = npos) { erase(data() + index, data() + index + capped_length(index, count)); return *this; } /** Erase from the string. Erases the character at `pos`. @par Preconditions `pos` shall be valid within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return An iterator referring to character immediately following the erased character, or @ref end() if one does not exist. @param pos An iterator referring to the character to erase. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator erase(const_iterator pos) { BOOST_STATIC_STRING_ASSERT(!empty()); return erase(pos, pos + 1); } /** Erase from the string. Erases the characters in the range `{first, last)`. @par Precondition `{first, last}` shall be valid within `{data(), data() + size()}` @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return An iterator referring to the character `last` previously referred to, or @ref end() if one does not exist. @param first An iterator referring to the first character to erase. @param last An iterator past the last character to erase. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator erase( const_iterator first, const_iterator last); /** Append a character. Appends a character to the end of the string. @par Exception Safety Strong guarantee. @param ch The character to append. @throw std::length_error `size() >= max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void push_back(value_type ch); /** Remove the last character. Removes a character from the end of the string. @par Precondition `not empty()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void pop_back() noexcept { BOOST_STATIC_STRING_ASSERT(!empty()); this->set_size(size() - 1); term(); } /** Append to the string. Appends `count` copies of `ch` to the end of the string. @par Exception Safety Strong guarantee. @return `*this` @param count The number of characters to append. @param ch The character to append. @throw std::length_error `size() + count > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( size_type count, value_type ch); /** Append to the string. Appends `s` to the end of the string. @par Exception Safety Strong guarantee. @tparam M The size of the string to append. @return `*this` @param s The string to append. @throw std::length_error `size() + s.size() > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( const basic_static_string& s) { return append(s.data(), s.size()); } /** Append to the string. Appends the substring `sub` to the end of the string, where `sub` is `s.substr(pos, count)`. @par Exception Safety Strong guarantee. @tparam M The size of the string to append. @return `*this` @param s The string to append. @param pos The index at which to begin the substring. @param count The size of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `size() + sub.size() > max_size()` @throw std::out_of_range `pos > s.size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( const basic_static_string& s, size_type pos, size_type count = npos) { return append(s.data() + pos, s.capped_length(pos, count)); } /** Append to the string. Appends `count` characters from the string pointed to by `s` to the end of the string. @par Exception Safety Strong guarantee. @note The string can contain null characters. @return `*this` @param s The string to append. @param count The number of characters to append. @throw std::length_error `size() + count > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( const_pointer s, size_type count); /** Append to the string. Appends `count` characters from the string pointed to by `s` to the end of the string, where `count` is `traits_type::length(s)`. @par Exception Safety Strong guarantee. @return `*this` @param s The string to append. @throw std::length_error `size() + count > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append(const_pointer s) { return append(s, traits_type::length(s)); } // KRYSTIAN TODO: change exception safety /** Append to the string. Appends characters from the range `{first, last)` to the end of the string. @par Precondition `{first, last)` shall be a valid range @par Exception Safety Strong guarantee. @tparam InputIterator The type of the iterators. @par Constraints `InputIterator` satisfies __InputIterator__. @return `*this` @param first An iterator referring to the first character to append. @param last An iterator past the end of last character to append. @throw std::length_error `size() + std::distance(first, last) > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR #ifdef BOOST_STATIC_STRING_DOCS basic_static_string& #else typename std::enable_if< detail::is_input_iterator::value, basic_static_string&>::type #endif append( InputIterator first, InputIterator last) { this->set_size(size() + read_back(true, first, last)); return term(); } /** Append to the string. Appends the characters from `ilist` to the end of the string. @par Exception Safety Strong guarantee. @return `*this` @param ilist The initializer list to append. @throw std::length_error `size() + ilist.size() > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( std::initializer_list ilist) { return append(ilist.begin(), ilist.size()); } /** Append to the string. Appends `sv` to the end of the string, where `sv` is `string_view_type(t)`. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The string to append. @throw std::length_error `size() + sv.size() > max_size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append(const T& t) { detail::common_string_view_type sv = t; return append(sv.data(), sv.size()); } /** Append to the string. Appends the substring `sv` to the end of the string, where `sv` is `string_view_type(t).substr(pos, count)`. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The object to append. @param pos The index at which to begin the substring. @param count The size of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `size() + sv.size() > max_size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& append( const T& t, size_type pos, size_type count = npos) { detail::common_string_view_type sv = t; if ( pos > sv.size() ) detail::throw_exception("pos > t.size()"); return append(sv.data() + pos, (std::min)(sv.size() - pos, count)); } /** Append to the string. Appends `s` to the end of the string. @par Exception Safety Strong guarantee. @tparam M The size of the string to append. @return `*this` @param s The string to append. @throw std::length_error `size() + s.size() > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator+=( const basic_static_string& s) { return append(s); } /** Append to the string. Appends a character to the end of the string. @par Exception Safety Strong guarantee. @param ch The character to append. @throw std::length_error `size() >= max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator+=(value_type ch) { push_back(ch); return *this; } /** Append to the string. Appends `count` characters from the string pointed to by `s` to the end of the string, where `count` is `traits_type::length(s)`. @par Exception Safety Strong guarantee. @return `*this` @param s The string to append. @throw std::length_error `size() + count > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator+=(const_pointer s) { return append(s); } /** Append to the string. Appends the characters from `ilist` to the end of the string. @par Exception Safety Strong guarantee. @return `*this` @param ilist The initializer list to append. @throw std::length_error `size() + ilist.size() > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator+=( std::initializer_list ilist) { return append(ilist); } /** Append to the string. Appends `sv` to the end of the string, where `sv` is `string_view_type(t)`. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value @endcode @return `*this` @param t The string to append. @throw std::length_error `size() + sv.size() > max_size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& operator+=(const T& t) { return append(t); } /** Compare a string with the string. Let `comp` be `traits_type::compare(data(), s.data(), std::min(size(), s.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1` otherwise. @par Complexity Linear. @return The result of lexicographically comparing `s` and the string. @tparam M The size of the string to compare with. @param s The string to compare. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( const basic_static_string& s) const noexcept { return detail::lexicographical_compare( data(), size(), s.data(), s.size()); } /** Compare a string with the string. Let `sub` be `substr(pos1, count1)` and `comp` be `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @return The result of lexicographically comparing `sub` and `s`. @tparam M The size of the string to compare with. @param pos1 The index at which to begin the substring. @param count1 The size of the substring. @param s The string to compare. @throw std::out_of_range `pos1 > size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const basic_static_string& s) const { return detail::lexicographical_compare( data() + pos1, capped_length(pos1, count1), s.data(), s.size()); } /** Compare a string with the string. Let `sub1` be `substr(pos1, count1)`, `sub2` be `s.substr(pos2, count2)`, and `comp` be `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @return The result of lexicographically comparing `sub1` and `sub2`. @param pos1 The index at which to begin the substring. @param count1 The size of the substring. @param s The string to compare. @param pos2 The index at which to begin the substring to compare. @param count2 The size of the substring to compare. @throw std::out_of_range `pos1 > size()` @throw std::out_of_range `pos2 > s.size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const basic_static_string& s, size_type pos2, size_type count2 = npos) const { return detail::lexicographical_compare( data() + pos1, capped_length(pos1, count1), s.data() + pos2, s.capped_length(pos2, count2)); } /** Compare a string with the string. Let `len` be `traits_type::length(s)` and `comp` be `traits_type::compare(data(), s, std::min(size(), len)`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `size() == len`, `-1` if `size() < len`, and `1` otherwise. @par Complexity Linear. @return The result of lexicographically comparing `s` and the string. @param s The string to compare. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare(const_pointer s) const noexcept { return detail::lexicographical_compare( data(), size(), s, traits_type::length(s)); } /** Compare a string with the string. Let `sub` be `substr(pos1, count1)`, `len` be `traits_type::length(s)`, and `comp` be `traits_type::compare(sub.data(), s, std::min(size(), len)`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub.size() == len`, `-1` if `sub.size() < len`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @return The result of lexicographically comparing `s` and `sub`. @param pos1 The index at which to begin the substring. @param count1 The size of the substring. @param s The string to compare. @throw std::out_of_range `pos1 > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const_pointer s) const { return detail::lexicographical_compare( data() + pos1, capped_length(pos1, count1), s, traits_type::length(s)); } /** Compare a string with the string. Let `sub` be `substr(pos1, count1)`, and `comp` be `traits_type::compare(sub.data(), s, std::min(size(), count2)`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub.size() == count2`, `-1` if `sub.size() < count2`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @return The result of lexicographically comparing `s` and `sub`. @param pos1 The index at which to begin the substring. @param count1 The size of the substring. @param s The string to compare. @param count2 The length of the string to compare. @throw std::out_of_range `pos1 > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const_pointer s, size_type count2) const { return detail::lexicographical_compare( data() + pos1, capped_length(pos1, count1), s, count2); } /** Compare a string with the string. Let `s` be `string_view_type(t)` and `comp` be `traits_type::compare(data(), s.data(), std::min(size(), s.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `size() == s.size()`, `-1` if `size() < s.size()`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value. @endcode @return The result of lexicographically comparing `s` and the string. @param t The string to compare. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare(const T& t) const noexcept { detail::common_string_view_type sv = t; return detail::lexicographical_compare( data(), size(), sv.data(), sv.size()); } /** Compare a string with the string. Let `s` be `string_view_type(t)`, `sub` be `substr(pos1, count1)`, and `comp` be `traits_type::compare(sub.data(), s.data(), std::min(sub.size(), s.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub.size() == s.size()`, `-1` if `sub.size() < s.size()`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value. @endcode @return The result of lexicographically comparing `s` and `sub`. @param pos1 The index at which to begin the substring. @param count1 The length of the substring. @param t The string to compare. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const T& t) const { detail::common_string_view_type sv = t; return detail::lexicographical_compare( data() + pos1, capped_length(pos1, count1), sv.data(), sv.size()); } /** Compare a string with the string. Let `sub1` be `substr(pos1, count1)`, `sub2` be `string_view_type(t).substr(pos2, count2)`, and `comp` be `traits_type::compare(sub1.data(), sub2.data(), std::min(sub1.size(), sub2.size())`. If `comp != 0`, then the result is `comp`. Otherwise, the result is `0` if `sub1.size() == sub2.size()`, `-1` if `sub1.size() < sub2.size()`, and `1` otherwise. @par Complexity Linear. @par Exception Safety Strong guarantee. @tparam T The type of the object to convert. @par Constraints @code std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value. @endcode @return The result of lexicographically comparing `sub1` and `sub2`. @param pos1 The index at which to begin the substring in the string. @param count1 The length of the substring in the string. @param t The string to compare. @param pos2 The index at which to begin the substring in the string view. @param count2 The length of the substring in the string view. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR int compare( size_type pos1, size_type count1, const T& t, size_type pos2, size_type count2 = npos) const { detail::common_string_view_type sv = t; if ( pos2 > sv.size()) detail::throw_exception("pos2 > sv.size()"); return compare( pos1, count1, sv.data() + pos2, (std::min)(sv.size() - pos2, count2)); } /** Return a substring. Returns a substring of the string. @par Exception Safety Strong guarantee. @return A string object containing the characters `{data() + pos, std::min(count, size() - pos))`. @param pos The index to being the substring at. The default argument for this parameter is `0`. @param count The length of the substring. The default argument for this parameter is @ref npos. @throw std::out_of_range `pos > size()` */ #ifndef BOOST_STATIC_STRING_GCC5_BAD_CONSTEXPR BOOST_STATIC_STRING_CPP14_CONSTEXPR #endif basic_static_string substr( size_type pos = 0, size_type count = npos) const { return basic_static_string( data() + pos, capped_length(pos, count)); } #ifdef BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW /** Return a string view of a substring. Returns a view of a substring. @par Exception Safety Strong guarantee. @return A `string_view_type` object referring to `{data() + pos, std::min(count, size() - pos))`. @param pos The index to being the substring at. The default argument for this parameter is `0`. @param count The length of the substring. The default argument for this parameter is @ref npos. @throw std::out_of_range `pos > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR string_view_type subview( size_type pos = 0, size_type count = npos) const { return string_view_type( data() + pos, capped_length(pos, count)); } #endif /** Copy a substring to another string. Copies `std::min(count, size() - pos)` characters starting at index `pos` to the string pointed to by `dest`. @note The resulting string is not null terminated. @return The number of characters copied. @param count The number of characters to copy. @param dest The string to copy to. @param pos The index to begin copying from. The default argument for this parameter is `0`. @throw std::out_of_range `pos > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type copy( pointer dest, size_type count, size_type pos = 0) const { const auto num_copied = capped_length(pos, count); traits_type::copy(dest, data() + pos, num_copied); return num_copied; } /** Change the size of the string. Resizes the string to contain `n` characters. If `n > size()`, characters with the value `CharT()` are appended. Otherwise, `size()` is reduced to `n`. @param n The size to resize the string to. @throw std::out_of_range `n > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void resize(size_type n) { resize(n, value_type()); } /** Change the size of the string. Resizes the string to contain `n` characters. If `n > size()`, copies of `c` are appended. Otherwise, `size()` is reduced to `n`. @param n The size to resize the string to. @param c The characters to append if the size increases. @throw std::out_of_range `n > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void resize( size_type n, value_type c); /** Resize the string and overwrite its contents. Resizes the string to contain `n` characters, and uses the provided function object `op` to overwrite the string contents. The function object is called with two arguments: a pointer to the string internal buffer, and the size of the string. The function object shall return the number of characters written to the buffer, which shall be less than or equal to `n`. The string size is set to the value returned by the function object. @par Exception Safety Strong guarantee. However, if an exception is thrown by `std::move(op)(p, count)`, the behavior is undefined. @throw std::length_error `n > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR void resize_and_overwrite( size_type n, Operation op); /** Swap two strings. Swaps the contents of the string and `s`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @param s The string to swap with. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR void swap(basic_static_string& s) noexcept; /** Swap two strings. Swaps the contents of the string and `s`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam M The size of the string to swap with. @param s The string to swap with. @throw std::length_error `s.size() > max_size() || size() > s.max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR void swap(basic_static_string& s); /** Replace a part of the string. Replaces `rcount` characters starting at index `pos1` with those of `str`, where `rcount` is `std::min(n1, size() - pos1)`. @par Exception Safety Strong guarantee. @note The replacement is done unchecked when the capacity of `str` differs from that of the string the function is called on. All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam M The size of the input string. @return `*this` @param pos1 The index to replace at. @param n1 The number of characters to replace. @param str The string to replace with. @throw std::length_error `size() + (str.size() - rcount) > max_size()` @throw std::out_of_range `pos1 > size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const basic_static_string& str) { return replace_unchecked(pos1, n1, str.data(), str.size()); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const basic_static_string& str) { return replace(pos1, n1, str.data(), str.size()); } #endif /** Replace a part of the string. Replaces `rcount` characters starting at index `pos1` with those of `str.subview(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos1)`. @par Exception Safety Strong guarantee. @note The replacement is done unchecked when the capacity of `str` differs from that of the string the function is called on. All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param pos1 The index to replace at. @param n1 The number of characters to replace. @param str The string to replace with. @param pos2 The index to begin the substring. @param n2 The length of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `size() + (std::min(str.size(), n2) - rcount) > max_size()` @throw std::out_of_range `pos1 > size()` @throw std::out_of_range `pos2 > str.size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const basic_static_string& str, size_type pos2, size_type n2 = npos) { return replace_unchecked(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2)); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const basic_static_string& str, size_type pos2, size_type n2 = npos) { return replace(pos1, n1, str.data() + pos2, str.capped_length(pos2, n2)); } #endif /** Replace a part of the string. Constructs a temporary `string_view_type` object `sv` from `t`, and replaces `rcount` characters starting at index `pos1` with those of `sv`, where `rcount` is `std::min(n1, size() - pos1)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return `*this` @param pos1 The index to replace at. @param n1 The number of characters to replace. @param t The object to replace with. @throw std::length_error `size() + (sv.size() - rcount) > max_size()` @throw std::out_of_range `pos1 > size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const T& t) { detail::common_string_view_type sv = t; return replace(pos1, n1, sv.data(), sv.size()); } /** Replace a part of the string. Constructs a temporary `string_view_type` object `sv` from `t`, and replaces `rcount` characters starting at index `pos1` with those of `sv.substr(pos2, n2)`, where `rcount` is `std::min(n1, size() - pos)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return `*this` @param pos1 The index to replace at. @param n1 The number of characters to replace. @param t The object to replace with. @param pos2 The index to begin the substring. @param n2 The length of the substring. The default argument for this parameter is @ref npos. @throw std::length_error `size() + (std::min(n2, sv.size()) - rcount) > max_size()` @throw std::out_of_range `pos1 > size()` @throw std::out_of_range `pos2 > sv.size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos) { detail::common_string_view_type sv = t; if ( pos2 > sv.size()) detail::throw_exception("pos2 > t.size()"); return replace( pos1, n1, sv.data() + pos2, (std::min)(sv.size() - pos2, n2)); } /** Replace a part of the string. Replaces `rcount` characters starting at index `pos` with those of `{s, s + n2)`, where `rcount` is `std::min(n1, size() - pos)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param pos The index to replace at. @param n1 The number of characters to replace. @param s The string to replace with. @param n2 The length of the string to replace with. @throw std::length_error `size() + (n2 - rcount) > max_size()` @throw std::out_of_range `pos > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos, size_type n1, const_pointer s, size_type n2) { return replace(data() + pos, data() + pos + capped_length(pos, n1), s, n2); } /** Replace a part of the string. Replaces `rcount` characters starting at index `pos` with those of `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)` and `rcount` is `std::min(n1, size() - pos)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param pos The index to replace at. @param n1 The number of characters to replace. @param s The string to replace with. @throw std::length_error `size() + (len - rcount) > max_size()` @throw std::out_of_range `pos > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos, size_type n1, const_pointer s) { return replace(pos, n1, s, traits_type::length(s)); } /** Replace a part of the string. Replaces `rcount` characters starting at index `pos` with `n2` copies of `c`, where `rcount` is `std::min(n1, size() - pos)`. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param pos The index to replace at. @param n1 The number of characters to replace. @param n2 The number of characters to replace with. @param c The character to replace with. @throw std::length_error `size() + (n2 - rcount) > max_size()` @throw std::out_of_range `pos > size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( size_type pos, size_type n1, size_type n2, value_type c) { return replace(data() + pos, data() + pos + capped_length(pos, n1), n2, c); } /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with those of `str`. @par Precondition `{i1, i2)` is a valid range. @par Exception Safety Strong guarantee. @note The replacement is done unchecked when the capacity of `str` differs from that of the string the function is called on. All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam M The size of the input string. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator referring past the end of the last character to replace. @param str The string to replace with. @throw std::length_error `size() + (str.size() - std::distance(i1, i2)) > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, const basic_static_string& str) { return replace_unchecked(i1, i2, str.data(), str.size()); } #ifndef BOOST_STATIC_STRING_DOCS BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, const basic_static_string& str) { return replace(i1, i2, str.data(), str.size()); } #endif /** Replace a part of the string. Constructs a temporary `string_view_type` object `sv` from `t`, and replaces the characters in the range `{i1, i2)` with those of `sv`. @par Precondition `{i1, i2)` is a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator referring past the end of the last character to replace. @param t The object to replace with. @throw std::length_error `size() + (sv.size() - std::distance(i1, i2)) > max_size()` */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, const T& t) { detail::common_string_view_type sv = t; return replace(i1, i2, sv.data(), sv.data() + sv.size()); } /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with those of `{s, s + n)`. @par Precondition `{i1, i2)` is a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator referring past the end of the last character to replace. @param s The string to replace with. @param n The length of the string to replace with. @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, const_pointer s, size_type n) { return replace(i1, i2, s, s + n); } /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with those of `{s, s + len)`, where the length of the string `len` is `traits_type::length(s)`. @par Precondition `{i1, i2)` shall be a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator referring past the end of the last character to replace. @param s The string to replace with. @throw std::length_error `size() + (len - std::distance(i1, i2)) > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, const_pointer s) { return replace(i1, i2, s, traits_type::length(s)); } /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with `n` copies of `c`. @par Precondition `{i1, i2)` is a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator past the end of the last character to replace. @param n The number of characters to replace with. @param c The character to replace with. @throw std::length_error `size() + (n - std::distance(i1, i2)) > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, size_type n, value_type c); /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with those of `{j1, j2)`. @par Precondition `{i1, i2)` is a valid range. `{j1, j2)` is a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @tparam InputIterator The type of the iterators. @par Constraints `InputIterator` satisfies __InputIterator__ and does not satisfy __ForwardIterator__. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator referring past the end of the last character to replace. @param j1 An iterator referring to the first character to replace with. @param j2 An iterator referring past the end of the last character to replace with. @throw std::length_error `size() + (inserted - std::distance(i1, i2)) > max_size()` */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR #ifdef BOOST_STATIC_STRING_DOCS basic_static_string& #else typename std::enable_if< detail::is_input_iterator< InputIterator>::value && !detail::is_forward_iterator< InputIterator>::value, basic_static_string&>::type #endif replace( const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); #ifndef BOOST_STATIC_STRING_DOCS template BOOST_STATIC_STRING_CPP14_CONSTEXPR typename std::enable_if< detail::is_forward_iterator< ForwardIterator>::value, basic_static_string&>::type replace( const_iterator i1, const_iterator i2, ForwardIterator j1, ForwardIterator j2); #endif /** Replace a part of the string. Replaces the characters in the range `{i1, i2)` with those of contained in the initializer list `il`. @par Precondition `{i1, i2)` is a valid range. @par Exception Safety Strong guarantee. @note All references, pointers, or iterators referring to contained elements are invalidated. Any past-the-end iterators are also invalidated. @return `*this` @param i1 An iterator referring to the first character to replace. @param i2 An iterator past the end of the last character to replace. @param il The initializer list to replace with. @throw std::length_error `size() + (il.size() - std::distance(i1, i2)) > max_size()` */ BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace( const_iterator i1, const_iterator i2, std::initializer_list il) { return replace_unchecked(i1, i2, il.begin(), il.size()); } //-------------------------------------------------------------------------- // // Search // //-------------------------------------------------------------------------- /** Find the first occurrence of a string within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the first occurrence of `sv` within the string starting at the index `pos`. @par Complexity Linear. @note An empty string is always found. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The lowest index `idx` greater than or equal to `pos` where each element of `{sv.begin(), sv.end())` is equal to that of `{begin() + idx, begin() + idx + count)` if one exists, and @ref npos otherwise. @param t The string to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find( const T& t, size_type pos = 0) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return find(sv.data(), pos, sv.size()); } /** Find the first occurrence of a string within the string. Finds the first occurrence of `str` within the string starting at the index `pos`. @par Complexity Linear. @return The lowest index `idx` greater than or equal to `pos` where each element of `str` is equal to that of `{begin() + idx, begin() + idx + str.size())` if one exists, and @ref npos otherwise. @param str The string to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find( const basic_static_string& str, size_type pos = 0) const noexcept { return find(str.data(), pos, str.size()); } /** Find the first occurrence of a string within the string. Finds the first occurrence of the string pointed to by `s` within the string starting at the index `pos`. @par Complexity Linear. @note An empty string is always found. @return The lowest index `idx` greater than or equal to `pos` where each element of `{s, s + n)` is equal to that of `{begin() + idx, begin() + idx + n)` if one exists, and @ref npos otherwise. @param s The string to search for. @param pos The index to start searching at. @param n The length of the string to search for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the first occurrence of a string within the string. Finds the first occurrence of the string pointed to by `s` of length `count` within the string starting at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @note An empty string is always found. @return The lowest index `idx` greater than or equal to `pos` where each element of `{s, s + count)` is equal to that of `{begin() + idx, begin() + idx + count)` if one exists, and @ref npos otherwise. @param s The string to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find( const_pointer s, size_type pos = 0) const noexcept { return find(s, pos, traits_type::length(s)); } /** Find the first occurrence of a character within the string. Finds the first occurrence of `c` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first occurrence of `c` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param c The character to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find( value_type c, size_type pos = 0) const noexcept { return find(&c, pos, 1); } /** Find the last occurrence of a string within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the last occurrence of `sv` within the string starting before or at the index `pos`. @par Complexity Linear. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The highest index `idx` less than or equal to `pos` where each element of `{sv.begin(), sv.end())` is equal to that of `{begin() + idx, begin() + idx + count)` if one exists, and @ref npos otherwise. @param t The string to search for. @param pos The index to start searching at. The default argument for this parameter is @ref npos. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type rfind( const T& t, size_type pos = npos) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return rfind(sv.data(), pos, sv.size()); } /** Find the last occurrence of a string within the string. Finds the last occurrence of `str` within the string starting before or at the index `pos`. @par Complexity Linear. @return The highest index `idx` less than or equal to `pos` where each element of `str` is equal to that of `{begin() + idx, begin() + idx + str.size())` if one exists, and @ref npos otherwise. @param str The string to search for. @param pos The index to start searching at. The default argument for this parameter is @ref npos. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type rfind( const basic_static_string& str, size_type pos = npos) const noexcept { return rfind(str.data(), pos, str.size()); } /** Find the last occurrence of a string within the string. Finds the last occurrence of the string pointed to by `s` within the string starting before or at the index `pos`. @par Complexity Linear. @return The highest index `idx` less than or equal to `pos` where each element of `{s, s + n)` is equal to that of `{begin() + idx, begin() + idx + n)` if one exists, and @ref npos otherwise. @param s The string to search for. @param pos The index to start searching at. @param n The length of the string to search for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type rfind( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the last occurrence of a string within the string. Finds the last occurrence of the string pointed to by `s` of length `count` within the string starting before or at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @return The highest index `idx` less than or equal to `pos` where each element of `{s, s + count)` is equal to that of `{begin() + idx, begin() + idx + count)` if one exists, and @ref npos otherwise. @param s The string to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type rfind( const_pointer s, size_type pos = npos) const noexcept { return rfind(s, pos, traits_type::length(s)); } /** Find the last occurrence of a character within the string. Finds the last occurrence of `c` within the string starting before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last occurrence of `c` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param c The character to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type rfind( value_type c, size_type pos = npos) const noexcept { return rfind(&c, pos, 1); } /** Find the first occurrence of any of the characters within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the first occurrence of any of the characters in `sv` within the string starting at the index `pos`. @par Complexity Linear. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The index corrosponding to the first occurrence of any of the characters in `{sv.begin(), sv.end())` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param t The characters to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_of( const T& t, size_type pos = 0) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return find_first_of(sv.data(), pos, sv.size()); } /** Find the first occurrence of any of the characters within the string. Finds the first occurrence of any of the characters within `str` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first occurrence of any of the characters of `str` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param str The characters to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_of( const basic_static_string& str, size_type pos = 0) const noexcept { return find_first_of(str.data(), pos, str.size()); } /** Find the first occurrence of any of the characters within the string. Finds the first occurrence of any of the characters within the string pointed to by `s` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first occurrence of any of the characters in `{s, s + n)` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param s The characters to search for. @param pos The index to start searching at. @param n The length of the string to search for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_of( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the first occurrence of any of the characters within the string. Finds the first occurrence of the any of the characters within string pointed to by `s` of length `count` within the string starting at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @return The index corrosponding to the first occurrence of any of the characters in `{s, s + count)` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param s The characters to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_of( const_pointer s, size_type pos = 0) const noexcept { return find_first_of(s, pos, traits_type::length(s)); } /** Find the first occurrence of a character within the string. Finds the first occurrence of `c` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first occurrence of `c` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param c The character to search for. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_of( value_type c, size_type pos = 0) const noexcept { return find_first_of(&c, pos, 1); } /** Find the last occurrence of any of the characters within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the last occurrence of any of the characters in `sv` within the string before or at the index `pos`. @par Complexity Linear. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The index corrosponding to the last occurrence of any of the characters in `{sv.begin(), sv.end())` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param t The characters to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_of( const T& t, size_type pos = npos) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return find_last_of(sv.data(), pos, sv.size()); } /** Find the last occurrence of any of the characters within the string. Finds the last occurrence of any of the characters within `str` within the string starting before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last occurrence of any of the characters of `str` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param str The characters to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_of( const basic_static_string& str, size_type pos = npos) const noexcept { return find_last_of(str.data(), pos, str.size()); } /** Find the last occurrence of any of the characters within the string. Finds the last occurrence of any of the characters within the string pointed to by `s` within the string before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last occurrence of any of the characters in `{s, s + n)` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param s The characters to search for. @param pos The index to stop searching at. @param n The length of the string to search for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_of( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the last occurrence of any of the characters within the string. Finds the last occurrence of any of the characters within the string pointed to by `s` of length `count` within the string before or at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @return The index corrosponding to the last occurrence of any of the characters in `{s, s + count)` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param s The characters to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_of( const_pointer s, size_type pos = npos) const noexcept { return find_last_of(s, pos, traits_type::length(s)); } /** Find the last occurrence of a character within the string. Finds the last occurrence of `c` within the string before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last occurrence of `c` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param c The character to search for. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_of( value_type c, size_type pos = npos) const noexcept { return find_last_of(&c, pos, 1); } /** Find the first occurrence of a character not within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the first character that is not within `sv`, starting at the index `pos`. @par Complexity Linear. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The index corrosponding to the first occurrence of a character that is not in `{sv.begin(), sv.end())` within `{begin() + pos, end())` if it exists, and @ref npos otherwise. @param t The characters to ignore. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_not_of( const T& t, size_type pos = 0) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return find_first_not_of(sv.data(), pos, sv.size()); } /** Find the first occurrence of any of the characters not within the string. Finds the first occurrence of a character that is not within `str` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first character of `{begin() + pos, end())` that is not within `str` if it exists, and @ref npos otherwise. @param str The characters to ignore. @param pos The index to start searching at. The default argument for this parameter is `0`. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_not_of( const basic_static_string& str, size_type pos = 0) const noexcept { return find_first_not_of(str.data(), pos, str.size()); } /** Find the first occurrence of any of the characters not within the string. Finds the first occurrence of a character that is not within the string pointed to by `s` within the string starting at the index `pos`. @par Complexity Linear. @return The index corrosponding to the first character of `{begin() + pos, end())` that is not within `{s, s + n)` if it exists, and @ref npos otherwise. @param s The characters to ignore. @param pos The index to start searching at. The default argument for this parameter is `0`. @param n The length of the characters to ignore. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_not_of( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the first occurrence of any of the characters not within the string. Finds the first occurrence of a character that is not within the string pointed to by `s` of length `count` within the string starting at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @return The index corrosponding to the first character of `{begin() + pos, end())` that is not within `{s, s + count)` if it exists, and @ref npos otherwise. @param s The characters to ignore. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_not_of( const_pointer s, size_type pos = 0) const noexcept { return find_first_not_of(s, pos, traits_type::length(s)); } /** Find the first occurrence of a character not equal to `c`. Finds the first occurrence of a character that is not equal to `c`. @par Complexity Linear. @return The index corrosponding to the first character of `{begin() + pos, end())` that is not equal to `c` if it exists, and @ref npos otherwise. @param c The character to ignore. @param pos The index to start searching at. The default argument for this parameter is `0`. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_first_not_of( value_type c, size_type pos = 0) const noexcept { return find_first_not_of(&c, pos, 1); } /** Find the last occurrence of a character not within the string. Constructs a temporary `string_view_type` object `sv` from `t`, and finds the last character that is not within `sv`, starting at the index `pos`. @par Complexity Linear. @tparam T The type of the object to convert. @par Constraints `std::is_convertible::value && !std::is_convertible::value && !std::is_convertible::value`. @return The index corrosponding to the last occurrence of a character that is not in `{sv.begin(), sv.end())` within `{begin(), begin() + pos}` if it exists, and @ref npos otherwise. @param t The characters to ignore. @param pos The index to start searching at. The default argument for this parameter is @ref npos. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_not_of( const T& t, size_type pos = npos) const #ifdef BOOST_STATIC_STRING_DOCS noexcept(detail::is_nothrow_convertible::value) #else noexcept(detail::is_nothrow_convertible>::value) #endif { detail::common_string_view_type sv = t; return find_last_not_of(sv.data(), pos, sv.size()); } /** Find the last occurrence of a character not within the string. Finds the last occurrence of a character that is not within `str` within the string before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last character of `{begin(), begin() + pos}` that is not within `str` if it exists, and @ref npos otherwise. @param str The characters to ignore. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_not_of( const basic_static_string& str, size_type pos = npos) const noexcept { return find_last_not_of(str.data(), pos, str.size()); } /** Find the last occurrence of a character not within the string. Finds the last occurrence of a character that is not within the string pointed to by `s` within the string before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last character of `{begin(), begin() + pos}` that is not within `{s, s + n)` if it exists, and @ref npos otherwise. @param s The characters to ignore. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. @param n The length of the characters to ignore. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_not_of( const_pointer s, size_type pos, size_type n) const noexcept; /** Find the last occurrence of a character not within the string. Finds the last occurrence of a character that is not within the string pointed to by `s` of length `count` within the string before or at the index `pos`, where `count` is `traits_type::length(s)`. @par Complexity Linear. @return The index corrosponding to the last character of `{begin(), begin() + pos}` that is not within `{s, s + count)` if it exists, and @ref npos otherwise. @param s The characters to ignore. @param pos The index to stop searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_not_of( const_pointer s, size_type pos = npos) const noexcept { return find_last_not_of(s, pos, traits_type::length(s)); } /** Find the last occurrence of a character not equal to `c`. Finds the last occurrence of a character that is not equal to `c` before or at the index `pos`. @par Complexity Linear. @return The index corrosponding to the last character of `{begin(), begin() + pos}` that is not equal to `c` if it exists, and @ref npos otherwise. @param c The character to ignore. @param pos The index to start searching at. The default argument for this parameter is @ref npos. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type find_last_not_of( value_type c, size_type pos = npos) const noexcept { return find_last_not_of(&c, pos, 1); } /** Return whether the string begins with a string. Returns `true` if the string begins with `s`, and `false` otherwise. @par Complexity Linear. @param t The string view to check for. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR bool starts_with( T const& t) const noexcept { detail::common_string_view_type sv = t; const size_type len = sv.size(); return size() >= len && !traits_type::compare(data(), sv.data(), len); } /** Return whether the string begins with a character. Returns `true` if the string begins with `c`, and `false` otherwise. @par Complexity Constant. @param c The character to check for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR bool starts_with( value_type c) const noexcept { return !empty() && traits_type::eq(front(), c); } /** Return whether the string begins with a string. Returns `true` if the string begins with the string pointed to be `s` of length `traits_type::length(s)`, and `false` otherwise. @par Complexity Linear. @param s The string to check for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR bool starts_with( const_pointer s) const noexcept { const size_type len = traits_type::length(s); return size() >= len && !traits_type::compare(data(), s, len); } /** Return whether the string ends with a string. Returns `true` if the string ends with `s`, and `false` otherwise. @par Complexity Linear. @param t The string view to check for. */ template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR bool ends_with( T const& t) const noexcept { detail::common_string_view_type sv = t; const size_type len = sv.size(); return size() >= len && !traits_type::compare(data() + (size() - len), sv.data(), len); } /** Return whether the string ends with a character. Returns `true` if the string ends with `c`, and `false` otherwise. @par Complexity Constant. @param c The character to check for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR bool ends_with( value_type c) const noexcept { return !empty() && traits_type::eq(back(), c); } /** Return whether the string ends with a string. Returns `true` if the string ends with the string pointed to be `s` of length `traits_type::length(s)`, and `false` otherwise. @par Complexity Linear. @param s The string to check for. */ BOOST_STATIC_STRING_CPP14_CONSTEXPR bool ends_with( const_pointer s) const noexcept { const size_type len = traits_type::length(s); return size() >= len && !traits_type::compare(data() + (size() - len), s, len); } private: BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& term() noexcept { this->term_impl(); return *this; } BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign_char(value_type ch, std::true_type) noexcept { this->set_size(1); traits_type::assign(data()[0], ch); return term(); } BOOST_STATIC_STRING_NORETURN basic_static_string& assign_char(value_type, std::false_type) { detail::throw_exception("max_size() == 0"); // This eliminates any potential warnings #ifdef BOOST_STATIC_STRING_NO_NORETURN return *this; #endif } // Returns the size of data read from input iterator. Read data begins at data() + size() + 1. template BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type read_back( bool overwrite_null, InputIterator first, InputIterator last); BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace_unchecked( size_type pos, size_type n1, const_pointer s, size_type n2) { if (pos > size()) detail::throw_exception( "pos > size()"); return replace_unchecked(data() + pos, data() + pos + capped_length(pos, n1), s, n2); } BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& replace_unchecked( const_iterator i1, const_iterator i2, const_pointer s, size_type n2); BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& insert_unchecked( size_type index, const_pointer s, size_type count) { if (index > size()) detail::throw_exception( "index > size()"); insert_unchecked(data() + index, s, count); return *this; } BOOST_STATIC_STRING_CPP14_CONSTEXPR iterator insert_unchecked( const_iterator pos, const_pointer s, size_type count); BOOST_STATIC_STRING_CPP14_CONSTEXPR basic_static_string& assign_unchecked( const_pointer s, size_type count) noexcept { this->set_size(count); traits_type::copy(data(), s, size() + 1); return *this; } BOOST_STATIC_STRING_CPP14_CONSTEXPR size_type capped_length( size_type index, size_type length) const { if (index > size()) detail::throw_exception( "index > size()"); return (std::min)(size() - index, length); } }; //------------------------------------------------------------------------------ // // Non-member functions // //------------------------------------------------------------------------------ template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator==( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) == 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator!=( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) != 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) < 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<=( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) <= 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) > 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>=( const basic_static_string& lhs, const basic_static_string& rhs) { return lhs.compare(rhs) >= 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator==( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) == 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator==( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) == 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator==( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) == 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator==( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) == 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator!=( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) != 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator!=( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) != 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator!=( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) != 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator!=( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) != 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) < 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) < 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) < 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) < 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<=( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) <= 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<=( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) <= 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<=( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) <= 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator<=( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) <= 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) > 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) > 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) > 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) > 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>=( const CharT* lhs, const basic_static_string& rhs) { return detail::lexicographical_compare( lhs, Traits::length(lhs), rhs.data(), rhs.size()) >= 0; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>=( const basic_static_string& lhs, const CharT* rhs) { return detail::lexicographical_compare( lhs.data(), lhs.size(), rhs, Traits::length(rhs)) >= 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>=( const T& lhs, const basic_static_string& rhs) { detail::common_string_view_type lhsv = lhs; return detail::lexicographical_compare( lhsv.data(), lhsv.size(), rhs.data(), rhs.size()) >= 0; } template #endif > BOOST_STATIC_STRING_CPP14_CONSTEXPR inline bool operator>=( const basic_static_string& lhs, const T& rhs) { detail::common_string_view_type rhsv = rhs; return detail::lexicographical_compare( lhs.data(), lhs.size(), rhsv.data(), rhsv.size()) >= 0; } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline basic_static_string operator+( const basic_static_string& lhs, const basic_static_string& rhs) { return basic_static_string(lhs) += rhs; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline basic_static_string operator+( const basic_static_string& lhs, CharT rhs) { return basic_static_string(lhs) += rhs; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline basic_static_string operator+( CharT lhs, const basic_static_string& rhs) { // The cast to std::size_t is needed here since 0 is a null pointer constant return basic_static_string(rhs).insert( std::size_t(0), 1, lhs); } // Add a null terminated character array to a string. template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline basic_static_string operator+( const basic_static_string& lhs, const CharT(&rhs)[M]) { return basic_static_string(lhs).append(+rhs); } // Add a string to a null terminated character array. template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline basic_static_string operator+( const CharT(&lhs)[N], const basic_static_string& rhs) { // The cast to std::size_t is needed here since 0 is a null pointer constant return basic_static_string(rhs).insert( std::size_t(0), +lhs); } //------------------------------------------------------------------------------ // // erase_if // //------------------------------------------------------------------------------ template< std::size_t N, typename CharT, typename Traits, typename UnaryPredicate> BOOST_STATIC_STRING_CPP14_CONSTEXPR typename basic_static_string::size_type erase_if( basic_static_string& str, UnaryPredicate pred) { auto first = str.begin(); for (auto it = first; it != str.end(); ++it) if (!pred(*it)) *first++ = std::move(*it); const auto count = str.end() - first; str.erase(first, str.end()); return count; } //------------------------------------------------------------------------------ // // swap // //------------------------------------------------------------------------------ template BOOST_STATIC_STRING_CPP14_CONSTEXPR inline void swap( basic_static_string& lhs, basic_static_string& rhs) { lhs.swap(rhs); } template< std::size_t N, std::size_t M, typename CharT, typename Traits> BOOST_STATIC_STRING_CPP14_CONSTEXPR inline void swap( basic_static_string& lhs, basic_static_string& rhs) { lhs.swap(rhs); } //------------------------------------------------------------------------------ // // Input/Output // //------------------------------------------------------------------------------ template inline std::basic_ostream& operator<<( std::basic_ostream& os, const basic_static_string& s) { #ifdef BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW return os << basic_string_view(s.data(), s.size()); #else for (auto c: s) os << c; return os; #endif } //------------------------------------------------------------------------------ // // Numeric conversions // //------------------------------------------------------------------------------ // Signed overloads have a + 2, one for the missing digit, // and one for the sign. // Unsigned overloads have a + 1, for the missing digit. // Floating point overloads have a +8 (for float), + 8 // (for double), and +10 for long double (that accounts // for the sign of the integral part, the missing digit, // the decimal point, the sign of the exponent, the 'e' // and up to two, three or five digits of exponent---float // uses the same value as double, because we sometimes // reuse the conversion from double for floats). /// Converts `value` to a `static_string` static_string::digits10 + 2> inline to_static_string(int value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_string` static_string::digits10 + 2> inline to_static_string(long value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_string` static_string::digits10 + 2> inline to_static_string(long long value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_string` static_string::digits10 + 1> inline to_static_string(unsigned int value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_string` static_string::digits10 + 1> inline to_static_string(unsigned long value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_string` static_string::digits10 + 1> inline to_static_string(unsigned long long value) noexcept { return detail::to_static_string_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_string` static_string::max_digits10 + 8> inline to_static_string(float value) noexcept { return detail::to_static_string_float_impl< std::numeric_limits::max_digits10 + 8>(value); } /// Converts `value` to a `static_string` static_string::max_digits10 + 8> inline to_static_string(double value) noexcept { return detail::to_static_string_float_impl< std::numeric_limits::max_digits10 + 8>(value); } /// Converts `value` to a `static_string` static_string::max_digits10 + 10> inline to_static_string(long double value) noexcept { return detail::to_static_string_float_impl< std::numeric_limits::max_digits10 + 10>(value); } #ifdef BOOST_STATIC_STRING_HAS_WCHAR /// Converts `value` to a `static_wstring` static_wstring::digits10 + 2> inline to_static_wstring(int value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_wstring` static_wstring::digits10 + 2> inline to_static_wstring(long value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_wstring` static_wstring::digits10 + 2> inline to_static_wstring(long long value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 2>(value); } /// Converts `value` to a `static_wstring` static_wstring::digits10 + 1> inline to_static_wstring(unsigned int value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_wstring` static_wstring::digits10 + 1> inline to_static_wstring(unsigned long value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_wstring` static_wstring::digits10 + 1> inline to_static_wstring(unsigned long long value) noexcept { return detail::to_static_wstring_int_impl< std::numeric_limits::digits10 + 1>(value); } /// Converts `value` to a `static_wstring` static_wstring::max_digits10 + 8> inline to_static_wstring(float value) noexcept { return detail::to_static_wstring_float_impl< std::numeric_limits::max_digits10 + 8>(value); } /// Converts `value` to a `static_wstring` static_wstring::max_digits10 + 8> inline to_static_wstring(double value) noexcept { return detail::to_static_wstring_float_impl< std::numeric_limits::max_digits10 + 8>(value); } /// Converts `value` to a `static_wstring` static_wstring::max_digits10 + 10> inline to_static_wstring(long double value) noexcept { return detail::to_static_wstring_float_impl< std::numeric_limits::max_digits10 + 10>(value); } #endif //------------------------------------------------------------------------------ // // Deduction Guides // //------------------------------------------------------------------------------ #ifdef BOOST_STATIC_STRING_USE_DEDUCT template basic_static_string(const CharT(&)[N]) -> basic_static_string>; #endif //------------------------------------------------------------------------------ // // Hashing // //------------------------------------------------------------------------------ #ifndef BOOST_STATIC_STRING_STANDALONE /// hash_value overload for Boost.Container_Hash template std::size_t hash_value( const basic_static_string& str) { return boost::hash_range(str.begin(), str.end()); } #endif } // static_strings //------------------------------------------------------------------------------ // // using Declarations // //------------------------------------------------------------------------------ using static_strings::static_string; #ifdef BOOST_STATIC_STRING_HAS_WCHAR using static_strings::static_wstring; #endif using static_strings::static_u16string; using static_strings::static_u32string; } // boost /// std::hash partial specialization for basic_static_string namespace std { template struct hash< #ifdef BOOST_STATIC_STRING_DOCS basic_static_string #else boost::static_strings::basic_static_string #endif > { std::size_t operator()( const boost::static_strings::basic_static_string& str) const noexcept { #if !defined(BOOST_STATIC_STRING_STANDALONE) return boost::hash_range(str.begin(), str.end()); #elif defined(BOOST_STATIC_STRING_HAS_ANY_STRING_VIEW) using view_type = typename boost::static_strings::basic_string_view; return std::hash()(view_type(str.data(), str.size())); #else std::size_t seed = 0; for (CharT const& c : str) { #if BOOST_STATIC_STRING_ARCH == 64 seed += 0x9e3779b9 + std::hash()( c ); std::size_t const m = (std::size_t(0xe9846af) << 32) + 0x9b1a615d; seed ^= seed >> 32; seed *= m; seed ^= seed >> 32; seed *= m; seed ^= seed >> 28; #elif BOOST_STATIC_STRING_ARCH == 32 seed += 0x9e3779b9 + std::hash()( c ); std::size_t const m1 = 0x21f0aaad; std::size_t const m2 = 0x735a2d97; seed ^= seed >> 16; seed *= m1; seed ^= seed >> 15; seed *= m2; seed ^= seed >> 15; #endif } return seed; #endif } }; } // std //-------------------------------------------------------------------------- // // Implementation // //-------------------------------------------------------------------------- #ifndef BOOST_STATIC_STRING_DOCS namespace boost { namespace static_strings { template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: assign( size_type count, value_type ch) -> basic_static_string& { if (count > max_size()) detail::throw_exception( "count > max_size()"); this->set_size(count); traits_type::assign(data(), size(), ch); return term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: assign( const_pointer s, size_type count) -> basic_static_string& { if (count > max_size()) detail::throw_exception( "count > max_size()"); this->set_size(count); traits_type::move(data(), s, size()); return term(); } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: assign( InputIterator first, InputIterator last) -> typename std::enable_if< detail::is_input_iterator::value, basic_static_string&>::type { auto ptr = data(); for (std::size_t i = 0; first != last; ++first, ++ptr, ++i) { if (i >= max_size()) { this->set_size(i); term(); detail::throw_exception("n > max_size()"); } traits_type::assign(*ptr, *first); } this->set_size(ptr - data()); return term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: insert( const_iterator pos, size_type count, value_type ch) -> iterator { const auto curr_size = size(); const auto curr_data = data(); if (count > max_size() - curr_size) detail::throw_exception( "count > max_size() - curr_size"); const auto index = pos - curr_data; traits_type::move(&curr_data[index + count], &curr_data[index], curr_size - index + 1); traits_type::assign(&curr_data[index], count, ch); this->set_size(curr_size + count); return &curr_data[index]; } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: insert( const_iterator pos, ForwardIterator first, ForwardIterator last) -> typename std::enable_if< detail::is_forward_iterator< ForwardIterator>::value, iterator>::type { // input const std::size_t count = detail::distance(first, last); const auto first_addr = &*first; const auto last_addr = first_addr + count; // output const auto curr_size = size(); const auto curr_data = data(); const std::size_t index = pos - curr_data; auto dest = &curr_data[index]; if (count > max_size() - curr_size) detail::throw_exception( "count > max_size() - curr_size"); traits_type::move(dest + count, dest, curr_size - index + 1); const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr); if (!inside || last_addr <= pos) { detail::copy_with_traits(first, last, dest); } else /* if (inside) */ { const size_type offset = first_addr - curr_data; if (offset < index) { const size_type diff = index - offset; traits_type::copy(dest, &curr_data[offset], diff); traits_type::copy(&curr_data[index + diff], dest + count, count - diff); } else { auto src = &curr_data[offset + count]; traits_type::copy(dest, src, count); } } this->set_size(curr_size + count); return curr_data + index; } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: insert( const_iterator pos, InputIterator first, InputIterator last) -> typename std::enable_if< detail::is_input_iterator< InputIterator>::value && !detail::is_forward_iterator< InputIterator>::value, iterator>::type { const auto curr_size = size(); const auto curr_data = data(); const auto count = read_back(false, first, last); const std::size_t index = pos - curr_data; std::rotate(&curr_data[index], &curr_data[curr_size + 1], &curr_data[curr_size + count + 1]); this->set_size(curr_size + count); return curr_data + index; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: erase( const_iterator first, const_iterator last) -> iterator { const auto curr_data = data(); const std::size_t index = first - curr_data; traits_type::move(&curr_data[index], last, (end() - last) + 1); this->set_size(size() - std::size_t(last - first)); return curr_data + index; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR void basic_static_string:: push_back( value_type ch) { const auto curr_size = size(); if (curr_size >= max_size()) detail::throw_exception( "curr_size >= max_size()"); traits_type::assign(data()[curr_size], ch); this->set_size(curr_size + 1); term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: append( size_type count, value_type ch) -> basic_static_string& { const auto curr_size = size(); if (count > max_size() - curr_size) detail::throw_exception( "count > max_size() - size()"); traits_type::assign(end(), count, ch); this->set_size(curr_size + count); return term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: append( const_pointer s, size_type count) -> basic_static_string& { const auto curr_size = size(); if (count > max_size() - curr_size) detail::throw_exception( "count > max_size() - size()"); traits_type::copy(end(), s, count); this->set_size(curr_size + count); return term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR void basic_static_string:: resize(size_type n, value_type c) { if (n > max_size()) detail::throw_exception( "n > max_size()"); const auto curr_size = size(); if(n > curr_size) traits_type::assign(data() + curr_size, n - curr_size, c); this->set_size(n); term(); } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR void basic_static_string:: resize_and_overwrite( size_type n, Operation op) { if (n > max_size()) { detail::throw_exception("n > max_size() in resize_and_overwrite()"); } CharT* p = data(); const auto new_size = std::move(op)(p, n); BOOST_STATIC_STRING_ASSERT(new_size >= 0 && size_type(new_size) <= n); this->set_size(size_type(new_size)); term(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR void basic_static_string:: swap(basic_static_string& s) noexcept { const auto curr_size = size(); basic_static_string tmp(s); s.set_size(curr_size); traits_type::copy(&s.data()[0], data(), curr_size + 1); this->set_size(tmp.size()); traits_type::copy(data(), tmp.data(), size() + 1); } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR void basic_static_string:: swap(basic_static_string& s) { const auto curr_size = size(); if (curr_size > s.max_size()) detail::throw_exception( "curr_size > s.max_size()"); if (s.size() > max_size()) detail::throw_exception( "s.size() > max_size()"); basic_static_string tmp(s); s.set_size(curr_size); traits_type::copy(&s.data()[0], data(), curr_size + 1); this->set_size(tmp.size()); traits_type::copy(data(), &tmp.data()[0], size() + 1); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: replace( const_iterator i1, const_iterator i2, size_type n, value_type c) -> basic_static_string& { const auto curr_size = size(); const auto curr_data = data(); const std::size_t n1 = i2 - i1; if (n > max_size() || curr_size - n1 >= max_size() - n) detail::throw_exception( "replaced string exceeds max_size()"); const auto pos = i1 - curr_data; traits_type::move(&curr_data[pos + n], i2, (end() - i2) + 1); traits_type::assign(&curr_data[pos], n, c); this->set_size((curr_size - n1) + n); return *this; } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: replace( const_iterator i1, const_iterator i2, ForwardIterator j1, ForwardIterator j2) -> typename std::enable_if< detail::is_forward_iterator::value, basic_static_string&>::type { const auto curr_size = size(); const auto curr_data = data(); const auto first_addr = &*j1; const std::size_t n1 = i2 - i1; const std::size_t n2 = detail::distance(j1, j2); const std::size_t pos = i1 - curr_data; if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2) detail::throw_exception( "replaced string exceeds max_size()"); const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, first_addr); if (inside && first_addr == i1 && n1 == n2) return *this; // Short circuit evaluation ensures that the pointer arithmetic is valid if (!inside || (inside && (first_addr + n2 <= i1))) { // source outside traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); detail::copy_with_traits(j1, j2, &curr_data[pos]); } else { // source inside const size_type offset = first_addr - curr_data; if (n2 >= n1) { // grow/unchanged const size_type diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0; // shift all right of splice point by n2 - n1 to the right traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); // copy all before splice point traits_type::move(&curr_data[pos], &curr_data[offset], diff); // copy all after splice point traits_type::move(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff); } else { // shrink // copy all elements into place traits_type::move(&curr_data[pos], &curr_data[offset], n2); // shift all elements after splice point left traits_type::move(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1); } } this->set_size((curr_size - n1) + n2); return *this; } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: replace( const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2) -> typename std::enable_if< detail::is_input_iterator< InputIterator>::value && !detail::is_forward_iterator< InputIterator>::value, basic_static_string&>::type { const auto curr_size = size(); const auto curr_data = data(); const std::size_t n1 = detail::distance(i1, i2); const std::size_t n2 = read_back(false, j1, j2); const std::size_t pos = i1 - curr_data; // Rotate to the correct order. [i2, end] will now start with the replaced string, // continue to the existing string not being replaced, and end with a null terminator std::rotate(&curr_data[pos], &curr_data[curr_size + 1], &curr_data[curr_size + n2 + 1]); // Move everything from the end of the splice point to the end of the rotated string to // the begining of the splice point traits_type::move(&curr_data[pos + n2], &curr_data[pos + n2 + n1], ((curr_size - n1) + n2) - pos); this->set_size((curr_size - n1) + n2); return *this; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: find( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { const auto curr_size = size(); if (pos > curr_size || n > curr_size - pos) return npos; if (!n) return pos; const auto res = detail::search(data() + pos, data() + curr_size, s, s + n, traits_type::eq); return res == end() ? npos : detail::distance(data(), res); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: rfind( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { 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_type::compare(sub, s, n)) return detail::distance(curr_data, sub); return npos; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: find_first_of( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { const auto curr_data = data(); if (pos >= size() || !n) return npos; const auto res = detail::find_first_of(&curr_data[pos], &curr_data[size()], s, &s[n], traits_type::eq); return res == end() ? npos : detail::distance(curr_data, res); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: find_last_of( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { const auto curr_size = size(); if (!n) return npos; if (pos >= curr_size) pos = 0; else pos = curr_size - (pos + 1); const auto res = detail::find_first_of(rbegin() + pos, rend(), s, &s[n], traits_type::eq); return res == rend() ? npos : curr_size - 1 - detail::distance(rbegin(), res); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: find_first_not_of( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { 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 : detail::distance(data(), res); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: find_last_not_of( const_pointer s, size_type pos, size_type n) const noexcept -> size_type { 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 - detail::distance(rbegin(), res); } template template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: read_back( bool overwrite_null, InputIterator first, InputIterator last) -> size_type { const auto curr_data = data(); auto new_size = size(); for (; first != last; ++first) { if (new_size >= max_size()) { // if we overwrote the null terminator, // put it back if (overwrite_null) term(); detail::throw_exception( "count > max_size() - size()"); } traits_type::assign(curr_data[new_size++ + (!overwrite_null)], *first); } return new_size - size(); } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: replace_unchecked( const_iterator i1, const_iterator i2, const_pointer s, size_type n2) -> basic_static_string& { const auto curr_data = data(); const auto curr_size = size(); const std::size_t pos = i1 - curr_data; const std::size_t n1 = i2 - i1; if (n2 > max_size() || curr_size - (std::min)(n1, curr_size - pos) >= max_size() - n2) detail::throw_exception( "replaced string exceeds max_size()"); traits_type::move(&curr_data[pos + n2], i2, (end() - i2) + 1); traits_type::copy(&curr_data[pos], s, n2); this->set_size((curr_size - n1) + n2); return *this; } template BOOST_STATIC_STRING_CPP14_CONSTEXPR auto basic_static_string:: insert_unchecked( const_iterator pos, const_pointer s, size_type count) -> iterator { const auto curr_data = data(); const auto curr_size = size(); if (count > max_size() - curr_size) detail::throw_exception( "count > max_size() - curr_size"); const std::size_t index = pos - curr_data; traits_type::move(&curr_data[index + count], pos, (end() - pos) + 1); traits_type::copy(&curr_data[index], s, count); this->set_size(curr_size + count); return curr_data + index; } } // static_strings } // boost #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic pop #endif #if defined(__GNUC__) && __GNUC__ >= 8 #pragma GCC diagnostic pop #endif #endif #endif