267 template <typename T>
269 if( !pc.hasNext() ) {
273 if( !pc.toConversion() ) {
280 if( !pc.nextSymbol(c) ) {
281 pc.setError(__LINE__);
286 pc.state = pstate_t::field_width;
290 if( !parseFieldWidth<T>(pc, c) ) {
297 pc.state = pstate_t::precision;
299 if( !parsePrecision<T>(pc, c) ) {
304 if( !parseLengthMods(pc, c) ) {
308 if( !parseFmtSpec<T>(pc, c) ) {
314 if( !pc.nextSymbol(c) ) {
322 constexpr void parseFlags(
PResult &pc,
char &c)
const noexcept {
333 }
while( pc.nextSymbol(c) );
337 template <
typename T>
338 constexpr bool parseFieldWidth(
PResult &pc,
char &c)
const noexcept {
340 if( !pc.nextSymbol(c) ) {
return false; }
342 using U = std::remove_cv_t<T>;
344 if constexpr( std::is_same_v<no_type_t, T> ) {
345 pc.setError(__LINE__);
349 if constexpr( !std::is_same_v<int, U> ) {
350 pc.setError(__LINE__);
355 if( !pc.nextSymbol(c) ) {
return false; }
357 if( !pc.nextSymbol(c) ) {
return false; }
364 template <
typename T>
365 constexpr bool parsePrecision(
PResult &pc,
char &c)
const noexcept {
366 pc.precision_set =
true;
367 if( !pc.nextSymbol(c) ) {
return false; }
369 if( !pc.nextSymbol(c) ) {
return false; }
371 using U = std::remove_cv_t<T>;
373 if constexpr( std::is_same_v<no_type_t, T> ) {
374 pc.setError(__LINE__);
378 if constexpr( !std::is_same_v<int, U> ) {
379 pc.setError(__LINE__);
384 if( !pc.nextSymbol(c) ) {
return false; }
386 if( !pc.nextSymbol(c) ) {
return false; }
393 constexpr bool parseLengthMods(
PResult &pc,
char &c)
const noexcept {
395 if( !pc.nextSymbol(c) ) {
return false; }
397 if( !pc.nextSymbol(c) ) {
return false; }
402 }
else if(
'l' == c ) {
403 if( !pc.nextSymbol(c) ) {
return false; }
405 if( !pc.nextSymbol(c) ) {
return false; }
410 }
else if(
'j' == c ) {
411 if( !pc.nextSymbol(c) ) {
return false; }
413 }
else if(
'z' == c ) {
414 if( !pc.nextSymbol(c) ) {
return false; }
416 }
else if(
't' == c ) {
417 if( !pc.nextSymbol(c) ) {
return false; }
419 }
else if(
'L' == c ) {
420 if( !pc.nextSymbol(c) ) {
return false; }
428 template <
typename T>
429 constexpr bool parseFmtSpec(
PResult &pc,
char fmt_literal)
const noexcept {
430 fmt_literal = unaliasFmtSpec(fmt_literal);
432 switch( fmt_literal ) {
436 return parseStringFmtSpec<T>(pc, fmt_literal);
438 return parseAPointerFmtSpec<T>(pc);
440 return parseSignedFmtSpec<T>(pc);
445 return parseUnsignedFmtSpec<T>(pc, fmt_literal);
453 return parseFloatFmtSpec<T>(pc, fmt_literal);
455 pc.setError(__LINE__);
460 constexpr char unaliasFmtSpec(
const char fmt_literal)
const noexcept {
461 switch( fmt_literal ) {
462 case 'i':
return 'd';
463 case 'F':
return 'f';
464 default:
return fmt_literal;
468 template <
typename T>
469 constexpr bool parseStringFmtSpec(
PResult &pc,
const char fmt_literal)
const noexcept {
470 if constexpr( std::is_same_v<no_type_t, T> ) {
471 pc.setError(__LINE__);
474 switch( fmt_literal ) {
479 using U = std::remove_cv_t<T>;
480 switch( pc.length_mod ) {
482 if constexpr( !std::is_same_v<char, U> ||
483 !std::is_same_v<int, U> ) {
484 pc.setError(__LINE__);
489 if constexpr( !std::is_same_v<wchar_t, U> ||
490 !std::is_same_v<wint_t, U> ) {
491 pc.setError(__LINE__);
496 pc.setError(__LINE__);
503 switch( pc.length_mod ) {
505 if constexpr( !std::is_pointer_v<T> ||
506 !std::is_same_v<char, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
507 pc.setError(__LINE__);
512 if constexpr( !std::is_pointer_v<T> ||
513 !std::is_same_v<wchar_t, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
514 pc.setError(__LINE__);
520 pc.setError(__LINE__);
525 pc.setError(__LINE__);
531 template <
typename T>
532 constexpr bool parseAPointerFmtSpec(
PResult &pc)
const noexcept {
534 if constexpr( std::is_same_v<no_type_t, T> ) {
535 pc.setError(__LINE__);
539 if constexpr( !std::is_pointer_v<T> ) {
540 pc.setError(__LINE__);
546 template <
typename S>
547 constexpr bool parseSignedFmtSpec(
PResult &pc)
const noexcept {
548 if constexpr( std::is_same_v<no_type_t, S> ) {
549 pc.setError(__LINE__);
554 using T = std::remove_cv_t<S>;
556 using U =
typename std::conditional_t<std::is_integral_v<T> && std::is_unsigned_v<T>, std::make_signed<T>, std::type_identity<T>>::type;
558 switch( pc.length_mod ) {
560 if constexpr( !std::is_same_v<char, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(char)) ) {
561 pc.setError(__LINE__);
566 if constexpr( !std::is_same_v<short, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(short)) ) {
567 pc.setError(__LINE__);
572 if constexpr( !std::is_same_v<int, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(int)) ) {
573 pc.setError(__LINE__);
578 if constexpr( !std::is_same_v<long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(long)) ) {
579 pc.setError(__LINE__);
584 if constexpr( !std::is_same_v<long long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
long long)) ) {
585 pc.setError(__LINE__);
590 if constexpr( !std::is_same_v<intmax_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(intmax_t)) ) {
591 pc.setError(__LINE__);
596 if constexpr( !std::is_same_v<ssize_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(ssize_t)) ) {
597 pc.setError(__LINE__);
602 if constexpr( !std::is_same_v<ptrdiff_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(ptrdiff_t)) ) {
603 pc.setError(__LINE__);
608 pc.setError(__LINE__);
614 template <
typename S>
615 constexpr bool parseUnsignedFmtSpec(
PResult &pc,
const char )
const noexcept {
616 if constexpr( std::is_same_v<no_type_t, S> ) {
617 pc.setError(__LINE__);
622 using T = std::remove_cv_t<S>;
624 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;
626 switch( pc.length_mod ) {
628 if constexpr( !std::is_same_v<unsigned char, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned char)) ) {
629 pc.setError(__LINE__);
634 if constexpr( !std::is_same_v<unsigned short, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned short)) ) {
635 pc.setError(__LINE__);
640 if constexpr( !std::is_same_v<unsigned int, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned int)) ) {
641 pc.setError(__LINE__);
646 if constexpr( !std::is_same_v<unsigned long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned long)) ) {
647 pc.setError(__LINE__);
652 if constexpr( !std::is_same_v<unsigned long long, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(
unsigned long long)) ) {
653 pc.setError(__LINE__);
658 if constexpr( !std::is_same_v<uintmax_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(uintmax_t)) ) {
659 pc.setError(__LINE__);
664 if constexpr( !std::is_same_v<size_t, U> && (!std::is_integral_v<U> ||
sizeof(U) >
sizeof(size_t)) ) {
665 pc.setError(__LINE__);
671 if constexpr( !std::is_same_v<unsigned ptrdiff_t, U> ) {
678 pc.setError(__LINE__);
684 template <
typename T>
685 constexpr bool parseFloatFmtSpec(
PResult &pc,
const char )
const noexcept {
686 if constexpr( std::is_same_v<no_type_t, T> ) {
687 pc.setError(__LINE__);
692 using U = std::remove_cv_t<T>;
694 switch( pc.length_mod ) {
697 if constexpr( !std::is_same_v<float, U> &&
698 !std::is_same_v<double, U> ) {
699 pc.setError(__LINE__);
704 if constexpr( !std::is_same_v<float, U> &&
705 !std::is_same_v<double, U> &&
706 !std::is_same_v<long double, U> ) {
708 pc.setError(__LINE__);
713 pc.setError(__LINE__);