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.
This commit is contained in:
Jett 2016-10-20 22:47:48 -05:00
parent 973ee97a93
commit 7dcc8a56bb
2 changed files with 32 additions and 42 deletions

View File

@ -8810,24 +8810,15 @@ basic_json_parser_63:
/*! /*!
@brief parse string to floating point number @brief parse string to floating point number
This function is a reimplementation of the strtold family without This function is a partial reimplementation of the strtold in order to meet needs of JSON number
regard to locale
@tparam T a is_floating_point type
@param[in] str the string we will parse @param[in] str the string we will parse
@return the floating point number @return the floating point number
*/ */
template <typename T, typename = typename std::enable_if< long double strtojnum(const char *str) const
std::is_floating_point<T>::value>::type>
T strtox(const char *str) const
{ {
constexpr std::array<long double, 9> powerof10 { long double result = 0;
{1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
};
T result = 0;
char cp = *str; char cp = *str;
int exp = 0; // exponent int exp = 0; // exponent
{ {
@ -8909,22 +8900,26 @@ skip_loop:
} }
// adjust number by powers of ten specified by format and exponent. // adjust number by powers of ten specified by format and exponent.
if (result != 0.0) if (result != 0.0L)
{ {
if (exp > std::numeric_limits<T>::max_exponent10) constexpr std::array<long double, 9> powerof10 = {
{1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
};
if (exp > std::numeric_limits<long double>::max_exponent10)
{ {
constexpr T inf = std::numeric_limits<T>::infinity(); constexpr long double inf = std::numeric_limits<long double>::infinity();
result = (result < 0) ? -inf : inf; result = (result < 0) ? -inf : inf;
} }
else if (exp < std::numeric_limits<T>::min_exponent10) else if (exp < std::numeric_limits<long double>::min_exponent10)
{ {
result = 0.0; result = 0.0L;
} }
else if (exp < 0) else if (exp < 0)
{ {
exp = -exp; 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) if (exp & 1)
{ {
@ -8934,7 +8929,7 @@ skip_loop:
} }
else else
{ {
for (std::size_t count = 0; exp; count++, exp >>= 1) for (std::size_t count = 0; exp; ++count, exp >>= 1)
{ {
if (exp & 1) if (exp & 1)
{ {
@ -9045,8 +9040,8 @@ skip_loop:
} }
else else
{ {
// parse with strtod // convert string by json number format to floating point
result.m_value.number_float = strtox<number_float_t>(reinterpret_cast<typename string_t::const_pointer>(m_start)); result.m_value.number_float = strtojnum(reinterpret_cast<typename string_t::const_pointer>(m_start));
} }
// save the type // save the type

View File

@ -8107,24 +8107,15 @@ class basic_json
/*! /*!
@brief parse string to floating point number @brief parse string to floating point number
This function is a reimplementation of the strtold family without This function is a partial reimplementation of the strtold in order to meet needs of JSON number
regard to locale
@tparam T a is_floating_point type
@param[in] str the string we will parse @param[in] str the string we will parse
@return the floating point number @return the floating point number
*/ */
template <typename T, typename = typename std::enable_if< long double strtojnum(const char *str) const
std::is_floating_point<T>::value>::type>
T strtox(const char *st) const
{ {
constexpr std::array<long double, 9> powerof10 { long double result = 0;
{1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
};
T result = 0;
char cp = *str; char cp = *str;
int exp = 0; // exponent int exp = 0; // exponent
{ {
@ -8206,22 +8197,26 @@ skip_loop:
} }
// adjust number by powers of ten specified by format and exponent. // adjust number by powers of ten specified by format and exponent.
if (result != 0.0) if (result != 0.0L)
{ {
if (exp > std::numeric_limits<T>::max_exponent10) constexpr std::array<long double, 9> powerof10 = {
{1.e1L, 1.e2L, 1.e4L, 1.e8L, 1.e16L, 1.e32L, 1.e64L, 1.e128L, 1.e256L}
};
if (exp > std::numeric_limits<long double>::max_exponent10)
{ {
constexpr T inf = std::numeric_limits<T>::infinity(); constexpr long double inf = std::numeric_limits<long double>::infinity();
result = (result < 0) ? -inf : inf; result = (result < 0) ? -inf : inf;
} }
else if (exp < std::numeric_limits<T>::min_exponent10) else if (exp < std::numeric_limits<long double>::min_exponent10)
{ {
result = 0.0; result = 0.0L;
} }
else if (exp < 0) else if (exp < 0)
{ {
exp = -exp; 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) if (exp & 1)
{ {
@ -8231,7 +8226,7 @@ skip_loop:
} }
else else
{ {
for (std::size_t count = 0; exp; count++, exp >>= 1) for (std::size_t count = 0; exp; ++count, exp >>= 1)
{ {
if (exp & 1) if (exp & 1)
{ {
@ -8342,8 +8337,8 @@ skip_loop:
} }
else else
{ {
// parse with strtod // convert string by json number format to floating point
result.m_value.number_float = strtox<number_float_t>(reinterpret_cast<typename string_t::const_pointer>(m_start)); result.m_value.number_float = strtojnum(reinterpret_cast<typename string_t::const_pointer>(m_start));
} }
// save the type // save the type