💄 cleanup
This commit is contained in:
parent
926af6d50b
commit
9f5dccbab5
2 changed files with 128 additions and 164 deletions
136
src/json.hpp
136
src/json.hpp
|
@ -10840,13 +10840,13 @@ basic_json_parser_66:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief parse string into a built-in arithmetic type as if
|
@brief parse string into a built-in arithmetic type as if the current
|
||||||
the current locale is POSIX.
|
locale is POSIX.
|
||||||
|
|
||||||
note: in floating-point case strtod may parse
|
@note in floating-point case strtod may parse past the token's end -
|
||||||
past the token's end - this is not an error.
|
this is not an error
|
||||||
|
|
||||||
any leading blanks are not handled.
|
@note any leading blanks are not handled
|
||||||
*/
|
*/
|
||||||
struct strtonum
|
struct strtonum
|
||||||
{
|
{
|
||||||
|
@ -10855,36 +10855,37 @@ basic_json_parser_66:
|
||||||
: m_start(start), m_end(end)
|
: m_start(start), m_end(end)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// return true iff parsed successfully as
|
/*!
|
||||||
/// number of type T.
|
@return true iff parsed successfully as number of type T
|
||||||
///
|
|
||||||
/// @val shall contain parsed value, or
|
@param[in,out] val shall contain parsed value, or undefined value
|
||||||
/// undefined value if could not parse.
|
if could not parse
|
||||||
template<typename T,
|
*/
|
||||||
typename = typename std::enable_if<
|
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||||
std::is_arithmetic<T>::value>::type >
|
|
||||||
bool to(T& val) const
|
bool to(T& val) const
|
||||||
{
|
{
|
||||||
return parse(val, std::is_integral<T>());
|
return parse(val, std::is_integral<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return true iff token matches ^[+-]\d+$
|
/*!
|
||||||
///
|
This is a helper to determine whether to parse the token into
|
||||||
/// this is a helper to determine whether to
|
floating-point or integral type.
|
||||||
/// parse the token into floating-point or
|
|
||||||
/// integral type. We wouldn't need it if
|
@note We wouldn't need it if we had separate token types for
|
||||||
/// we had separate token types for integral
|
integral and floating-point cases.
|
||||||
/// and floating-point cases.
|
|
||||||
|
@return true iff token matches `^[+-]\d+$`
|
||||||
|
*/
|
||||||
bool is_integral() const
|
bool is_integral() const
|
||||||
{
|
{
|
||||||
const char* p = m_start;
|
const char* p = m_start;
|
||||||
|
|
||||||
if (!p)
|
if (p == nullptr)
|
||||||
{
|
{
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p == '-' or * p == '+')
|
if ((*p == '-') or (*p == '+'))
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
@ -10894,13 +10895,12 @@ basic_json_parser_66:
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p < m_end and* p >= '0'
|
while ((p < m_end) and (*p >= '0') and (*p <= '9'))
|
||||||
and * p <= '9')
|
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p == m_end;
|
return (p == m_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -10909,24 +10909,17 @@ basic_json_parser_66:
|
||||||
|
|
||||||
// overloaded wrappers for strtod/strtof/strtold
|
// overloaded wrappers for strtod/strtof/strtold
|
||||||
// that will be called from parse<floating_point_t>
|
// that will be called from parse<floating_point_t>
|
||||||
|
static void strtof(float& f, const char* str, char** endptr)
|
||||||
static void strtof(float& f,
|
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtof(str, endptr);
|
f = std::strtof(str, endptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strtof(double& f,
|
static void strtof(double& f, const char* str, char** endptr)
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtod(str, endptr);
|
f = std::strtod(str, endptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strtof(long double& f,
|
static void strtof(long double& f, const char* str, char** endptr)
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtold(str, endptr);
|
f = std::strtold(str, endptr);
|
||||||
}
|
}
|
||||||
|
@ -10934,37 +10927,32 @@ basic_json_parser_66:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool parse(T& value, /*is_integral=*/std::false_type) const
|
bool parse(T& value, /*is_integral=*/std::false_type) const
|
||||||
{
|
{
|
||||||
// replace decimal separator with locale-specific
|
// replace decimal separator with locale-specific version,
|
||||||
// version, when necessary; data will point to
|
// when necessary; data will point to either the original
|
||||||
// either the original string, or buf, or tempstr
|
// string, or buf, or tempstr containing the fixed string.
|
||||||
// containing the fixed string.
|
|
||||||
std::string tempstr;
|
std::string tempstr;
|
||||||
std::array<char, 64> buf;
|
std::array<char, 64> buf;
|
||||||
const size_t len = static_cast<size_t>(m_end - m_start);
|
const size_t len = static_cast<size_t>(m_end - m_start);
|
||||||
|
|
||||||
// Since dealing with strtod family of functions,
|
// since dealing with strtod family of functions, we're
|
||||||
// we're getting the decimal point char from the
|
// getting the decimal point char from the C locale facilities
|
||||||
// C locale facilities instead of C++'s numpunct
|
// instead of C++'s numpunct facet of the current std::locale
|
||||||
// facet of the current std::locale;
|
|
||||||
const auto loc = localeconv();
|
const auto loc = localeconv();
|
||||||
assert(loc != nullptr);
|
assert(loc != nullptr);
|
||||||
const char decimal_point_char = !loc->decimal_point ? '.'
|
const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
|
||||||
: loc->decimal_point[0];
|
|
||||||
|
|
||||||
const char* data = m_start;
|
const char* data = m_start;
|
||||||
|
|
||||||
if (decimal_point_char != '.')
|
if (decimal_point_char != '.')
|
||||||
{
|
{
|
||||||
const size_t ds_pos = static_cast<size_t>(
|
const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);
|
||||||
std::find(m_start, m_end, '.') - m_start );
|
|
||||||
|
|
||||||
if (ds_pos != len)
|
if (ds_pos != len)
|
||||||
{
|
{
|
||||||
// copy the data into the local buffer or
|
// copy the data into the local buffer or tempstr, if
|
||||||
// tempstr, if buffer is too small;
|
// buffer is too small; replace decimal separator, and
|
||||||
// replace decimal separator, and update
|
// update data to point to the modified bytes
|
||||||
// data to point to the modified bytes
|
if ((len + 1) < buf.size())
|
||||||
if (len + 1 < buf.size())
|
|
||||||
{
|
{
|
||||||
std::copy(m_start, m_end, buf.data());
|
std::copy(m_start, m_end, buf.data());
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
|
@ -10985,13 +10973,12 @@ basic_json_parser_66:
|
||||||
// this calls appropriate overload depending on T
|
// this calls appropriate overload depending on T
|
||||||
strtof(value, data, &endptr);
|
strtof(value, data, &endptr);
|
||||||
|
|
||||||
// note that reading past the end is OK, the data may be,
|
// note that reading past the end is OK, the data may be, for
|
||||||
// for example, "123.", where the parsed token only
|
// example, "123.", where the parsed token only contains
|
||||||
// contains "123", but strtod will read the dot as well.
|
// "123", but strtod will read the dot as well.
|
||||||
const bool ok = endptr >= data + len
|
const bool ok = (endptr >= (data + len)) and (len > 0);
|
||||||
and len > 0;
|
|
||||||
|
|
||||||
if (ok and value == 0.0 and * data == '-')
|
if (ok and (value == 0.0) and (*data == '-'))
|
||||||
{
|
{
|
||||||
// some implementations forget to negate the zero
|
// some implementations forget to negate the zero
|
||||||
value = -0.0;
|
value = -0.0;
|
||||||
|
@ -11000,16 +10987,12 @@ basic_json_parser_66:
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed long long parse_integral(
|
signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const
|
||||||
char** endptr,
|
|
||||||
/*is_signed*/std::true_type) const
|
|
||||||
{
|
{
|
||||||
return std::strtoll(m_start, endptr, 10);
|
return std::strtoll(m_start, endptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long parse_integral(
|
unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const
|
||||||
char** endptr,
|
|
||||||
/*is_signed*/std::false_type) const
|
|
||||||
{
|
{
|
||||||
return std::strtoull(m_start, endptr, 10);
|
return std::strtoull(m_start, endptr, 10);
|
||||||
}
|
}
|
||||||
|
@ -11021,17 +11004,17 @@ basic_json_parser_66:
|
||||||
errno = 0; // these are thread-local
|
errno = 0; // these are thread-local
|
||||||
const auto x = parse_integral(&endptr, std::is_signed<T>());
|
const auto x = parse_integral(&endptr, std::is_signed<T>());
|
||||||
|
|
||||||
static_assert(std::is_signed<T>() // called right overload?
|
// called right overload?
|
||||||
== std::is_signed<decltype(x)>(), "");
|
static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");
|
||||||
|
|
||||||
value = static_cast<T>(x);
|
value = static_cast<T>(x);
|
||||||
|
|
||||||
return x == static_cast<decltype(x)>(value) // x fits into destination T
|
return (x == static_cast<decltype(x)>(value)) // x fits into destination T
|
||||||
and (x < 0) == (value < 0) // preserved sign
|
and (x < 0) == (value < 0) // preserved sign
|
||||||
and (x != 0 or is_integral()) // strto[u]ll did nto fail
|
and ((x != 0) or is_integral()) // strto[u]ll did nto fail
|
||||||
and errno == 0 // strto[u]ll did not overflow
|
and (errno == 0) // strto[u]ll did not overflow
|
||||||
and m_start < m_end // token was not empty
|
and (m_start < m_end) // token was not empty
|
||||||
and endptr == m_end; // parsed entire token exactly
|
and (endptr == m_end); // parsed entire token exactly
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11061,13 +11044,13 @@ basic_json_parser_66:
|
||||||
strtonum num(reinterpret_cast<const char*>(m_start),
|
strtonum num(reinterpret_cast<const char*>(m_start),
|
||||||
reinterpret_cast<const char*>(m_cursor));
|
reinterpret_cast<const char*>(m_cursor));
|
||||||
|
|
||||||
const bool is_negative = *m_start == '-';
|
const bool is_negative = (*m_start == '-');
|
||||||
|
|
||||||
result.m_type = value_t::discarded;
|
result.m_type = value_t::discarded;
|
||||||
|
|
||||||
if (not num.is_integral())
|
if (not num.is_integral())
|
||||||
{
|
{
|
||||||
; // will parse as float below
|
// will parse as float below
|
||||||
}
|
}
|
||||||
else if (is_negative)
|
else if (is_negative)
|
||||||
{
|
{
|
||||||
|
@ -11089,11 +11072,10 @@ basic_json_parser_66:
|
||||||
}
|
}
|
||||||
|
|
||||||
number_float_t val{0};
|
number_float_t val{0};
|
||||||
if (result.m_type != value_t::discarded
|
if (result.m_type != value_t::discarded or (not num.to(val)))
|
||||||
or !num.to(val))
|
|
||||||
{
|
{
|
||||||
return; // already have a value from above
|
// already have a value from above or couldn't parse as float_t
|
||||||
// or couldn't parse as float_t
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.m_type = value_t::number_float;
|
result.m_type = value_t::number_float;
|
||||||
|
|
|
@ -9990,13 +9990,13 @@ class basic_json
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief parse string into a built-in arithmetic type as if
|
@brief parse string into a built-in arithmetic type as if the current
|
||||||
the current locale is POSIX.
|
locale is POSIX.
|
||||||
|
|
||||||
note: in floating-point case strtod may parse
|
@note in floating-point case strtod may parse past the token's end -
|
||||||
past the token's end - this is not an error.
|
this is not an error
|
||||||
|
|
||||||
any leading blanks are not handled.
|
@note any leading blanks are not handled
|
||||||
*/
|
*/
|
||||||
struct strtonum
|
struct strtonum
|
||||||
{
|
{
|
||||||
|
@ -10005,36 +10005,37 @@ class basic_json
|
||||||
: m_start(start), m_end(end)
|
: m_start(start), m_end(end)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// return true iff parsed successfully as
|
/*!
|
||||||
/// number of type T.
|
@return true iff parsed successfully as number of type T
|
||||||
///
|
|
||||||
/// @val shall contain parsed value, or
|
@param[in,out] val shall contain parsed value, or undefined value
|
||||||
/// undefined value if could not parse.
|
if could not parse
|
||||||
template<typename T,
|
*/
|
||||||
typename = typename std::enable_if<
|
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type>
|
||||||
std::is_arithmetic<T>::value>::type >
|
|
||||||
bool to(T& val) const
|
bool to(T& val) const
|
||||||
{
|
{
|
||||||
return parse(val, std::is_integral<T>());
|
return parse(val, std::is_integral<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return true iff token matches ^[+-]\d+$
|
/*!
|
||||||
///
|
This is a helper to determine whether to parse the token into
|
||||||
/// this is a helper to determine whether to
|
floating-point or integral type.
|
||||||
/// parse the token into floating-point or
|
|
||||||
/// integral type. We wouldn't need it if
|
@note We wouldn't need it if we had separate token types for
|
||||||
/// we had separate token types for integral
|
integral and floating-point cases.
|
||||||
/// and floating-point cases.
|
|
||||||
|
@return true iff token matches `^[+-]\d+$`
|
||||||
|
*/
|
||||||
bool is_integral() const
|
bool is_integral() const
|
||||||
{
|
{
|
||||||
const char* p = m_start;
|
const char* p = m_start;
|
||||||
|
|
||||||
if (!p)
|
if (p == nullptr)
|
||||||
{
|
{
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*p == '-' or * p == '+')
|
if ((*p == '-') or (*p == '+'))
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
@ -10044,13 +10045,12 @@ class basic_json
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
while (p < m_end and* p >= '0'
|
while ((p < m_end) and (*p >= '0') and (*p <= '9'))
|
||||||
and * p <= '9')
|
|
||||||
{
|
{
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p == m_end;
|
return (p == m_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -10059,24 +10059,17 @@ class basic_json
|
||||||
|
|
||||||
// overloaded wrappers for strtod/strtof/strtold
|
// overloaded wrappers for strtod/strtof/strtold
|
||||||
// that will be called from parse<floating_point_t>
|
// that will be called from parse<floating_point_t>
|
||||||
|
static void strtof(float& f, const char* str, char** endptr)
|
||||||
static void strtof(float& f,
|
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtof(str, endptr);
|
f = std::strtof(str, endptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strtof(double& f,
|
static void strtof(double& f, const char* str, char** endptr)
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtod(str, endptr);
|
f = std::strtod(str, endptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strtof(long double& f,
|
static void strtof(long double& f, const char* str, char** endptr)
|
||||||
const char* str,
|
|
||||||
char** endptr)
|
|
||||||
{
|
{
|
||||||
f = std::strtold(str, endptr);
|
f = std::strtold(str, endptr);
|
||||||
}
|
}
|
||||||
|
@ -10084,37 +10077,32 @@ class basic_json
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool parse(T& value, /*is_integral=*/std::false_type) const
|
bool parse(T& value, /*is_integral=*/std::false_type) const
|
||||||
{
|
{
|
||||||
// replace decimal separator with locale-specific
|
// replace decimal separator with locale-specific version,
|
||||||
// version, when necessary; data will point to
|
// when necessary; data will point to either the original
|
||||||
// either the original string, or buf, or tempstr
|
// string, or buf, or tempstr containing the fixed string.
|
||||||
// containing the fixed string.
|
|
||||||
std::string tempstr;
|
std::string tempstr;
|
||||||
std::array<char, 64> buf;
|
std::array<char, 64> buf;
|
||||||
const size_t len = static_cast<size_t>(m_end - m_start);
|
const size_t len = static_cast<size_t>(m_end - m_start);
|
||||||
|
|
||||||
// Since dealing with strtod family of functions,
|
// since dealing with strtod family of functions, we're
|
||||||
// we're getting the decimal point char from the
|
// getting the decimal point char from the C locale facilities
|
||||||
// C locale facilities instead of C++'s numpunct
|
// instead of C++'s numpunct facet of the current std::locale
|
||||||
// facet of the current std::locale;
|
|
||||||
const auto loc = localeconv();
|
const auto loc = localeconv();
|
||||||
assert(loc != nullptr);
|
assert(loc != nullptr);
|
||||||
const char decimal_point_char = !loc->decimal_point ? '.'
|
const char decimal_point_char = (loc->decimal_point == nullptr) ? '.' : loc->decimal_point[0];
|
||||||
: loc->decimal_point[0];
|
|
||||||
|
|
||||||
const char* data = m_start;
|
const char* data = m_start;
|
||||||
|
|
||||||
if (decimal_point_char != '.')
|
if (decimal_point_char != '.')
|
||||||
{
|
{
|
||||||
const size_t ds_pos = static_cast<size_t>(
|
const size_t ds_pos = static_cast<size_t>(std::find(m_start, m_end, '.') - m_start);
|
||||||
std::find(m_start, m_end, '.') - m_start );
|
|
||||||
|
|
||||||
if (ds_pos != len)
|
if (ds_pos != len)
|
||||||
{
|
{
|
||||||
// copy the data into the local buffer or
|
// copy the data into the local buffer or tempstr, if
|
||||||
// tempstr, if buffer is too small;
|
// buffer is too small; replace decimal separator, and
|
||||||
// replace decimal separator, and update
|
// update data to point to the modified bytes
|
||||||
// data to point to the modified bytes
|
if ((len + 1) < buf.size())
|
||||||
if (len + 1 < buf.size())
|
|
||||||
{
|
{
|
||||||
std::copy(m_start, m_end, buf.data());
|
std::copy(m_start, m_end, buf.data());
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
|
@ -10135,13 +10123,12 @@ class basic_json
|
||||||
// this calls appropriate overload depending on T
|
// this calls appropriate overload depending on T
|
||||||
strtof(value, data, &endptr);
|
strtof(value, data, &endptr);
|
||||||
|
|
||||||
// note that reading past the end is OK, the data may be,
|
// note that reading past the end is OK, the data may be, for
|
||||||
// for example, "123.", where the parsed token only
|
// example, "123.", where the parsed token only contains
|
||||||
// contains "123", but strtod will read the dot as well.
|
// "123", but strtod will read the dot as well.
|
||||||
const bool ok = endptr >= data + len
|
const bool ok = (endptr >= (data + len)) and (len > 0);
|
||||||
and len > 0;
|
|
||||||
|
|
||||||
if (ok and value == 0.0 and * data == '-')
|
if (ok and (value == 0.0) and (*data == '-'))
|
||||||
{
|
{
|
||||||
// some implementations forget to negate the zero
|
// some implementations forget to negate the zero
|
||||||
value = -0.0;
|
value = -0.0;
|
||||||
|
@ -10150,16 +10137,12 @@ class basic_json
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed long long parse_integral(
|
signed long long parse_integral(char** endptr, /*is_signed*/std::true_type) const
|
||||||
char** endptr,
|
|
||||||
/*is_signed*/std::true_type) const
|
|
||||||
{
|
{
|
||||||
return std::strtoll(m_start, endptr, 10);
|
return std::strtoll(m_start, endptr, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long parse_integral(
|
unsigned long long parse_integral(char** endptr, /*is_signed*/std::false_type) const
|
||||||
char** endptr,
|
|
||||||
/*is_signed*/std::false_type) const
|
|
||||||
{
|
{
|
||||||
return std::strtoull(m_start, endptr, 10);
|
return std::strtoull(m_start, endptr, 10);
|
||||||
}
|
}
|
||||||
|
@ -10171,17 +10154,17 @@ class basic_json
|
||||||
errno = 0; // these are thread-local
|
errno = 0; // these are thread-local
|
||||||
const auto x = parse_integral(&endptr, std::is_signed<T>());
|
const auto x = parse_integral(&endptr, std::is_signed<T>());
|
||||||
|
|
||||||
static_assert(std::is_signed<T>() // called right overload?
|
// called right overload?
|
||||||
== std::is_signed<decltype(x)>(), "");
|
static_assert(std::is_signed<T>() == std::is_signed<decltype(x)>(), "");
|
||||||
|
|
||||||
value = static_cast<T>(x);
|
value = static_cast<T>(x);
|
||||||
|
|
||||||
return x == static_cast<decltype(x)>(value) // x fits into destination T
|
return (x == static_cast<decltype(x)>(value)) // x fits into destination T
|
||||||
and (x < 0) == (value < 0) // preserved sign
|
and (x < 0) == (value < 0) // preserved sign
|
||||||
and (x != 0 or is_integral()) // strto[u]ll did nto fail
|
and ((x != 0) or is_integral()) // strto[u]ll did nto fail
|
||||||
and errno == 0 // strto[u]ll did not overflow
|
and (errno == 0) // strto[u]ll did not overflow
|
||||||
and m_start < m_end // token was not empty
|
and (m_start < m_end) // token was not empty
|
||||||
and endptr == m_end; // parsed entire token exactly
|
and (endptr == m_end); // parsed entire token exactly
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10211,13 +10194,13 @@ class basic_json
|
||||||
strtonum num(reinterpret_cast<const char*>(m_start),
|
strtonum num(reinterpret_cast<const char*>(m_start),
|
||||||
reinterpret_cast<const char*>(m_cursor));
|
reinterpret_cast<const char*>(m_cursor));
|
||||||
|
|
||||||
const bool is_negative = *m_start == '-';
|
const bool is_negative = (*m_start == '-');
|
||||||
|
|
||||||
result.m_type = value_t::discarded;
|
result.m_type = value_t::discarded;
|
||||||
|
|
||||||
if (not num.is_integral())
|
if (not num.is_integral())
|
||||||
{
|
{
|
||||||
; // will parse as float below
|
// will parse as float below
|
||||||
}
|
}
|
||||||
else if (is_negative)
|
else if (is_negative)
|
||||||
{
|
{
|
||||||
|
@ -10239,11 +10222,10 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
number_float_t val{0};
|
number_float_t val{0};
|
||||||
if (result.m_type != value_t::discarded
|
if (result.m_type != value_t::discarded or (not num.to(val)))
|
||||||
or !num.to(val))
|
|
||||||
{
|
{
|
||||||
return; // already have a value from above
|
// already have a value from above or couldn't parse as float_t
|
||||||
// or couldn't parse as float_t
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.m_type = value_t::number_float;
|
result.m_type = value_t::number_float;
|
||||||
|
|
Loading…
Reference in a new issue