🔨 fixed number parsing
This commit is contained in:
parent
3b069b4b4c
commit
06e2a291b1
4 changed files with 43 additions and 26 deletions
65
src/json.hpp
65
src/json.hpp
|
@ -222,8 +222,8 @@ class parse_error : public exception
|
||||||
const size_t byte;
|
const size_t byte;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
parse_error(int id, size_t byte_, const char* what_arg)
|
parse_error(int id_, size_t byte_, const char* what_arg)
|
||||||
: exception(id, what_arg), byte(byte_)
|
: exception(id_, what_arg), byte(byte_)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -261,8 +261,8 @@ class invalid_iterator : public exception
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
invalid_iterator(int id, const char* what_arg)
|
invalid_iterator(int id_, const char* what_arg)
|
||||||
: exception(id, what_arg)
|
: exception(id_, what_arg)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -300,8 +300,8 @@ class type_error : public exception
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type_error(int id, const char* what_arg)
|
type_error(int id_, const char* what_arg)
|
||||||
: exception(id, what_arg)
|
: exception(id_, what_arg)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -331,8 +331,8 @@ class out_of_range : public exception
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
out_of_range(int id, const char* what_arg)
|
out_of_range(int id_, const char* what_arg)
|
||||||
: exception(id, what_arg)
|
: exception(id_, what_arg)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -357,8 +357,8 @@ class other_error : public exception
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
other_error(int id, const char* what_arg)
|
other_error(int id_, const char* what_arg)
|
||||||
: exception(id, what_arg)
|
: exception(id_, what_arg)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10828,24 +10828,33 @@ class basic_json
|
||||||
add('\0');
|
add('\0');
|
||||||
--yylen;
|
--yylen;
|
||||||
|
|
||||||
if (has_exp or has_point)
|
// the conversion
|
||||||
|
char* endptr = nullptr;
|
||||||
|
|
||||||
|
// try to parse integers first and fall back to floats
|
||||||
|
if (not has_exp and not has_point)
|
||||||
{
|
{
|
||||||
value_float = std::strtod(yytext.data(), nullptr);
|
errno = 0;
|
||||||
return token_type::value_float;
|
if (has_sign)
|
||||||
|
{
|
||||||
|
value_integer = std::strtoll(yytext.data(), &endptr, 10);
|
||||||
|
if (JSON_LIKELY(errno == 0 and endptr == yytext.data() + yylen))
|
||||||
|
{
|
||||||
|
return token_type::value_integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value_unsigned = std::strtoull(yytext.data(), &endptr, 10);
|
||||||
|
if (JSON_LIKELY(errno == 0 and endptr == yytext.data() + yylen))
|
||||||
|
{
|
||||||
|
return token_type::value_unsigned;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_sign)
|
value_float = std::strtod(yytext.data(), nullptr);
|
||||||
{
|
return token_type::value_float;
|
||||||
char* endptr = nullptr;
|
|
||||||
value_integer = std::strtoll(yytext.data(), &endptr, 10);
|
|
||||||
return token_type::value_integer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char* endptr = nullptr;
|
|
||||||
value_unsigned = std::strtoull(yytext.data(), &endptr, 10);
|
|
||||||
return token_type::value_unsigned;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token_type scan_true()
|
token_type scan_true()
|
||||||
|
@ -10986,6 +10995,12 @@ class basic_json
|
||||||
|
|
||||||
case lexer::token_type::value_float:
|
case lexer::token_type::value_float:
|
||||||
{
|
{
|
||||||
|
// throw in case of infinity or NAN
|
||||||
|
if (not std::isfinite(value_float))
|
||||||
|
{
|
||||||
|
JSON_THROW(out_of_range::create(406, "number overflow parsing '" + get_token_string() + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
result.m_type = value_t::number_float;
|
result.m_type = value_t::number_float;
|
||||||
result.m_value = static_cast<number_float_t>(value_float);
|
result.m_value = static_cast<number_float_t>(value_float);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -529,7 +529,7 @@ TEST_CASE("parser class")
|
||||||
if (c > 0x1f)
|
if (c > 0x1f)
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH(json::parser(s.c_str()).parse(),
|
CHECK_THROWS_WITH(json::parser(s.c_str()).parse(),
|
||||||
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid string: forbidden character after backspace; last read '\"\\" + std::string(1, c) + "'");
|
"[json.exception.parse_error.101] parse error at 3: syntax error - invalid string: forbidden character after backspace; last read '\"\\" + std::string(1, static_cast<char>(c)) + "'");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,6 +216,7 @@ TEST_CASE("regression tests")
|
||||||
{
|
{
|
||||||
json a = {1, 2, 3};
|
json a = {1, 2, 3};
|
||||||
json::reverse_iterator rit = ++a.rbegin();
|
json::reverse_iterator rit = ++a.rbegin();
|
||||||
|
CHECK(*rit == json(2));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json a = {1, 2, 3};
|
json a = {1, 2, 3};
|
||||||
|
|
|
@ -305,6 +305,7 @@ TEST_CASE("compliance tests from nativejson-benchmark")
|
||||||
std::string json_string( (std::istreambuf_iterator<char>(f) ),
|
std::string json_string( (std::istreambuf_iterator<char>(f) ),
|
||||||
(std::istreambuf_iterator<char>()) );
|
(std::istreambuf_iterator<char>()) );
|
||||||
|
|
||||||
|
CAPTURE(json_string);
|
||||||
json j = json::parse(json_string);
|
json j = json::parse(json_string);
|
||||||
CHECK(j.dump() == json_string);
|
CHECK(j.dump() == json_string);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue