diff --git a/include/boost/charconv/detail/dragonbox.hpp b/include/boost/charconv/detail/dragonbox.hpp index d15c24e..f2f9089 100644 --- a/include/boost/charconv/detail/dragonbox.hpp +++ b/include/boost/charconv/detail/dragonbox.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -2559,11 +2560,11 @@ BOOST_FORCEINLINE BOOST_CHARCONV_SAFEBUFFERS auto to_decimal(Float x, Policies.. namespace to_chars_detail { template - extern char* to_chars(typename FloatTraits::carrier_uint significand, int exponent, char* buffer) noexcept; + extern char* to_chars(typename FloatTraits::carrier_uint significand, int exponent, char* buffer, chars_format fmt) noexcept; // Avoid needless ABI overhead incurred by tag dispatch. template - char* to_chars_n_impl(dragonbox_float_bits br, char* buffer) noexcept + char* to_chars_n_impl(dragonbox_float_bits br, char* buffer, chars_format fmt) noexcept { const auto exponent_bits = br.extract_exponent_bits(); const auto s = br.remove_exponent_bits(exponent_bits); @@ -2583,7 +2584,7 @@ namespace to_chars_detail { typename PolicyHolder::binary_to_decimal_rounding_policy{}, typename PolicyHolder::cache_policy{}); return to_chars_detail::to_chars(result.significand, - result.exponent, buffer); + result.exponent, buffer, fmt); } else { @@ -2664,7 +2665,7 @@ namespace to_chars_detail { // Returns the next-to-end position template , typename... Policies> -char* to_chars_n(Float x, char* buffer, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept +char* to_chars_n(Float x, char* buffer, chars_format fmt, BOOST_ATTRIBUTE_UNUSED Policies... policies) noexcept { using namespace policy_impl; @@ -2686,14 +2687,14 @@ char* to_chars_n(Float x, char* buffer, BOOST_ATTRIBUTE_UNUSED Policies... polic #endif - return to_chars_detail::to_chars_n_impl(dragonbox_float_bits(x), buffer); + return to_chars_detail::to_chars_n_impl(dragonbox_float_bits(x), buffer, fmt); } // Null-terminate and bypass the return value of fp_to_chars_n template , typename... Policies> -char* to_chars(Float x, char* buffer, Policies... policies) noexcept +char* to_chars(Float x, char* buffer, chars_format fmt, Policies... policies) noexcept { - auto ptr = to_chars_n(x, buffer, policies...); + auto ptr = to_chars_n(x, buffer, fmt, policies...); *ptr = '\0'; return ptr; } diff --git a/include/boost/charconv/to_chars.hpp b/include/boost/charconv/to_chars.hpp index 57afe85..bf77443 100644 --- a/include/boost/charconv/to_chars.hpp +++ b/include/boost/charconv/to_chars.hpp @@ -481,7 +481,7 @@ to_chars_result to_chars_hex(char* first, char* last, Real value, int precision) BOOST_FALLTHROUGH; case FP_NAN: // The dragonbox impl will return the correct type of NaN - ptr = boost::charconv::detail::to_chars(value, first); + ptr = boost::charconv::detail::to_chars(value, first, chars_format::general); return { ptr, 0 }; case FP_ZERO: if (std::signbit(value)) @@ -692,13 +692,13 @@ to_chars_result to_chars_float_impl(char* first, char* last, Real value, chars_f } else { - auto* ptr = boost::charconv::detail::to_chars(value, first); + auto* ptr = boost::charconv::detail::to_chars(value, first, fmt); return { ptr, 0 }; } } else if (fmt == boost::charconv::chars_format::scientific) { - auto* ptr = boost::charconv::detail::to_chars(value, first); + auto* ptr = boost::charconv::detail::to_chars(value, first, fmt); return { ptr, 0 }; } } diff --git a/src/to_chars.cpp b/src/to_chars.cpp index 8f84ca2..122389b 100644 --- a/src/to_chars.cpp +++ b/src/to_chars.cpp @@ -299,7 +299,7 @@ namespace boost { namespace charconv { namespace detail { namespace to_chars_det } template <> - char* to_chars>(std::uint32_t s32, int exponent, char* buffer) noexcept + char* to_chars>(std::uint32_t s32, int exponent, char* buffer, chars_format fmt) noexcept { // Print significand. print_9_digits(s32, exponent, buffer); @@ -311,28 +311,30 @@ namespace boost { namespace charconv { namespace detail { namespace to_chars_det buffer += 2; exponent = -exponent; } + else if (exponent == 0) + { + if (fmt == chars_format::scientific) + { + std::memcpy(buffer, "e+00", 4); + buffer += 4; + } + + return buffer; + } else { std::memcpy(buffer, "e+", 2); buffer += 2; } - if (exponent >= 10) - { - print_2_digits(std::uint32_t(exponent), buffer); - buffer += 2; - } - else - { - print_1_digit(std::uint32_t(exponent), buffer); - buffer += 1; - } + print_2_digits(std::uint32_t(exponent), buffer); + buffer += 2; return buffer; } template <> - char* to_chars>(const std::uint64_t significand, int exponent, char* buffer) noexcept { + char* to_chars>(const std::uint64_t significand, int exponent, char* buffer, chars_format fmt) noexcept { // Print significand by decomposing it into a 9-digit block and a 8-digit block. std::uint32_t first_block; std::uint32_t second_block {}; @@ -522,6 +524,12 @@ namespace boost { namespace charconv { namespace detail { namespace to_chars_det } else if (exponent == 0) { + if (fmt == chars_format::scientific) + { + std::memcpy(buffer, "e+00", 4); + buffer += 4; + } + return buffer; } else