From adea138d232b371d4e7940dbb20dfbfceb079200 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 4 May 2023 08:45:42 +0200 Subject: [PATCH] Add strtod fallback routine --- include/boost/charconv/from_chars.hpp | 43 +++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/include/boost/charconv/from_chars.hpp b/include/boost/charconv/from_chars.hpp index 1031d01..1a1055f 100644 --- a/include/boost/charconv/from_chars.hpp +++ b/include/boost/charconv/from_chars.hpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace boost { namespace charconv { @@ -82,6 +83,44 @@ BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, co namespace detail { +template +from_chars_result from_chars_strtod(const char* first, const char* last, T& value) noexcept +{ + // For strto(f/d) + // Floating point value corresponding to the contents of str on success. + // If the converted value falls out of range of corresponding return type, range error occurs and HUGE_VAL, HUGE_VALF or HUGE_VALL is returned. + // If no conversion can be performed, 0 is returned and *str_end is set to str. + + value = 0; + char* str_end; + T return_value {}; + BOOST_IF_CONSTEXPR (std::is_same::value) + { + return_value = std::strtof(first, &str_end); + if (return_value == HUGE_VALF) + { + return {last, EOVERFLOW}; + } + } + else + { + return_value = std::strtod(first, &str_end); + if (return_value == HUGE_VAL) + { + return {last, ERANGE}; + } + } + + // Since this is a fallback routine we are safe to check for 0 + if (return_value == 0 && str_end == last) + { + return {first, EINVAL}; + } + + value = return_value; + return {str_end, 0}; +} + template from_chars_result from_chars_float_impl(const char* first, const char* last, T& value, chars_format fmt) noexcept { @@ -117,8 +156,8 @@ from_chars_result from_chars_float_impl(const char* first, const char* last, T& } else { - value = 0; - r.ec = ERANGE; + // Fallback to strtod to try again + r = from_chars_strtod(first, last, value); } } else