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 Jun 22, 2023
1 parent 1803bd9 commit bf756d5
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 32 deletions.
8 changes: 6 additions & 2 deletions include/boost/json/basic_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ class basic_parser
bool neg;
};

template< char C >
struct parse_number_helper;

// optimization: must come first
Handler h_;

Expand Down Expand Up @@ -440,10 +443,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
114 changes: 84 additions & 30 deletions include/boost/json/basic_parser_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,30 @@ enum json_literal

//----------------------------------------------------------

template< class Handler >
template< char C >
struct basic_parser<Handler>::
parse_number_helper
{
basic_parser* parser;
char const* p;

template< std::size_t N >
char const*
operator()( mp11::mp_size_t<N> ) const
{
return parser->parse_number(
p,
std::true_type(),
std::integral_constant<char, C>(),
std::integral_constant<
number_parse_mode_t,
static_cast<number_parse_mode_t>(N)>() );
}
};

//----------------------------------------------------------

template<class Handler>
void
basic_parser<Handler>::
Expand Down Expand Up @@ -616,13 +640,19 @@ parse_value(const char* p,
switch(*p)
{
case '0':
return parse_number(p, std::true_type(), std::integral_constant<char, '0'>());
return mp11::mp_with_index<3>(
static_cast<unsigned char>(opt_.number_parse_mode),
parse_number_helper<'0'>{ this, p });
case '-':
return parse_number(p, std::true_type(), std::integral_constant<char, '-'>());
return mp11::mp_with_index<3>(
static_cast<unsigned char>(opt_.number_parse_mode),
parse_number_helper<'-'>{ this, p });
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, '+'>());
return mp11::mp_with_index<3>(
static_cast<unsigned char>(opt_.number_parse_mode),
parse_number_helper<'+'>{ this, p });
case 'n':
return parse_literal( p, mp11::mp_int<detail::null_literal>() );
case 't':
Expand Down Expand Up @@ -735,7 +765,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 @@ -1970,24 +2022,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 @@ -2037,8 +2089,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 @@ -2066,7 +2120,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 @@ -2093,7 +2147,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 @@ -2190,7 +2244,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 @@ -2215,7 +2269,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 @@ -2230,7 +2284,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 @@ -2250,7 +2304,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 @@ -2265,7 +2319,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 @@ -2293,7 +2347,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 @@ -2339,7 +2393,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 @@ -2378,7 +2432,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 @@ -2416,7 +2470,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 @@ -2456,7 +2510,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 @@ -2494,7 +2548,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 @@ -2539,7 +2593,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 @@ -2570,7 +2624,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 @@ -2609,7 +2663,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 @@ -2630,7 +2684,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 @@ -2683,7 +2737,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;
std::size_t full_size = size;
Expand All @@ -2701,7 +2755,7 @@ parse_number(const char* p,
BOOST_ASSERT( err.ptr == data + full_size );
(void)err;
}
else if ( no_parsing )
else BOOST_IF_CONSTEXPR( no_parsing )
d = 0;
else
d = detail::dec_to_float(
Expand Down

0 comments on commit bf756d5

Please sign in to comment.