From 1803bd9243b9f39a7ad63ff3893e50f404ae03ef Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Wed, 31 May 2023 18:12:44 +0300 Subject: [PATCH] mode to not parse numbers --- bench/bench.cpp | 28 ++++++++++++++++++------ include/boost/json/basic_parser_impl.hpp | 26 +++++++++++++++------- include/boost/json/parse_options.hpp | 9 +++++++- test/doc_parsing.cpp | 2 +- test/double.cpp | 13 ++++++++--- test/limits.cpp | 2 +- 6 files changed, 59 insertions(+), 21 deletions(-) diff --git a/bench/bench.cpp b/bench/bench.cpp index 10af36e9e..05b55e5fb 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -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.number_parse_mode = number_parse_mode_t::imprecise; + break; + case 'p': + popts.number_parse_mode = number_parse_mode_t::precise; + break; + case 'n': + popts.number_parse_mode = number_parse_mode_t::none; + break; + default: + return false; + } + break; } return true; @@ -817,7 +827,11 @@ main( " (default all)\n" " -n: Number of trials (default 6)\n" " -b: 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; diff --git a/include/boost/json/basic_parser_impl.hpp b/include/boost/json/basic_parser_impl.hpp index d3f165e60..b30d46b32 100644 --- a/include/boost/json/basic_parser_impl.hpp +++ b/include/boost/json/basic_parser_impl.hpp @@ -1984,7 +1984,10 @@ 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; + bool const precise_parsing = + opt_.number_parse_mode == number_parse_mode_t::precise; + bool const no_parsing = + opt_.number_parse_mode == number_parse_mode_t::none; detail::const_stream_wrapper cs(p, end_); number num; const char* begin = cs.begin(); @@ -2034,7 +2037,8 @@ 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 ); cs += n1; @@ -2062,7 +2066,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 +2093,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 +2230,8 @@ parse_number(const char* p, 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 +2265,8 @@ parse_number(const char* p, 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 +2505,7 @@ parse_number(const char* p, 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 +2630,8 @@ parse_number(const char* p, 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 +2701,8 @@ parse_number(const char* p, BOOST_ASSERT( err.ptr == data + full_size ); (void)err; } + else if ( no_parsing ) + d = 0; else d = detail::dec_to_float( num.mant, diff --git a/include/boost/json/parse_options.hpp b/include/boost/json/parse_options.hpp index d3a33d6a1..32e5ef287 100644 --- a/include/boost/json/parse_options.hpp +++ b/include/boost/json/parse_options.hpp @@ -16,6 +16,13 @@ namespace boost { namespace json { +enum class number_parse_mode_t : unsigned char +{ + imprecise, + precise, + none, +}; + /** Parser options This structure is used for specifying @@ -52,7 +59,7 @@ struct parse_options @ref basic_parser, @ref stream_parser. */ - bool precise_parsing = false; + number_parse_mode_t number_parse_mode = number_parse_mode_t::imprecise; /** Non-standard extension option diff --git a/test/doc_parsing.cpp b/test/doc_parsing.cpp index b3431725e..17f446089 100644 --- a/test/doc_parsing.cpp +++ b/test/doc_parsing.cpp @@ -279,7 +279,7 @@ testPrecise() { //[doc_parsing_precise parse_options opt; - opt.precise_parsing = true; + opt.number_parse_mode = number_parse_mode_t::precise; value jv = parse( "1002.9111801605201", storage_ptr(), opt ); //] (void)jv; diff --git a/test/double.cpp b/test/double.cpp index 26a97ceb6..6af03b179 100644 --- a/test/double.cpp +++ b/test/double.cpp @@ -228,7 +228,8 @@ class double_test for (bool is_precise: {false, true}) { parse_options po; - po.precise_parsing = is_precise; + po.number_parse_mode = is_precise ? + number_parse_mode_t::precise : number_parse_mode_t::imprecise; double const got = f(s, po); auto same = got == need; auto close = same ? @@ -241,6 +242,12 @@ class double_test << got << " != " << need << "\n"; } } + + // test that number_parse_mode_t::none works + parse_options po; + po.number_parse_mode = number_parse_mode_t::none; + double const got = f(s, po); + (void)got; } void @@ -423,7 +430,7 @@ class double_test sprintf( buffer, "%llu.%llue%d", x1, x2, x3 ); parse_options precise; - precise.precise_parsing = true; + precise.number_parse_mode = number_parse_mode_t::precise; checkAccuracy( buffer, 2 ); checkAccuracy( buffer, 0, precise ); } @@ -441,7 +448,7 @@ class double_test testExtraPrecision() { parse_options opts; - opts.precise_parsing = true; + opts.number_parse_mode = number_parse_mode_t::precise; BOOST_TEST( parse("1002.9111801605201", {}, opts) == 1002.9111801605201 ); BOOST_TEST( diff --git a/test/limits.cpp b/test/limits.cpp index c75d8a50e..51a580de9 100644 --- a/test/limits.cpp +++ b/test/limits.cpp @@ -358,7 +358,7 @@ class limits_test buffer.data()[1] = '.'; parse_options precise; - precise.precise_parsing = true; + precise.number_parse_mode = number_parse_mode_t::precise; stream_parser p( {}, precise ); error_code ec;