Skip to content

Commit

Permalink
split parse_number into separate instatntiations per number parsing mode
Browse files Browse the repository at this point in the history
  • Loading branch information
grisumbras committed May 31, 2023
1 parent 0696eb5 commit abafb5b
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 32 deletions.
5 changes: 3 additions & 2 deletions include/boost/json/basic_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,10 +440,11 @@ class basic_parser
std::integral_constant<bool, IsKey_> is_key,
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);

template<bool StackEmpty_, char First_>
template<bool StackEmpty_, char First_, number_parse_mode_t Mode_>
const char* parse_number(const char* p,
std::integral_constant<bool, StackEmpty_> stack_empty,
std::integral_constant<char, First_> first);
std::integral_constant<char, First_> first,
std::integral_constant<number_parse_mode_t, Mode_> mode);

template<bool StackEmpty_, bool IsKey_/*,
bool AllowBadUTF8_*/>
Expand Down
150 changes: 120 additions & 30 deletions include/boost/json/basic_parser_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,13 +605,79 @@ parse_value(const char* p,
switch(*p)
{
case '0':
return parse_number(p, std::true_type(), std::integral_constant<char, '0'>());
switch( opt_.number_parse_mode )
{
case number_parse_mode_t::imprecise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '0'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::imprecise>());
case number_parse_mode_t::precise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '0'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::precise>());
case number_parse_mode_t::none:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '0'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::none>());
default:
BOOST_JSON_UNREACHABLE();
}
case '-':
return parse_number(p, std::true_type(), std::integral_constant<char, '-'>());
switch( opt_.number_parse_mode )
{
case number_parse_mode_t::imprecise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '-'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::imprecise>());
case number_parse_mode_t::precise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '-'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::precise>());
case number_parse_mode_t::none:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '-'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::none>());
default:
BOOST_JSON_UNREACHABLE();
}
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
return parse_number(p, std::true_type(), std::integral_constant<char, '+'>());
switch( opt_.number_parse_mode )
{
case number_parse_mode_t::imprecise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '+'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::imprecise>());
case number_parse_mode_t::precise:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '+'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::precise>());
case number_parse_mode_t::none:
return parse_number(
p,
std::true_type(),
std::integral_constant<char, '+'>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::none>());
default:
BOOST_JSON_UNREACHABLE();
}
case 'n':
return parse_literal( p, mp11::mp_int<detail::null_literal>() );
case 't':
Expand Down Expand Up @@ -708,7 +774,29 @@ resume_value(const char* p,
case state::num7: case state::num8:
case state::exp1: case state::exp2:
case state::exp3:
return parse_number(p, std::false_type(), std::integral_constant<char, 0>());
switch( opt_.number_parse_mode )
{
case number_parse_mode_t::imprecise:
return parse_number(
p,
std::false_type(),
std::integral_constant<char, 0>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::imprecise>());
case number_parse_mode_t::precise:
return parse_number(
p,
std::false_type(),
std::integral_constant<char, 0>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::precise>());
case number_parse_mode_t::none:
return parse_number(
p,
std::false_type(),
std::integral_constant<char, 0>(),
std::integral_constant<number_parse_mode_t, number_parse_mode_t::none>());
default:
BOOST_JSON_UNREACHABLE();
}

// KRYSTIAN NOTE: these are special cases
case state::val1:
Expand Down Expand Up @@ -1874,24 +1962,24 @@ parse_array(const char* p,
//----------------------------------------------------------

template<class Handler>
template<bool StackEmpty_, char First_>
template<bool StackEmpty_, char First_, number_parse_mode_t Mode_>
const char*
basic_parser<Handler>::
parse_number(const char* p,
std::integral_constant<bool, StackEmpty_> stack_empty,
std::integral_constant<char, First_> first)
std::integral_constant<char, First_> first,
std::integral_constant<number_parse_mode_t, Mode_> mode)
{
constexpr bool precise_parsing = mode == number_parse_mode_t::precise;
constexpr bool no_parsing = mode == number_parse_mode_t::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
// if nonzero_first then !zero_first && !negative
bool const negative = first == '-';
bool const zero_first = first == '0';
bool const nonzero_first = first == '+';
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();
Expand Down Expand Up @@ -1935,8 +2023,10 @@ parse_number(const char* p,
return fail(cs.begin(), error::syntax, &loc);
}

if( !no_parsing )
BOOST_IF_CONSTEXPR( !no_parsing )
num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
else
num.mant = 0;

cs += n1;

Expand Down Expand Up @@ -1964,7 +2054,7 @@ parse_number(const char* p,
++cs;
goto do_exp1;
}
if( negative && !no_parsing )
BOOST_IF_CONSTEXPR( negative && !no_parsing )
num.mant = ~num.mant + 1;
goto finish_signed;
}
Expand All @@ -1991,7 +2081,7 @@ parse_number(const char* p,
goto do_num7;
}

if( !no_parsing )
BOOST_IF_CONSTEXPR( !no_parsing )
num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );

BOOST_ASSERT(num.bias == 0);
Expand Down Expand Up @@ -2080,7 +2170,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return maybe_suspend(
cs.begin(), state::num1, num);
Expand All @@ -2105,7 +2195,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num2, num);
}
Expand All @@ -2120,7 +2210,7 @@ parse_number(const char* p,
if( num.mant > 922337203685477580 || (
num.mant == 922337203685477580 && c > '8'))
break;
else if( !no_parsing )
BOOST_IF_CONSTEXPR( !no_parsing )
num.mant = 10 * num.mant + ( c - '0' );
continue;
}
Expand All @@ -2140,7 +2230,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num2, num);
}
Expand All @@ -2155,7 +2245,7 @@ parse_number(const char* p,
if( num.mant > 1844674407370955161 || (
num.mant == 1844674407370955161 && c > '5'))
break;
else if( !no_parsing )
BOOST_IF_CONSTEXPR( !no_parsing )
num.mant = 10 * num.mant + ( c - '0' );
}
else
Expand Down Expand Up @@ -2183,7 +2273,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num3, num);
}
Expand Down Expand Up @@ -2229,7 +2319,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return maybe_suspend(
cs.begin(), state::num4, num);
Expand Down Expand Up @@ -2268,7 +2358,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num5, num);
}
Expand Down Expand Up @@ -2306,7 +2396,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num6, num);
}
Expand Down Expand Up @@ -2346,7 +2436,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num7, num);
}
Expand Down Expand Up @@ -2384,7 +2474,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::num8, num);
}
Expand Down Expand Up @@ -2429,7 +2519,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return maybe_suspend(
cs.begin(), state::exp1, num);
Expand Down Expand Up @@ -2460,7 +2550,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::exp2, num);
}
Expand Down Expand Up @@ -2499,7 +2589,7 @@ parse_number(const char* p,
{begin, cs.used(begin)}, ec_)))
return fail(cs.begin());

if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
num_buf_.append( begin, cs.used(begin) );
return suspend(cs.begin(), state::exp3, num);
}
Expand All @@ -2520,7 +2610,7 @@ parse_number(const char* p,
return fail(cs.begin(), error::exponent_overflow, &loc);
}
++cs;
if( !no_parsing )
BOOST_IF_CONSTEXPR( !no_parsing )
num.exp = 10 * num.exp + ( c - '0' );
continue;
}
Expand Down Expand Up @@ -2573,7 +2663,7 @@ parse_number(const char* p,
double d;
std::size_t const size = cs.used(begin);
BOOST_ASSERT( !num_buf_.size() || precise_parsing );
if( precise_parsing )
BOOST_IF_CONSTEXPR( precise_parsing )
{
char const* data = begin;
// if we previously suspended or if the current input ends with the
Expand All @@ -2587,7 +2677,7 @@ parse_number(const char* p,
}
d = std::strtod( data, nullptr );
}
else if ( no_parsing )
else BOOST_IF_CONSTEXPR( no_parsing )
d = 0;
else
d = detail::dec_to_float(
Expand Down

0 comments on commit abafb5b

Please sign in to comment.