283 if( !pc.hasNext() ) {
287 const PResult pc2 = pc.toConversion();
288 if( !pc2.hasNext() ) {
295 const PResult pc3 = pc2.nextSymbol();
298 const PResult pc4 = parseFlags(PResult(pc3, pstate_t::field_width));
301 bool next_arg = false;
302 const PResult pc5 = parseFieldWidth(pc4, next_arg);
303 if( next_arg || pc5.error() ) {
314 static constexpr const PResult parseP2(
const PResult pc)
noexcept {
318 if( pc2.sym() ==
'.' ) {
319 const PResult pc3 = PResult(pc2, pc2.length_mod,
true);
320 bool next_arg =
false;
321 const PResult pc4 = parsePrecision(pc3, next_arg);
322 if( next_arg || pc4.error() ) {
334 static constexpr const PResult parseP3(
const PResult pc)
noexcept {
335 const PResult pc2 = parseLengthMods(pc);
340 const PResult pc3 = parseFmtSpec(pc2);
347 if( !pc4.hasNext() ) {
353 static constexpr const PResult parseFlags(
const PResult pc)
noexcept {
364 return parseFlags(pc.nextSymbol());
370 static constexpr const PResult parseDigit(
const PResult pc)
noexcept {
371 if( !pc.hasNext() || !
isDigit(pc.sym()) ) {
return pc; }
372 return parseDigit( pc.nextSymbol() );
376 static constexpr const PResult parseFieldWidth(
const PResult pc,
bool& next_arg)
noexcept {
378 if( pc.sym() ==
'*' ) {
379 if( !pc.hasNext() ) {
return pc; }
380 const PResult pc2 = pc.nextSymbol();
382 using U = std::remove_cv_t<T>;
384 if constexpr( std::is_same_v<no_type_t, T> ) {
385 return pc2.setError(__LINE__);
387 const PResult pc3 = PResult(pc2, pc.arg_count+1);
388 if constexpr( !std::is_same_v<int, U> ) {
389 return pc3.setError(__LINE__);
395 return parseDigit(pc);
400 static constexpr const PResult parsePrecision(
const PResult pc,
bool &next_arg)
noexcept {
402 if( !pc.hasNext() ) {
return pc; }
403 const PResult pc2 = pc.nextSymbol();
404 const char c = pc.fmt[pc.pos];
406 if( !pc2.hasNext() ) {
return pc2; }
407 const PResult pc3 = pc2.nextSymbol();
409 using U = std::remove_cv_t<T>;
411 if constexpr( std::is_same_v<no_type_t, T> ) {
412 return pc3.setError(__LINE__);
414 const PResult pc4 = PResult(pc3, pc.arg_count+1);
415 if constexpr( !std::is_same_v<int, U> ) {
416 return pc4.setError(__LINE__);
422 return parseDigit(pc2);
426 static constexpr const PResult parseLengthMods(
const PResult pc)
noexcept {
427 const char sym = pc.sym();
429 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
430 const PResult pc2 = pc.nextSymbol();
431 if(
'h' == pc2.sym() ) {
432 if( !pc2.hasNext() ) {
return pc2.setError(__LINE__); }
433 return PResult(pc2.nextSymbol(),
plength_t::hh, pc2.precision_set);
437 }
else if(
'l' == sym ) {
438 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
439 const PResult pc2 = pc.nextSymbol();
440 if(
'l' == pc2.sym() ) {
441 if( !pc2.hasNext() ) {
return pc2.setError(__LINE__); }
442 return PResult(pc2.nextSymbol(),
plength_t::ll, pc2.precision_set);
446 }
else if(
'j' == sym ) {
447 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
448 return PResult(pc.nextSymbol(),
plength_t::j, pc.precision_set);
449 }
else if(
'z' == sym ) {
450 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
451 return PResult(pc.nextSymbol(),
plength_t::z, pc.precision_set);
452 }
else if(
't' == sym ) {
453 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
454 return PResult(pc.nextSymbol(),
plength_t::t, pc.precision_set);
455 }
else if(
'L' == sym ) {
456 if( !pc.hasNext() ) {
return pc.setError(__LINE__); }
457 return PResult(pc.nextSymbol(),
plength_t::L, pc.precision_set);
463 static constexpr const PResult parseFmtSpec(
const PResult pc)
noexcept {
464 const char fmt_literal = unaliasFmtSpec( pc.sym() );
466 switch( fmt_literal ) {
470 return parseStringFmtSpec(pc, fmt_literal);
472 return parseAPointerFmtSpec(pc);
474 return parseSignedFmtSpec(pc);
479 return parseUnsignedFmtSpec(pc, fmt_literal);
487 return parseFloatFmtSpec(pc, fmt_literal);
489 return pc.setError(__LINE__);
493 static constexpr char unaliasFmtSpec(
const char fmt_literal)
noexcept {
494 switch( fmt_literal ) {
495 case 'i':
return 'd';
496 case 'F':
return 'f';
497 default:
return fmt_literal;
501 static constexpr const PResult parseStringFmtSpec(
const PResult pc,
const char fmt_literal)
noexcept {
502 if constexpr( std::is_same_v<no_type_t, T> ) {
503 return pc.setError(__LINE__);
505 switch( fmt_literal ) {
509 const PResult pc2 = PResult(pc, pc.pos, pc.arg_count+1);
510 using U = std::remove_cv_t<T>;
511 switch( pc2.length_mod ) {
513 if constexpr( !std::is_same_v<char, U> ||
514 !std::is_same_v<int, U> ) {
515 return pc2.setError(__LINE__);
519 if constexpr( !std::is_same_v<wchar_t, U> ||
520 !std::is_same_v<wint_t, U> ) {
521 return pc2.setError(__LINE__);
525 return pc2.setError(__LINE__);
530 const PResult pc2 = PResult(pc, pc.pos, pc.arg_count+1);
531 switch( pc2.length_mod ) {
533 if constexpr( !std::is_pointer_v<T> ||
534 !std::is_same_v<char, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
535 return pc2.setError(__LINE__);
539 if constexpr( !std::is_pointer_v<T> ||
540 !std::is_same_v<wchar_t, std::remove_cv_t<std::remove_pointer_t<T>>> ) {
541 return pc2.setError(__LINE__);
545 return pc2.setError(__LINE__);
549 default:
return pc.setError(__LINE__);
554 static constexpr const PResult parseAPointerFmtSpec(
const PResult pc)
noexcept {
556 if constexpr( std::is_same_v<no_type_t, T> ) {
557 return pc2.setError(__LINE__);
559 const PResult pc3 = PResult(pc2, pc2.pos, pc2.arg_count+1);
560 if constexpr( !std::is_pointer_v<T> ) {
561 return pc3.setError(__LINE__);
566 static constexpr const PResult parseSignedFmtSpec(
const PResult pc)
noexcept {
567 if constexpr( std::is_same_v<no_type_t, T> ) {
568 return pc.setError(__LINE__);
570 const PResult pc2 = PResult(pc, pc.pos, pc.arg_count+1);
572 using U = std::remove_cv_t<T>;
574 using V =
typename std::conditional_t<std::is_integral_v<U> && std::is_unsigned_v<U>, std::make_signed<U>, std::type_identity<U>>::type;
576 switch( pc2.length_mod ) {
578 if constexpr( !std::is_same_v<char, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(char)) ) {
579 return pc2.setError(__LINE__);
583 if constexpr( !std::is_same_v<short, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(short)) ) {
584 return pc2.setError(__LINE__);
588 if constexpr( !std::is_same_v<int, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(int)) ) {
589 return pc2.setError(__LINE__);
593 if constexpr( !std::is_same_v<long, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(long)) ) {
594 return pc2.setError(__LINE__);
598 if constexpr( !std::is_same_v<long long, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
long long)) ) {
599 return pc2.setError(__LINE__);
603 if constexpr( !std::is_same_v<intmax_t, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(intmax_t)) ) {
604 return pc2.setError(__LINE__);
608 if constexpr( !std::is_same_v<ssize_t, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(ssize_t)) ) {
609 return pc2.setError(__LINE__);
613 if constexpr( !std::is_same_v<ptrdiff_t, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(ptrdiff_t)) ) {
614 return pc2.setError(__LINE__);
618 return pc2.setError(__LINE__);
623 static constexpr const PResult parseUnsignedFmtSpec(
const PResult pc,
const char )
noexcept {
624 if constexpr( std::is_same_v<no_type_t, T> ) {
625 return pc.setError(__LINE__);
627 const PResult pc2 = PResult(pc, pc.pos, pc.arg_count+1);
629 using U = std::remove_cv_t<T>;
631 using V =
typename std::conditional_t<std::is_integral_v<U> && std::is_signed_v<U>, std::make_unsigned<U>, std::type_identity<U>>::type;
633 switch( pc2.length_mod ) {
635 if constexpr( !std::is_same_v<unsigned char, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
unsigned char)) ) {
636 return pc2.setError(__LINE__);
640 if constexpr( !std::is_same_v<unsigned short, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
unsigned short)) ) {
641 return pc2.setError(__LINE__);
645 if constexpr( !std::is_same_v<unsigned int, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
unsigned int)) ) {
646 return pc2.setError(__LINE__);
650 if constexpr( !std::is_same_v<unsigned long, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
unsigned long)) ) {
651 return pc2.setError(__LINE__);
655 if constexpr( !std::is_same_v<unsigned long long, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(
unsigned long long)) ) {
656 return pc2.setError(__LINE__);
660 if constexpr( !std::is_same_v<uintmax_t, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(uintmax_t)) ) {
661 return pc2.setError(__LINE__);
665 if constexpr( !std::is_same_v<size_t, V> && (!std::is_integral_v<V> ||
sizeof(V) >
sizeof(size_t)) ) {
666 return pc2.setError(__LINE__);
671 if constexpr( !std::is_same_v<unsigned ptrdiff_t, U> ) {
672 return pc2.setError(__LINE__);
677 return pc2.setError(__LINE__);
682 static constexpr const PResult parseFloatFmtSpec(
const PResult pc,
const char )
noexcept {
683 if constexpr( std::is_same_v<no_type_t, T> ) {
684 return pc.setError(__LINE__);
686 const PResult pc2 = PResult(pc, pc.pos, pc.arg_count+1);
688 using U = std::remove_cv_t<T>;
690 switch( pc2.length_mod ) {
693 if constexpr( !std::is_same_v<float, U> &&
694 !std::is_same_v<double, U> ) {
695 return pc2.setError(__LINE__);
699 if constexpr( !std::is_same_v<float, U> &&
700 !std::is_same_v<double, U> &&
701 !std::is_same_v<long double, U> ) {
703 return pc2.setError(__LINE__);
707 return pc2.setError(__LINE__);