Skip to content

Commit 285c3aa

Browse files
committed
mode to not parse numbers
1 parent 105e74e commit 285c3aa

File tree

7 files changed

+84
-23
lines changed

7 files changed

+84
-23
lines changed

bench/bench.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -668,12 +668,6 @@ static bool parse_option( char const * s )
668668

669669
char opt = *s++;
670670

671-
if( opt == 'p' )
672-
{
673-
popts.precise_parsing = true;
674-
return *s == 0;
675-
}
676-
677671
if( *s++ != ':' )
678672
{
679673
return false;
@@ -711,6 +705,22 @@ static bool parse_option( char const * s )
711705
case 'b':
712706
s_branch = s;
713707
break;
708+
case 'm':
709+
switch( *s )
710+
{
711+
case 'i':
712+
popts.numbers = number_precision::imprecise;
713+
break;
714+
case 'p':
715+
popts.numbers = number_precision::precise;
716+
break;
717+
case 'n':
718+
popts.numbers = number_precision::none;
719+
break;
720+
default:
721+
return false;
722+
}
723+
break;
714724
}
715725

716726
return true;
@@ -817,7 +827,11 @@ main(
817827
" (default all)\n"
818828
" -n:<number> Number of trials (default 6)\n"
819829
" -b:<branch> Branch label for boost implementations\n"
820-
" -p Enable precise parsing\n"
830+
" -m:(i|p|n) Number parsing mode\n"
831+
" (i: imprecise)\n"
832+
" (p: precise)\n"
833+
" (n: none)\n"
834+
" (default imprecise)\n"
821835
;
822836

823837
return 4;

doc/qbk/quickref.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
<member><link linkend="json.ref.boost__json__basic_parser">basic_parser</link></member>
2525
<member><link linkend="json.ref.boost__json__key_value_pair">key_value_pair</link></member>
2626
<member><link linkend="json.ref.boost__json__monotonic_resource">monotonic_resource</link></member>
27+
<member><link linkend="json.ref.boost__json__monotonic_resource">monotonic_resource</link></member>
28+
<member><link linkend="json.ref.boost__json__number_precision">number_precision</link></member>
2729
<member><link linkend="json.ref.boost__json__object">object</link></member>
2830
<member><link linkend="json.ref.boost__json__parser">parser</link></member>
2931
<member><link linkend="json.ref.boost__json__parse_options">parse_options</link></member>

include/boost/json/basic_parser_impl.hpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,14 +1977,16 @@ parse_number(const char* p,
19771977
std::integral_constant<bool, StackEmpty_> stack_empty,
19781978
std::integral_constant<char, First_> first)
19791979
{
1980+
bool const precise_parsing = opt_.numbers == number_precision::precise;
1981+
bool const no_parsing = opt_.numbers == number_precision::none;
1982+
19801983
// only one of these will be true if we are not resuming
19811984
// if negative then !zero_first && !nonzero_first
19821985
// if zero_first then !nonzero_first && !negative
19831986
// if nonzero_first then !zero_first && !negative
19841987
bool const negative = first == '-';
19851988
bool const zero_first = first == '0';
19861989
bool const nonzero_first = first == '+';
1987-
bool const precise_parsing = opt_.precise_parsing;
19881990
detail::const_stream_wrapper cs(p, end_);
19891991
number num;
19901992
const char* begin = cs.begin();
@@ -2034,7 +2036,10 @@ parse_number(const char* p,
20342036
return fail(cs.begin(), error::syntax, &loc);
20352037
}
20362038

2037-
num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2039+
if( !no_parsing )
2040+
num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2041+
else
2042+
num.mant = 0;
20382043

20392044
cs += n1;
20402045

@@ -2062,7 +2067,7 @@ parse_number(const char* p,
20622067
++cs;
20632068
goto do_exp1;
20642069
}
2065-
if(negative)
2070+
if( negative && !no_parsing )
20662071
num.mant = ~num.mant + 1;
20672072
goto finish_signed;
20682073
}
@@ -2089,7 +2094,8 @@ parse_number(const char* p,
20892094
goto do_num7;
20902095
}
20912096

2092-
num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2097+
if( !no_parsing )
2098+
num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
20932099

20942100
BOOST_ASSERT(num.bias == 0);
20952101

@@ -2225,7 +2231,8 @@ parse_number(const char* p,
22252231
if( num.mant > 922337203685477580 || (
22262232
num.mant == 922337203685477580 && c > '8'))
22272233
break;
2228-
num.mant = 10 * num.mant + ( c - '0' );
2234+
else if( !no_parsing )
2235+
num.mant = 10 * num.mant + ( c - '0' );
22292236
continue;
22302237
}
22312238
goto do_num6; // [.eE]
@@ -2259,7 +2266,8 @@ parse_number(const char* p,
22592266
if( num.mant > 1844674407370955161 || (
22602267
num.mant == 1844674407370955161 && c > '5'))
22612268
break;
2262-
num.mant = 10 * num.mant + ( c - '0' );
2269+
else if( !no_parsing )
2270+
num.mant = 10 * num.mant + ( c - '0' );
22632271
}
22642272
else
22652273
{
@@ -2498,7 +2506,7 @@ parse_number(const char* p,
24982506
c >= '0' && c <= '9'))
24992507
{
25002508
++cs;
2501-
if(BOOST_JSON_LIKELY(
2509+
if(!no_parsing && BOOST_JSON_LIKELY(
25022510
num.mant <= 9007199254740991)) // 2^53-1
25032511
{
25042512
--num.bias;
@@ -2623,7 +2631,8 @@ parse_number(const char* p,
26232631
return fail(cs.begin(), error::exponent_overflow, &loc);
26242632
}
26252633
++cs;
2626-
num.exp = 10 * num.exp + ( c - '0' );
2634+
if( !no_parsing )
2635+
num.exp = 10 * num.exp + ( c - '0' );
26272636
continue;
26282637
}
26292638
}
@@ -2693,6 +2702,8 @@ parse_number(const char* p,
26932702
BOOST_ASSERT( err.ptr == data + full_size );
26942703
(void)err;
26952704
}
2705+
else if ( no_parsing )
2706+
d = 0;
26962707
else
26972708
d = detail::dec_to_float(
26982709
num.mant,

include/boost/json/parse_options.hpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@
1616
namespace boost {
1717
namespace json {
1818

19+
/** Enumeration of number parsing modes
20+
21+
These values are used to select the way to parse numbers.
22+
23+
@see
24+
@ref parse_options,
25+
@ref basic_parser,
26+
@ref parser.
27+
*/
28+
enum class number_precision : unsigned char
29+
{
30+
/// Fast, but potentially less precise mode.
31+
imprecise,
32+
33+
/// Slower, but precise mode.
34+
precise,
35+
36+
/// The fastest mode, that only validates encountered numbers without
37+
/// parsing them.
38+
none,
39+
};
40+
1941
/** Parser options
2042
2143
This structure is used for specifying
@@ -44,15 +66,20 @@ struct parse_options
4466
*/
4567
std::size_t max_depth = 32;
4668

47-
/** Number prasing mode
69+
/** Number pasing mode
4870
49-
This selects enables precise parsing at the cost of performance.
71+
This selects the way to parse numbers. The default is to parse them
72+
fast, but with possible slight imprecision for floating point numbers
73+
with larger mantissas. Users can also choose to parse numbers slower
74+
but with full precision. Or to not parse them at all, and only validate
75+
numbers. The latter mode is useful for @ref basic_parser instantiations
76+
that wish to treat numbers in a custom way.
5077
5178
@see
5279
@ref basic_parser,
5380
@ref stream_parser.
5481
*/
55-
bool precise_parsing = false;
82+
number_precision numbers = number_precision::imprecise;
5683

5784
/** Non-standard extension option
5885

test/doc_parsing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ testPrecise()
279279
{
280280
//[doc_parsing_precise
281281
parse_options opt;
282-
opt.precise_parsing = true;
282+
opt.numbers = number_precision::precise;
283283
value jv = parse( "1002.9111801605201", storage_ptr(), opt );
284284
//]
285285
(void)jv;

test/double.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,8 @@ class double_test
228228
for (bool is_precise: {false, true})
229229
{
230230
parse_options po;
231-
po.precise_parsing = is_precise;
231+
po.numbers = is_precise ?
232+
number_precision::precise : number_precision::imprecise;
232233
double const got = f(s, po);
233234
auto same = got == need;
234235
auto close = same ?
@@ -241,6 +242,12 @@ class double_test
241242
<< got << " != " << need << "\n";
242243
}
243244
}
245+
246+
// test that number_precision::none works
247+
parse_options po;
248+
po.numbers = number_precision::none;
249+
double const got = f(s, po);
250+
(void)got;
244251
}
245252

246253
void
@@ -423,7 +430,7 @@ class double_test
423430
sprintf( buffer, "%llu.%llue%d", x1, x2, x3 );
424431

425432
parse_options precise;
426-
precise.precise_parsing = true;
433+
precise.numbers = number_precision::precise;
427434
checkAccuracy( buffer, 2 );
428435
checkAccuracy( buffer, 0, precise );
429436
}
@@ -441,7 +448,7 @@ class double_test
441448
testExtraPrecision()
442449
{
443450
parse_options opts;
444-
opts.precise_parsing = true;
451+
opts.numbers = number_precision::precise;
445452
BOOST_TEST(
446453
parse("1002.9111801605201", {}, opts) == 1002.9111801605201 );
447454
BOOST_TEST(

test/limits.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ class limits_test
358358
buffer.data()[1] = '.';
359359

360360
parse_options precise;
361-
precise.precise_parsing = true;
361+
precise.numbers = number_precision::precise;
362362

363363
stream_parser p( {}, precise );
364364
error_code ec;

0 commit comments

Comments
 (0)