diff --git a/include/boost/static_string/static_string.hpp b/include/boost/static_string/static_string.hpp index d2cfa52..6bbc26c 100644 --- a/include/boost/static_string/static_string.hpp +++ b/include/boost/static_string/static_string.hpp @@ -550,13 +550,21 @@ inline static_string to_static_string_int_impl(Integer value) noexcept { + using size_type = typename static_string::size_type; static_string result; - char * const digits_end = result.data() + N; - char * const digits_begin = integer_to_string, Integer>( - digits_end, value, std::is_signed{}); - result.set_size(digits_end - digits_begin); - std::char_traits::move(result.data(), digits_begin, result.size()); - result.term(); + 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; } @@ -566,13 +574,20 @@ inline static_wstring to_static_wstring_int_impl(Integer value) noexcept { + using size_type = typename static_wstring::size_type; static_wstring result; - wchar_t * const digits_end = result.data() + N; - wchar_t * const digits_begin = integer_to_wstring, Integer>( - digits_end, value, std::is_signed{}); - result.set_size(digits_end - digits_begin); - std::char_traits::move(result.data(), digits_begin, result.size()); - result.term(); + 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 @@ -598,27 +613,34 @@ inline static_string to_static_string_float_impl(double value) noexcept { + using size_type = typename static_string::size_type; // 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); static_string result; - // we know that a formatting error will not occur, so - // we assume that the result is always positive - std::size_t length = std::snprintf(result.data(), 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(result.data(), N + 1, "%.*e", precision, value); - } - result.set_size(length); + 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; } @@ -627,29 +649,36 @@ inline static_string to_static_string_float_impl(long double value) noexcept { + using size_type = typename static_string::size_type; // 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); static_string result; - // 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(result.data(), 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(result.data(), N + 1, "%.*Le", precision, value); - } - result.set_size(length); + 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; } @@ -659,34 +688,41 @@ inline static_wstring to_static_wstring_float_impl(double value) noexcept { + using size_type = typename static_wstring::size_type; // 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); static_wstring result; - // 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. - long long num_written = - std::swprintf(result.data(), 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(result.data(), N + 1, L"%.*e", precision, value); - } - result.set_size(static_cast(num_written)); + 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. + long long 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; } @@ -695,34 +731,41 @@ inline static_wstring to_static_wstring_float_impl(long double value) noexcept { + using size_type = typename static_wstring::size_type; // 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); static_wstring result; - // 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. - long long num_written = - std::swprintf(result.data(), 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(result.data(), N + 1, L"%.*Le", precision, value); - } - result.set_size(static_cast(num_written)); + 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. + long long 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 @@ -931,36 +974,6 @@ private: template friend class basic_static_string; - template - friend - static_string

- detail::to_static_string_int_impl(Integer value) noexcept; - - template - friend - static_string

- detail::to_static_string_float_impl(double value) noexcept; - - template - friend - static_string

- detail::to_static_string_float_impl(long double value) noexcept; - -#ifdef BOOST_STATIC_STRING_HAS_WCHAR - template - friend static_wstring

- detail::to_static_wstring_int_impl(Integer value) noexcept; - - template - friend - static_wstring

- detail::to_static_wstring_float_impl(double value) noexcept; - - template - friend - static_wstring

- detail::to_static_wstring_float_impl(long double value) noexcept; -#endif public: //-------------------------------------------------------------------------- //