mirror of
https://github.com/boostorg/json.git
synced 2026-01-19 04:12:14 +00:00
mode to not parse numbers
This commit is contained in:
committed by
Dmitry Arkhipov
parent
105e74e46f
commit
285c3aa5a2
@@ -668,12 +668,6 @@ static bool parse_option( char const * s )
|
||||
|
||||
char opt = *s++;
|
||||
|
||||
if( opt == 'p' )
|
||||
{
|
||||
popts.precise_parsing = true;
|
||||
return *s == 0;
|
||||
}
|
||||
|
||||
if( *s++ != ':' )
|
||||
{
|
||||
return false;
|
||||
@@ -711,6 +705,22 @@ static bool parse_option( char const * s )
|
||||
case 'b':
|
||||
s_branch = s;
|
||||
break;
|
||||
case 'm':
|
||||
switch( *s )
|
||||
{
|
||||
case 'i':
|
||||
popts.numbers = number_precision::imprecise;
|
||||
break;
|
||||
case 'p':
|
||||
popts.numbers = number_precision::precise;
|
||||
break;
|
||||
case 'n':
|
||||
popts.numbers = number_precision::none;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -817,7 +827,11 @@ main(
|
||||
" (default all)\n"
|
||||
" -n:<number> Number of trials (default 6)\n"
|
||||
" -b:<branch> Branch label for boost implementations\n"
|
||||
" -p Enable precise parsing\n"
|
||||
" -m:(i|p|n) Number parsing mode\n"
|
||||
" (i: imprecise)\n"
|
||||
" (p: precise)\n"
|
||||
" (n: none)\n"
|
||||
" (default imprecise)\n"
|
||||
;
|
||||
|
||||
return 4;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
<member><link linkend="json.ref.boost__json__basic_parser">basic_parser</link></member>
|
||||
<member><link linkend="json.ref.boost__json__key_value_pair">key_value_pair</link></member>
|
||||
<member><link linkend="json.ref.boost__json__monotonic_resource">monotonic_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__monotonic_resource">monotonic_resource</link></member>
|
||||
<member><link linkend="json.ref.boost__json__number_precision">number_precision</link></member>
|
||||
<member><link linkend="json.ref.boost__json__object">object</link></member>
|
||||
<member><link linkend="json.ref.boost__json__parser">parser</link></member>
|
||||
<member><link linkend="json.ref.boost__json__parse_options">parse_options</link></member>
|
||||
|
||||
@@ -1977,6 +1977,9 @@ parse_number(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<char, First_> first)
|
||||
{
|
||||
bool const precise_parsing = opt_.numbers == number_precision::precise;
|
||||
bool const no_parsing = opt_.numbers == number_precision::none;
|
||||
|
||||
// only one of these will be true if we are not resuming
|
||||
// if negative then !zero_first && !nonzero_first
|
||||
// if zero_first then !nonzero_first && !negative
|
||||
@@ -1984,7 +1987,6 @@ parse_number(const char* p,
|
||||
bool const negative = first == '-';
|
||||
bool const zero_first = first == '0';
|
||||
bool const nonzero_first = first == '+';
|
||||
bool const precise_parsing = opt_.precise_parsing;
|
||||
detail::const_stream_wrapper cs(p, end_);
|
||||
number num;
|
||||
const char* begin = cs.begin();
|
||||
@@ -2034,7 +2036,10 @@ parse_number(const char* p,
|
||||
return fail(cs.begin(), error::syntax, &loc);
|
||||
}
|
||||
|
||||
num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
|
||||
if( !no_parsing )
|
||||
num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
|
||||
else
|
||||
num.mant = 0;
|
||||
|
||||
cs += n1;
|
||||
|
||||
@@ -2062,7 +2067,7 @@ parse_number(const char* p,
|
||||
++cs;
|
||||
goto do_exp1;
|
||||
}
|
||||
if(negative)
|
||||
if( negative && !no_parsing )
|
||||
num.mant = ~num.mant + 1;
|
||||
goto finish_signed;
|
||||
}
|
||||
@@ -2089,7 +2094,8 @@ parse_number(const char* p,
|
||||
goto do_num7;
|
||||
}
|
||||
|
||||
num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
|
||||
if( !no_parsing )
|
||||
num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
|
||||
|
||||
BOOST_ASSERT(num.bias == 0);
|
||||
|
||||
@@ -2225,7 +2231,8 @@ do_num2:
|
||||
if( num.mant > 922337203685477580 || (
|
||||
num.mant == 922337203685477580 && c > '8'))
|
||||
break;
|
||||
num.mant = 10 * num.mant + ( c - '0' );
|
||||
else if( !no_parsing )
|
||||
num.mant = 10 * num.mant + ( c - '0' );
|
||||
continue;
|
||||
}
|
||||
goto do_num6; // [.eE]
|
||||
@@ -2259,7 +2266,8 @@ do_num2:
|
||||
if( num.mant > 1844674407370955161 || (
|
||||
num.mant == 1844674407370955161 && c > '5'))
|
||||
break;
|
||||
num.mant = 10 * num.mant + ( c - '0' );
|
||||
else if( !no_parsing )
|
||||
num.mant = 10 * num.mant + ( c - '0' );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2498,7 +2506,7 @@ do_num8:
|
||||
c >= '0' && c <= '9'))
|
||||
{
|
||||
++cs;
|
||||
if(BOOST_JSON_LIKELY(
|
||||
if(!no_parsing && BOOST_JSON_LIKELY(
|
||||
num.mant <= 9007199254740991)) // 2^53-1
|
||||
{
|
||||
--num.bias;
|
||||
@@ -2623,7 +2631,8 @@ do_exp3:
|
||||
return fail(cs.begin(), error::exponent_overflow, &loc);
|
||||
}
|
||||
++cs;
|
||||
num.exp = 10 * num.exp + ( c - '0' );
|
||||
if( !no_parsing )
|
||||
num.exp = 10 * num.exp + ( c - '0' );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2693,6 +2702,8 @@ finish_dub:
|
||||
BOOST_ASSERT( err.ptr == data + full_size );
|
||||
(void)err;
|
||||
}
|
||||
else if ( no_parsing )
|
||||
d = 0;
|
||||
else
|
||||
d = detail::dec_to_float(
|
||||
num.mant,
|
||||
|
||||
@@ -16,6 +16,28 @@
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
/** Enumeration of number parsing modes
|
||||
|
||||
These values are used to select the way to parse numbers.
|
||||
|
||||
@see
|
||||
@ref parse_options,
|
||||
@ref basic_parser,
|
||||
@ref parser.
|
||||
*/
|
||||
enum class number_precision : unsigned char
|
||||
{
|
||||
/// Fast, but potentially less precise mode.
|
||||
imprecise,
|
||||
|
||||
/// Slower, but precise mode.
|
||||
precise,
|
||||
|
||||
/// The fastest mode, that only validates encountered numbers without
|
||||
/// parsing them.
|
||||
none,
|
||||
};
|
||||
|
||||
/** Parser options
|
||||
|
||||
This structure is used for specifying
|
||||
@@ -44,15 +66,20 @@ struct parse_options
|
||||
*/
|
||||
std::size_t max_depth = 32;
|
||||
|
||||
/** Number prasing mode
|
||||
/** Number pasing mode
|
||||
|
||||
This selects enables precise parsing at the cost of performance.
|
||||
This selects the way to parse numbers. The default is to parse them
|
||||
fast, but with possible slight imprecision for floating point numbers
|
||||
with larger mantissas. Users can also choose to parse numbers slower
|
||||
but with full precision. Or to not parse them at all, and only validate
|
||||
numbers. The latter mode is useful for @ref basic_parser instantiations
|
||||
that wish to treat numbers in a custom way.
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
bool precise_parsing = false;
|
||||
number_precision numbers = number_precision::imprecise;
|
||||
|
||||
/** Non-standard extension option
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ testPrecise()
|
||||
{
|
||||
//[doc_parsing_precise
|
||||
parse_options opt;
|
||||
opt.precise_parsing = true;
|
||||
opt.numbers = number_precision::precise;
|
||||
value jv = parse( "1002.9111801605201", storage_ptr(), opt );
|
||||
//]
|
||||
(void)jv;
|
||||
|
||||
@@ -228,7 +228,8 @@ public:
|
||||
for (bool is_precise: {false, true})
|
||||
{
|
||||
parse_options po;
|
||||
po.precise_parsing = is_precise;
|
||||
po.numbers = is_precise ?
|
||||
number_precision::precise : number_precision::imprecise;
|
||||
double const got = f(s, po);
|
||||
auto same = got == need;
|
||||
auto close = same ?
|
||||
@@ -241,6 +242,12 @@ public:
|
||||
<< got << " != " << need << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// test that number_precision::none works
|
||||
parse_options po;
|
||||
po.numbers = number_precision::none;
|
||||
double const got = f(s, po);
|
||||
(void)got;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -423,7 +430,7 @@ public:
|
||||
sprintf( buffer, "%llu.%llue%d", x1, x2, x3 );
|
||||
|
||||
parse_options precise;
|
||||
precise.precise_parsing = true;
|
||||
precise.numbers = number_precision::precise;
|
||||
checkAccuracy( buffer, 2 );
|
||||
checkAccuracy( buffer, 0, precise );
|
||||
}
|
||||
@@ -441,7 +448,7 @@ public:
|
||||
testExtraPrecision()
|
||||
{
|
||||
parse_options opts;
|
||||
opts.precise_parsing = true;
|
||||
opts.numbers = number_precision::precise;
|
||||
BOOST_TEST(
|
||||
parse("1002.9111801605201", {}, opts) == 1002.9111801605201 );
|
||||
BOOST_TEST(
|
||||
|
||||
@@ -358,7 +358,7 @@ public:
|
||||
buffer.data()[1] = '.';
|
||||
|
||||
parse_options precise;
|
||||
precise.precise_parsing = true;
|
||||
precise.numbers = number_precision::precise;
|
||||
|
||||
stream_parser p( {}, precise );
|
||||
error_code ec;
|
||||
|
||||
Reference in New Issue
Block a user