43 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
61 #if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__)
70 size_t parse_unsigned_integer_gcc_intrinsic_( utils::InputStream& source )
83 auto buffer_pair = source.buffer();
84 auto buffer = buffer_pair.first;
86 size_t data_end = buffer_pair.second;
89 std::uint64_t chunk = 0;
90 std::memcpy( &chunk, &buffer[ data_pos ],
sizeof( chunk ));
96 auto const zero =
static_cast<uint64_t
>(0);
97 #define hasless(x,n) (((x)-~zero/255*(n))&~(x)&~zero/255*128)
98 #define hasmore(x,n) ((((x)+~zero/255*(127-(n)))|(x))&~zero/255*128)
101 auto const l = hasless( chunk,
'0' );
102 auto const m = hasmore( chunk,
'9' );
103 auto const p = l | m;
125 if(
sizeof(
int) ==
sizeof(std::uint64_t) ) {
126 idx = __builtin_ffs(p) / 8;
127 }
else if(
sizeof(
long) ==
sizeof(std::uint64_t) ) {
128 idx = __builtin_ffsl(p) / 8;
129 }
else if(
sizeof(
long long) ==
sizeof(std::uint64_t) ) {
130 idx = __builtin_ffsll(p) / 8;
133 (
sizeof(
int) ==
sizeof(std::uint64_t) ) ||
134 (
sizeof(
long) ==
sizeof(std::uint64_t) ) ||
135 (
sizeof(
long long) ==
sizeof(std::uint64_t) ),
136 "No compilter intrinsic __builtin_ffs[l][l] for std::uint64_t"
138 throw std::runtime_error(
139 "No compilter intrinsic __builtin_ffs[l][l] for std::uint64_t"
142 assert( 0 <= idx && idx <= 8 );
151 chunk <<= (8 * ( 8 - idx + 1 ));
158 std::uint64_t lower_digits = (chunk & 0x0f000f000f000f00) >> 8;
159 std::uint64_t upper_digits = (chunk & 0x000f000f000f000f) * 10;
160 chunk = lower_digits + upper_digits;
163 lower_digits = (chunk & 0x00ff000000ff0000) >> 16;
164 upper_digits = (chunk & 0x000000ff000000ff) * 100;
165 chunk = lower_digits + upper_digits;
168 lower_digits = (chunk & 0x0000ffff00000000) >> 32;
169 upper_digits = (chunk & 0x000000000000ffff) * 10000;
170 chunk = lower_digits + upper_digits;
184 if( idx == 0 || data_pos + 8 >= data_end ) {
188 throw std::runtime_error(
189 "Expecting integer in " + source.source_name() +
" at " + source.at() +
"."
195 source.jump_unchecked( data_pos );
199 #endif // defined(__GNUC__) || defined(__GNUG__) || defined(__clang__)
244 size_t parse_unsigned_integer_from_chars_( utils::InputStream& source )
251 auto buffer_pair = source.buffer();
252 auto buffer = buffer_pair.first;
254 size_t data_end = buffer_pair.second;
258 using namespace utils;
262 auto raise_and_add_ = []( T& val,
unsigned char c ) {
264 __builtin_mul_overflow( val, 10, &val ) ||
265 __builtin_add_overflow( val, c, &val )
276 auto from_chars_digit_ = [&](
char const*& first,
char const* last, T& val ) {
277 while( first != last ) {
278 char const c = *first;
280 if( !raise_and_add_(val, c -
'0') ) {
291 char const* start = &buffer[ data_pos ];
292 char const* end = &buffer[ data_end ];
293 auto const valid = from_chars_digit_( start, end, x );
294 auto const dist = start - &buffer[ data_pos ];
297 throw std::runtime_error(
298 "Expecting integer in " + source_name() +
" at " + at() +
"."
300 }
else if( !valid ) {
301 throw std::overflow_error(
302 "Numerical overflow in " + source_name() +
" at " + at() +
"."
304 }
else if( std::is_signed<T>::value ) {
316 source.jump_unchecked( data_pos );
320 #endif // ( defined(__GNUC__) || defined(__GNUG__) ) && ( !defined(__clang__) || ( __clang_major__ >= 8 ))
327 #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
333 size_t parse_unsigned_integer_std_from_chars_( utils::InputStream& source )
339 auto buffer_pair = source.buffer();
340 auto buffer = buffer_pair.first;
342 size_t data_end = buffer_pair.second;
346 using namespace utils;
353 auto const conv = std::from_chars( &buffer[ data_pos ], &buffer[ data_end ], x );
356 auto const dist = conv.ptr - &buffer[ data_pos ];
362 throw std::runtime_error(
363 "Expecting integer in " + source.source_name() +
" at " + source.at() +
"."
367 if( conv.ec != std::errc() ) {
368 if( conv.ec == std::errc::result_out_of_range ) {
369 throw std::overflow_error(
370 "Numerical overflow in " + source.source_name() +
" at " + source.at() +
"."
372 }
else if( conv.ec == std::errc::invalid_argument ) {
381 throw std::overflow_error(
382 "Integer parsing error in " + source.source_name() +
" at " + source.at() +
"."
388 source.jump_unchecked( data_pos );
392 #endif // ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
404 auto buffer_pair = source.
buffer();
405 auto buffer = buffer_pair.first;
407 size_t data_end = buffer_pair.second;
411 using namespace utils;
414 if( data_pos >= data_end || !
utils::is_digit( buffer[ data_pos ] ) ) {
415 throw std::runtime_error(
416 "Expecting digit in " + source.
source_name() +
" at " + source.
at() +
"."
420 while(( data_pos < data_end ) &&
utils::is_digit( buffer[ data_pos ] )) {
421 T y = buffer[ data_pos ] -
'0';
423 if( x > ( std::numeric_limits<T>::max() - y ) / 10 ) {
424 throw std::overflow_error(
425 "Numerical overflow in " + source.
source_name() +
" at " + source.
at() +
"."
439 assert( data_pos < data_end );
440 assert( buffer[ data_pos ] !=
'\n' );
456 #if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__)
459 return parse_unsigned_integer_gcc_intrinsic_( source );
486 bool found_digits =
false;
489 if( source && ( *source ==
'+' || *source ==
'-' )) {
502 if( source && *source ==
'.' ) {
516 if( ! found_digits ) {
529 if( source && ( *source ==
'+' || *source ==
'-' )) {
550 bool use_twin_quotes,
554 std::string value =
"";
562 char qmark = *source;
566 if( include_qmarks ) {
570 bool found_closing_qmark =
false;
574 if( *source == qmark ) {
578 if( ! use_twin_quotes ) {
579 found_closing_qmark =
true;
585 if( source && *source == qmark ) {
588 found_closing_qmark =
true;
593 }
else if( *source ==
'\\' && use_escapes ) {
600 throw std::runtime_error(
601 "Unexpected end of " + source.
source_name() +
" at " + source.
at()
602 +
". Expecting escape sequence."
622 if( ! found_closing_qmark ) {
624 throw std::runtime_error(
625 "Unexpected end of " + source.
source_name() +
" at " + source.
at()
626 +
". Expected closing quotation mark."
631 if( include_qmarks ) {