266 template <typename T>
268 if( !pc.hasNext() ) {
272 if( !pc.toConversion() ) {
279 if( !pc.nextSymbol(c) ) {
280 pc.setError(__LINE__);
285 pc.state = pstate_t::field_width;
289 if( !parseFieldWidth<T>(pc, c) ) {
296 pc.state = pstate_t::precision;
298 if( !parsePrecision<T>(pc, c) ) {
303 if( !parseLengthMods(pc, c) ) {
307 if( !parseFmtSpec<T>(pc, c) ) {
313 if( !pc.nextSymbol(c) ) {
321 constexpr void parseFlags(
PResult &pc,
char &c)
const noexcept {
332 }
while( pc.nextSymbol(c) );
336 template <
typename T>
337 constexpr bool parseFieldWidth(
PResult &pc,
char &c)
const noexcept {
339 if( !pc.nextSymbol(c) ) {
return false; }
341 using U = std::remove_cv_t<T>;
343 if constexpr( std::is_same_v<no_type_t, T> ) {
344 pc.setError(__LINE__);
348 if constexpr( !std::is_same_v<int, U> ) {
349 pc.setError(__LINE__);
354 if( !pc.nextSymbol(c) ) {
return false; }
356 if( !pc.nextSymbol(c) ) {
return false; }
363 template <
typename T>
364 constexpr bool parsePrecision(
PResult &pc,
char &c)
const noexcept {
365 pc.precision_set =
true;
366 if( !pc.nextSymbol(c) ) {
return false; }
368 if( !pc.nextSymbol(c) ) {
return false; }
370 using U = std::remove_cv_t<T>;
372 if constexpr( std::is_same_v<no_type_t, T> ) {
373 pc.setError(__LINE__);
377 if constexpr( !std::is_same_v<int, U> ) {
378 pc.setError(__LINE__);
383 if( !pc.nextSymbol(c) ) {
return false; }
385 if( !pc.nextSymbol(c) ) {
return false; }
392 constexpr bool parseLengthMods(
PResult &pc,
char &c)
const noexcept {
394 if( !pc.nextSymbol(c) ) {
return false; }
396 if( !pc.nextSymbol(c) ) {
return false; }
401 }
else if(
'l' == c ) {
402 if( !pc.nextSymbol(c) ) {
return false; }
404 if( !pc.nextSymbol(c) ) {
return false; }
409 }
else if(
'j' == c ) {
410 if( !pc.nextSymbol(c) ) {
return false; }
412 }
else if(
'z' == c ) {
413 if( !pc.nextSymbol(c) ) {
return false; }
415 }
else if(
't' == c ) {
416 if( !pc.nextSymbol(c) ) {
return false; }
418 }
else if(
'L' == c ) {
419 if( !pc.nextSymbol(c) ) {
return false; }
427 template <
typename T>
428 constexpr bool parseFmtSpec(
PResult &pc,
char fmt_literal)
const noexcept {
429 fmt_literal = unaliasFmtSpec(fmt_literal);
431 switch( fmt_literal ) {
435 return parseStringFmtSpec<T>(pc, fmt_literal);
437 return parseAPointerFmtSpec<T>(pc);
439 return parseSignedFmtSpec<T>(pc);
444 return parseUnsignedFmtSpec<T>(pc, fmt_literal);
452 return parseFloatFmtSpec<T>(pc, fmt_literal);
454 pc.setError(__LINE__);
459 constexpr char unaliasFmtSpec(
const char fmt_literal)
const noexcept {
460 switch( fmt_literal ) {
461 case 'i':
return 'd';
462 case 'F':
return 'f';
463 default:
return fmt_literal;
467 template <
typename T>
468 constexpr bool parseStringFmtSpec(
PResult &pc,
const char fmt_literal)
const noexcept {
469 if constexpr( std::is_same_v<no_type_t, T> ) {
470 pc.setError(__LINE__);
473 switch( fmt_literal ) {
478 using U = std::remove_cv_t<T>;
479 switch( pc.length_mod ) {
481 if constexpr( !std::is_same_v<char, U> ||
482 !std::is_same_v<int, U> ) {
483 pc.setError(__LINE__);
488 if constexpr( !std::is_same_v<wchar_t, U> ||
489 !std::is_same_v<wint_t, U> ) {
490 pc.setError(__LINE__);
495 pc.setError(__LINE__);
502 switch( pc.length_mod ) {
504 if constexpr( !std::is_pointer_v<T> ||
505 !std::is_same_v<char, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
506 pc.setError(__LINE__);
511 if constexpr( !std::is_pointer_v<T> ||
512 !std::is_same_v<wchar_t, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
513 pc.setError(__LINE__);
519 pc.setError(__LINE__);
524 pc.setError(__LINE__);
530 template <
typename T>
531 constexpr bool parseAPointerFmtSpec(
PResult &pc)
const noexcept {
533 if constexpr( std::is_same_v<no_type_t, T> ) {
534 pc.setError(__LINE__);
538 if constexpr( !std::is_pointer_v<T> ) {
539 pc.setError(__LINE__);
545 template <
typename S>
546 constexpr bool parseSignedFmtSpec(
PResult &pc)
const noexcept {
547 if constexpr( std::is_same_v<no_type_t, S> ) {
548 pc.setError(__LINE__);
553 using T = std::remove_cv_t<S>;
555 using U =
typename std::conditional_t<!std::is_same_v<bool, T> && std::is_integral_v<T> && std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>::type;
557 switch( pc.length_mod ) {
559 if constexpr( !std::is_same_v<char, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(char)) ) {
560 pc.setError(__LINE__);
565 if constexpr( !std::is_same_v<short, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(short)) ) {
566 pc.setError(__LINE__);
571 if constexpr( !std::is_same_v<int, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(int)) ) {
572 pc.setError(__LINE__);
577 if constexpr( !std::is_same_v<long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(long)) ) {
578 pc.setError(__LINE__);
583 if constexpr( !std::is_same_v<long long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
long long)) ) {
584 pc.setError(__LINE__);
589 if constexpr( !std::is_same_v<intmax_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(intmax_t)) ) {
590 pc.setError(__LINE__);
595 if constexpr( !std::is_same_v<ssize_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(ssize_t)) ) {
596 pc.setError(__LINE__);
601 if constexpr( !std::is_same_v<ptrdiff_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(ptrdiff_t)) ) {
602 pc.setError(__LINE__);
607 pc.setError(__LINE__);
613 template <
typename S>
614 constexpr bool parseUnsignedFmtSpec(
PResult &pc,
const char )
const noexcept {
615 if constexpr( std::is_same_v<no_type_t, S> ) {
616 pc.setError(__LINE__);
621 using T = std::remove_cv_t<S>;
623 using U =
typename std::conditional_t<std::is_integral_v<T> && std::is_signed_v<T>, std::make_unsigned<T>, std::type_identity<T>>::type;
625 switch( pc.length_mod ) {
627 if constexpr( !std::is_same_v<unsigned char, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned char)) ) {
628 pc.setError(__LINE__);
633 if constexpr( !std::is_same_v<unsigned short, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned short)) ) {
634 pc.setError(__LINE__);
639 if constexpr( !std::is_same_v<unsigned int, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned int)) ) {
640 pc.setError(__LINE__);
645 if constexpr( !std::is_same_v<unsigned long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned long)) ) {
646 pc.setError(__LINE__);
651 if constexpr( !std::is_same_v<unsigned long long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned long long)) ) {
652 pc.setError(__LINE__);
657 if constexpr( !std::is_same_v<uintmax_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(uintmax_t)) ) {
658 pc.setError(__LINE__);
663 if constexpr( !std::is_same_v<size_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(size_t)) ) {
664 pc.setError(__LINE__);
670 if constexpr( !std::is_same_v<unsigned ptrdiff_t, U> ) {
677 pc.setError(__LINE__);
683 template <
typename T>
684 constexpr bool parseFloatFmtSpec(
PResult &pc,
const char )
const noexcept {
685 if constexpr( std::is_same_v<no_type_t, T> ) {
686 pc.setError(__LINE__);
691 using U = std::remove_cv_t<T>;
693 switch( pc.length_mod ) {
696 if constexpr( !std::is_same_v<float, U> &&
697 !std::is_same_v<double, U> ) {
698 pc.setError(__LINE__);
703 if constexpr( !std::is_same_v<float, U> &&
704 !std::is_same_v<double, U> &&
705 !std::is_same_v<long double, U> ) {
707 pc.setError(__LINE__);
712 pc.setError(__LINE__);