From 7dcc8a56bba738de6267dc4737e75ea68c144536 Mon Sep 17 00:00:00 2001 From: Jett Date: Thu, 20 Oct 2016 22:47:48 -0500 Subject: [PATCH] continuing work on our own strtold - reduced to 3 failing assertions this changes a few things. the name of the function to better represent what it does (string to json number) - we aren't strtoul compliant so best not to lie about that. we remove template code and just use one function. this makes it a bit simpler and we can always add it back if it buys us anything. the penalty for casting down from long double seems to be inconsequential. --- src/json.hpp | 37 ++++++++++++++++--------------------- src/json.hpp.re2c | 37 ++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 7045a7102..149bedae4 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8810,24 +8810,15 @@ basic_json_parser_63: /*! @brief parse string to floating point number - This function is a reimplementation of the strtold family without - regard to locale - - @tparam T a is_floating_point type + This function is a partial reimplementation of the strtold in order to meet needs of JSON number @param[in] str the string we will parse @return the floating point number */ - template ::value>::type> - T strtox(const char *str) const + long double strtojnum(const char *str) const { - constexpr std::array powerof10 { - {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L} - }; - - T result = 0; + long double result = 0; char cp = *str; int exp = 0; // exponent { @@ -8909,22 +8900,26 @@ skip_loop: } // adjust number by powers of ten specified by format and exponent. - if (result != 0.0) + if (result != 0.0L) { - if (exp > std::numeric_limits::max_exponent10) + constexpr std::array powerof10 = { + {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L} + }; + + if (exp > std::numeric_limits::max_exponent10) { - constexpr T inf = std::numeric_limits::infinity(); + constexpr long double inf = std::numeric_limits::infinity(); result = (result < 0) ? -inf : inf; } - else if (exp < std::numeric_limits::min_exponent10) + else if (exp < std::numeric_limits::min_exponent10) { - result = 0.0; + result = 0.0L; } else if (exp < 0) { exp = -exp; - for (std::size_t count = 0; exp; count++, exp >>= 1) + for (std::size_t count = 0; exp; ++count, exp >>= 1) { if (exp & 1) { @@ -8934,7 +8929,7 @@ skip_loop: } else { - for (std::size_t count = 0; exp; count++, exp >>= 1) + for (std::size_t count = 0; exp; ++count, exp >>= 1) { if (exp & 1) { @@ -9045,8 +9040,8 @@ skip_loop: } else { - // parse with strtod - result.m_value.number_float = strtox(reinterpret_cast(m_start)); + // convert string by json number format to floating point + result.m_value.number_float = strtojnum(reinterpret_cast(m_start)); } // save the type diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 53fc2e0ed..ab0969350 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8107,24 +8107,15 @@ class basic_json /*! @brief parse string to floating point number - This function is a reimplementation of the strtold family without - regard to locale - - @tparam T a is_floating_point type + This function is a partial reimplementation of the strtold in order to meet needs of JSON number @param[in] str the string we will parse @return the floating point number */ - template ::value>::type> - T strtox(const char *st) const + long double strtojnum(const char *str) const { - constexpr std::array powerof10 { - {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L} - }; - - T result = 0; + long double result = 0; char cp = *str; int exp = 0; // exponent { @@ -8206,22 +8197,26 @@ skip_loop: } // adjust number by powers of ten specified by format and exponent. - if (result != 0.0) + if (result != 0.0L) { - if (exp > std::numeric_limits::max_exponent10) + constexpr std::array powerof10 = { + {1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L} + }; + + if (exp > std::numeric_limits::max_exponent10) { - constexpr T inf = std::numeric_limits::infinity(); + constexpr long double inf = std::numeric_limits::infinity(); result = (result < 0) ? -inf : inf; } - else if (exp < std::numeric_limits::min_exponent10) + else if (exp < std::numeric_limits::min_exponent10) { - result = 0.0; + result = 0.0L; } else if (exp < 0) { exp = -exp; - for (std::size_t count = 0; exp; count++, exp >>= 1) + for (std::size_t count = 0; exp; ++count, exp >>= 1) { if (exp & 1) { @@ -8231,7 +8226,7 @@ skip_loop: } else { - for (std::size_t count = 0; exp; count++, exp >>= 1) + for (std::size_t count = 0; exp; ++count, exp >>= 1) { if (exp & 1) { @@ -8342,8 +8337,8 @@ skip_loop: } else { - // parse with strtod - result.m_value.number_float = strtox(reinterpret_cast(m_start)); + // convert string by json number format to floating point + result.m_value.number_float = strtojnum(reinterpret_cast(m_start)); } // save the type