240 default:
return "error";
325 default:
return false;
356 switch (fmt_literal) {
431 fmt = std::string_view();
455 std::string_view m_fmt;
464 : m_fmt(
f), m_pos(
pos), m_arg_count(acount), m_line(line), m_opts(o), m_success(ok) {}
467 constexpr bool success() const noexcept {
return m_success; }
473 constexpr const std::string_view&
fmt() const noexcept {
return m_fmt; }
478 constexpr size_t pos() const noexcept {
return m_pos; }
480 constexpr int errorLine() const noexcept {
return m_line; }
491 inline constexpr const size_t char32buf_maxlen = 32;
492 inline constexpr const uint32_t default_float_precision = 6;
493 inline constexpr const double_t max_append_float = (double_t)1e9;
495 void append_rev(std::string &dest,
const size_t dest_maxlen, std::string_view src,
bool prec_cut,
bool reverse,
const FormatOpts &opts);
496 inline void append_string(std::string &dest,
const size_t dest_maxlen, std::string_view src,
const FormatOpts &opts) {
497 append_rev(dest, dest_maxlen, src,
true ,
false , opts);
499 void append_integral(std::string &dest,
const size_t dest_maxlen, uint64_t v,
const bool negative,
const FormatOpts &opts,
const bool inject_dot=
false);
501 void append_integral_simple(std::string &dest,
const size_t dest_maxlen, uint64_t v,
const bool negative,
const FormatOpts &opts);
504 bool is_float_validF64(std::string &dest,
const size_t dest_maxlen,
const double value,
const FormatOpts &opts);
505 void append_floatF64(std::string &dest,
const size_t dest_maxlen,
const double value,
const FormatOpts &opts);
506 void append_efloatF64(std::string &dest,
const size_t dest_maxlen,
const double ivalue,
const FormatOpts &iopts);
507 void append_afloatF64(std::string &dest,
const size_t dest_maxlen,
const double ivalue,
const size_t ivalue_size,
const FormatOpts &iopts);
510 concept OutputType =
requires(T
t) {
511 {
t.maxLen() } -> std::same_as<size_t>;
514 {
t.get() } -> std::same_as<std::string_view>;
520 constexpr NullOutput() noexcept = default;
522 constexpr
size_t maxLen() const noexcept {
return 0; }
523 constexpr bool fits(
size_t)
const noexcept {
return false; }
525 std::string_view get() const noexcept {
return "(nil)"; }
528 requires jau::req::stringifyable0_jau<T> || jau::req::pointer<T>
529 constexpr void appendFormatted(
const FormatOpts&,
const T&)
noexcept { }
532 requires jau::req::unsigned_integral<T> && (!jau::req::boolean<T>)
533 constexpr void appendFormattedInt(
const FormatOpts&,
const T&,
bool)
noexcept { }
536 requires std::is_floating_point_v<T>
537 constexpr void appendFormattedFloat(
const FormatOpts&,
const T&,
nsize_t)
noexcept {}
539 constexpr void appendText(std::string_view )
noexcept { }
540 constexpr void appendError(
size_t,
int ,
const std::string_view )
noexcept {}
546 std::size_t m_maxLen;
550 constexpr StringOutput(std::size_t maxLen, std::string &s) noexcept
551 : m_maxLen(maxLen), m_s(s) {}
553 constexpr size_t maxLen() const noexcept {
return m_maxLen; }
554 constexpr bool fits(
size_t n)
const noexcept {
return m_s.size() + n <= m_maxLen; }
556 std::string_view get() const noexcept {
return m_s; }
562 void appendFormatted(
const FormatOpts& opts,
const T& v) {
563 impl::append_string(m_s, m_maxLen, v.toString(), opts);
567 void appendFormatted(
const FormatOpts& opts,
const T& v) {
568 impl::append_string(m_s, m_maxLen, v.to_string(), opts);
572 void appendFormatted(
const FormatOpts& opts,
const T& v) {
573 impl::append_string(m_s, m_maxLen,
to_string(v), opts);
576 requires jau::req::string_literal<T> || jau::req::string_class<T>
577 void appendFormatted(
const FormatOpts& opts,
const T& v) {
578 impl::append_string(m_s, m_maxLen, v, opts);
581 requires jau::req::char_pointer<T>
582 void appendFormatted(
const FormatOpts& opts,
const T& v) {
584 impl::append_string(m_s, m_maxLen, std::string_view(v), opts);
586 impl::append_string(m_s, m_maxLen,
"(null)", opts);
590 requires jau::req::pointer<T> && (!jau::req::string_alike<T>)
591 void appendFormatted(
const FormatOpts& opts,
const T& v) {
593 const uintptr_t v_le =
jau::cpu_to_le(
reinterpret_cast<uintptr_t
>(v));
594 if (!opts.width_set && !opts.precision_set) {
595 impl::append_integral_simple(m_s, m_maxLen, v_le,
false, opts);
597 impl::append_integral(m_s, m_maxLen, v_le,
false, opts);
600 impl::append_string(m_s, m_maxLen,
"(nil)", opts);
604 requires jau::req::unsigned_integral<T>
605 void appendFormattedInt(
const FormatOpts& opts,
const T& v,
bool negative) {
606 if (!opts.width_set && !opts.precision_set) {
607 impl::append_integral_simple(m_s, m_maxLen, uint64_t(v), negative, opts);
609 impl::append_integral(m_s, m_maxLen, uint64_t(v), negative, opts);
613 requires std::is_floating_point_v<T>
614 void appendFormattedFloat(
const FormatOpts& opts,
const T& v,
nsize_t floatSize) {
616 impl::append_floatF64(m_s, m_maxLen, v, opts);
618 impl::append_afloatF64(m_s, m_maxLen, v, floatSize, opts);
621 impl::append_efloatF64(m_s, m_maxLen, v, opts);
624 inline void appendText(
const std::string_view v) {
625 if (fits(v.size())) {
630 void appendError(
size_t argIdx,
int line,
const std::string_view tag);
633 template<OutputType Output>
638 template<OutputType Output>
641 std::string_view fmt;
651 unsigned int m_argtype_size;
652 bool m_argtype_signed:1;
653 bool m_argval_negative:1;
656 constexpr FResult(Output p, std::string_view fmt_) noexcept
657 : fmt(fmt_), pos(0), arg_count(0), line(0), opts(),
659 m_out(std::move(p)), pos_lstart(0),
661 m_argtype_signed(
false),
662 m_argval_negative(
false)
665 constexpr FResult(
const FResult &pre)
noexcept =
default;
666 constexpr FResult &operator=(
const FResult &x)
noexcept =
default;
668 constexpr operator Result() const noexcept {
672 constexpr bool hasNext() const noexcept {
673 return !error() && pos < fmt.length();
676 constexpr ssize_t argCount() const noexcept {
return arg_count; }
677 constexpr bool error() const noexcept {
return pstate_t::error == state; }
679 std::string toString()
const {
680 const char c = pos < fmt.length() ? fmt[pos] :
'@';
681 std::string s =
"args ";
682 s.append(std::to_string(arg_count))
686 .append(std::to_string(line))
688 .append(std::to_string(pos))
690 .append(std::string(1, c))
692 .append(opts.toString())
693 .append(
"`, type[signed ")
696 .append(std::to_string(m_argtype_size))
697 .append(
"], negative ")
708 friend class impl::Parser<Output>;
710 constexpr void reset() noexcept {
713 constexpr bool nextSymbol(
char &c)
noexcept {
714 if (pos < fmt.length()) {
721 constexpr bool toConversion() noexcept {
724 }
else if (fmt[pos] ==
'%') {
729 }
else if (pos < fmt.length()) {
731 const size_t q = fmt.find(
'%', pos + 1);
732 if (q == std::string::npos) {
734 appendText(fmt.substr(pos, fmt.length() - pos));
739 appendText(fmt.substr(pos, q - pos));
752 constexpr void setLastSpec(
size_t endpos)
noexcept {
753 if (endpos > pos_lstart) {
754 opts.fmt = fmt.substr(pos_lstart, endpos - pos_lstart);
758 constexpr void setError(
int l)
noexcept {
761 if (0 == arg_count) {
762 arg_count = std::numeric_limits<ssize_t>::min();
763 }
else if (0 < arg_count) {
769 requires (jau::req::stringifyable0_jau<T> || jau::req::pointer<T>)
770 constexpr void appendFormatted(
const T &v) {
771 m_out.appendFormatted(opts, v);
774 requires jau::req::unsigned_integral<T> && (!jau::req::boolean<T>)
775 constexpr void appendFormatted(
const T &v) {
776 m_out.appendFormattedInt(opts, v, m_argval_negative);
780 requires jau::req::boolean<T>
781 constexpr void appendFormatted(
const T &v) {
782 m_out.appendFormatted(opts, v ?
"true" :
"false");
786 requires std::floating_point<T>
787 constexpr void appendFormatted(
const T &v) {
788 m_out.appendFormattedFloat(opts, v, m_argtype_size);
791 constexpr void appendText(
const std::string_view v) {
795 constexpr void appendError(
const std::string_view tag) {
796 const ssize_t c = arg_count == std::numeric_limits<ssize_t>::min() ? 0 : arg_count;
797 m_out.appendError(
jau::abs(c), line, tag);
801 template <jau::req::
signed_
integral T>
802 constexpr std::make_unsigned_t<T>
unsigned_int(
const T x)
noexcept
808 requires (!jau::req::signed_integral<T>)
814 requires jau::req::signed_integral<T>
815 constexpr bool is_positive(
const T a)
noexcept {
820 requires std::floating_point<T>
821 constexpr bool is_positive(
const T a)
noexcept {
826 requires (!jau::req::signed_integral<T>) && (!std::floating_point<T>)
827 constexpr bool is_positive(
const T&)
noexcept {
833 using make_int_unsigned_t =
typename std::conditional_t<std::is_integral_v<T> || jau::req::boolean<T>, std::type_identity<uint64_t>, std::type_identity<T>>::type;
837 using make_int_signed_t =
typename std::conditional_t<jau::req::unsigned_integral<T> && !jau::req::boolean<T>, std::make_signed<T>, std::type_identity<T>>::type;
841 using make_char_pointer_t =
typename std::conditional_t<jau::req::char_pointer<T>, std::type_identity<const char * const>, std::type_identity<T>>::type;
845 using make_void_pointer_t =
typename std::conditional_t<jau::req::pointer<T>, std::type_identity<const void * const>, std::type_identity<T>>::type;
848 typedef FResult<NullOutput> CheckResult;
851 typedef FResult<StringOutput> StringResult;
853 template<OutputType Output>
856 typedef FResult<Output> Result;
857 constexpr Parser() noexcept = delete;
862 template <typename T>
863 requires std::is_integral_v<T> && (!jau::req::
boolean<T>)
864 static constexpr
void parseOne(Result &pc, const T &val) {
865 pc.m_argtype_size =
sizeof(T);
866 pc.m_argtype_signed = std::is_signed_v<T>;
868 using U = make_int_unsigned_t<T>;
872 template <
typename T>
873 requires std::is_floating_point_v<T>
874 static constexpr void parseOne(Result &pc,
const T &val) {
875 pc.m_argtype_size =
sizeof(T);
876 pc.m_argtype_signed =
true;
878 parseOneImpl<double>(pc,
double(val));
881 template <
typename T>
882 requires jau::req::pointer<T> && (!jau::req::char_pointer<T>)
883 static constexpr void parseOne(Result &pc,
const T &val) {
884 pc.m_argtype_size =
sizeof(T);
885 pc.m_argtype_signed =
false;
886 pc.m_argval_negative =
false;
887 using U = make_void_pointer_t<T>;
888 parseOneImpl<U>(pc,
U(val));
891 template <
typename T>
892 requires jau::req::char_pointer<T>
893 static constexpr void parseOne(Result &pc,
const T &val) {
894 pc.m_argtype_size =
sizeof(T);
895 pc.m_argtype_signed =
false;
896 pc.m_argval_negative =
false;
897 using U = make_char_pointer_t<T>;
898 parseOneImpl<U>(pc,
U(val));
901 template <
typename T>
902 requires jau::req::string_literal<T> || jau::req::string_class<T>
903 static constexpr void parseOne(Result &pc,
const T &val) {
904 pc.m_argtype_size =
sizeof(T);
905 pc.m_argtype_signed =
false;
906 pc.m_argval_negative =
false;
907 parseOneImpl<std::string_view>(pc, std::string_view(val));
910 template <
typename T>
911 requires (!( std::is_integral_v<T>
912 || std::is_floating_point_v<T>
913 || jau::req::pointer<T>
914 || jau::req::string_alike<T>)
915 ) || jau::req::boolean<T>
916 static constexpr void parseOne(Result &pc,
const T &val) {
917 pc.m_argtype_size =
sizeof(T);
918 pc.m_argtype_signed = std::is_signed_v<T>;
920 parseOneImpl<T>(pc, val);
923 template <
typename T>
924 requires std::is_integral_v<T> && (!jau::req::boolean<T>)
925 static constexpr void checkOne(CheckResult &pc)
noexcept {
926 pc.m_argtype_size =
sizeof(T);
927 pc.m_argtype_signed = std::is_signed_v<T>;
928 pc.m_argval_negative =
false;
929 using U = make_int_unsigned_t<T>;
930 parseOneImpl<U>(pc,
U());
933 template <
typename T>
934 requires std::is_floating_point_v<T>
935 static constexpr void checkOne(CheckResult &pc)
noexcept {
936 pc.m_argtype_size =
sizeof(T);
937 pc.m_argtype_signed =
true;
938 pc.m_argval_negative =
false;
939 parseOneImpl<double>(pc,
double());
942 template <
typename T>
943 requires jau::req::pointer<T>
944 static constexpr void checkOne(CheckResult &pc)
noexcept {
945 pc.m_argtype_size =
sizeof(T);
946 pc.m_argtype_signed =
false;
947 pc.m_argval_negative =
false;
949 parseOneImpl<U>(pc,
U());
952 template <
typename T>
953 requires jau::req::string_literal<T> || jau::req::string_class<T>
954 static constexpr void checkOne(CheckResult &pc)
noexcept {
955 pc.m_argtype_size =
sizeof(T);
956 pc.m_argtype_signed =
false;
957 pc.m_argval_negative =
false;
958 parseOneImpl<std::string_view>(pc, std::string_view());
961 template <
typename T>
962 requires (!( std::is_integral_v<T>
963 || std::is_floating_point_v<T>
964 || jau::req::pointer<T>
965 || jau::req::string_alike<T>)
966 ) || jau::req::boolean<T>
967 static constexpr void checkOne(CheckResult &pc)
noexcept {
968 pc.m_argtype_size =
sizeof(T);
969 pc.m_argtype_signed = std::is_signed_v<T>;
970 pc.m_argval_negative =
false;
971 parseOneImpl<T>(pc, T());
990 template <
typename T>
991 static constexpr void parseOneImpl(Result &pc,
const T &val) {
992 if( !pc.hasNext() ) {
999 if( !pc.toConversion() ) {
1005 if( !pc.nextSymbol(c) ) {
1006 pc.setError(__LINE__);
1017 parseArgWidthPrecision<T>(
true, pc, val);
1020 if( !parseFmtWidthPrecision(
true, pc, c) ) {
1033 if( !pc.nextSymbol(c) ) {
1034 pc.setError(__LINE__);
1039 parseArgWidthPrecision<T>(
false, pc, val);
1042 if( !parseFmtWidthPrecision(
false, pc, c) ) {
1047 pc.opts.setPrecision(0);
1053 if( !parseLengthMods(pc, c) ) {
1054 pc.appendError(
"Len");
1057 pc.setLastSpec(pc.pos);
1064 if( !parseFmtSpec<T>(pc, c, val) ) {
1065 pc.appendError(
"Cnv");
1073 }
while (loop_next);
1078 static constexpr void parseFlags(Result &pc,
char &c)
noexcept {
1079 while( pc.opts.addFlag(c) && pc.nextSymbol(c) ) { }
1083 template <
typename T>
1084 requires (!jau::req::unsigned_integral<T>)
1085 static constexpr void parseArgWidthPrecision(
bool, Result &pc,
const T &)
noexcept {
1086 pc.setError(__LINE__);
1089 template <
typename T>
1090 requires (jau::req::unsigned_integral<T>)
1091 static constexpr void parseArgWidthPrecision(
bool is_width, Result &pc,
const T &val)
noexcept {
1092 if constexpr( std::is_same_v<no_type_t, T> ) {
1093 pc.setError(__LINE__);
1097 if ( pc.m_argtype_size >
sizeof(
int) ) {
1098 pc.setError(__LINE__);
1101 if( pc.m_argval_negative ) {
1104 pc.opts.setWidth((uint32_t)val);
1106 pc.opts.setPrecision(0);
1110 pc.opts.setWidth((uint32_t)val);
1112 pc.opts.setPrecision((uint32_t)val);
1120 static constexpr bool parseFmtWidthPrecision(
bool is_width, Result &pc,
char &c)
noexcept {
1122 char *s = &buffer[0];
1123 const char *s_begin = s;
1127 if( !pc.nextSymbol(c) ) {
1128 pc.setError(__LINE__);
1133 pc.setError(__LINE__);
1136 std::string_view sv(s_begin, s - s_begin);
1146 if( num < 0 || num > std::numeric_limits<int>::max() ) {
1151 pc.opts.setWidth((uint32_t)num);
1153 pc.opts.setPrecision((uint32_t)num);
1159 static constexpr bool parseLengthMods(Result &pc,
char &c)
noexcept {
1161 if( !pc.nextSymbol(c) ) {
return false; }
1163 if( !pc.nextSymbol(c) ) {
return false; }
1168 }
else if(
'l' == c ) {
1169 if( !pc.nextSymbol(c) ) {
return false; }
1171 if( !pc.nextSymbol(c) ) {
return false; }
1176 }
else if(
'q' == c ) {
1177 if( !pc.nextSymbol(c) ) {
return false; }
1179 }
else if(
'L' == c ) {
1180 if( !pc.nextSymbol(c) ) {
return false; }
1182 }
else if(
'j' == c ) {
1183 if( !pc.nextSymbol(c) ) {
return false; }
1185 }
else if(
'z' == c ||
'Z' == c ) {
1186 if( !pc.nextSymbol(c) ) {
return false; }
1188 }
else if(
't' == c ) {
1189 if( !pc.nextSymbol(c) ) {
return false; }
1197 template <
typename T>
1198 static constexpr bool parseFmtSpec(Result &pc,
char fmt_literal,
const T &val) {
1199 if( !pc.opts.setConversion(fmt_literal) ) {
1200 pc.setError(__LINE__);
1204 switch( pc.opts.conversion ) {
1206 return parseCharFmtSpec<T>(pc, val);
1208 return parseStringFmtSpec<T>(pc, val);
1210 return parseAPointerFmtSpec<T>(pc, val);
1212 return parseSignedFmtSpec<T>(pc, val);
1214 return parseUnsignedFmtSpec<T>(pc, val);
1219 return parseFloatFmtSpec<T>(pc, fmt_literal, val);
1221 pc.setError(__LINE__);
1226 template <
typename T>
1227 requires (!jau::req::unsigned_integral<T>) || jau::req::boolean<T>
1228 static constexpr bool parseCharFmtSpec(Result &pc,
const T &)
noexcept {
1229 if constexpr( !std::is_same_v<no_type_t, T> ) {
1232 pc.setError(__LINE__);
1236 template <
typename T>
1237 requires jau::req::unsigned_integral<T> && (!jau::req::boolean<T>)
1238 static constexpr bool parseCharFmtSpec(Result &pc,
const T &val0) {
1241 using V = make_int_signed_t<T>;
1242 const V val =
V(val0);
1243 const V sign = pc.m_argval_negative ? -1 : 1;
1245 switch( pc.opts.length_mod ) {
1247 if ( !pc.m_argtype_signed ||
1248 (
sizeof(
char) != pc.m_argtype_size &&
1249 sizeof(
int) != pc.m_argtype_size ) ) {
1250 pc.setError(__LINE__);
1253 std::string s(1, (
char)(val*
sign));
1254 pc.appendFormatted(std::string_view(s));
1257 if ( !pc.m_argtype_signed ||
1258 (
sizeof(
wchar_t) != pc.m_argtype_size &&
1259 sizeof(wint_t) != pc.m_argtype_size ) ) {
1260 pc.setError(__LINE__);
1263 std::string s(1, (
char)(val*
sign));
1264 pc.appendFormatted(std::string_view(s));
1267 pc.setError(__LINE__);
1273 template <
typename T>
1274 requires (!(jau::req::stringifyable0_jau<T> || jau::req::boolean<T>))
1275 static constexpr bool parseStringFmtSpec(Result &pc,
const T &)
noexcept {
1276 if constexpr( !std::is_same_v<no_type_t, T> ) {
1279 pc.setError(__LINE__);
1282 template <
typename T>
1283 requires jau::req::stringifyable0_jau<T> || jau::req::boolean<T>
1284 static constexpr bool parseStringFmtSpec(Result &pc,
const T &val) {
1286 switch( pc.opts.length_mod ) {
1290 if constexpr( !(std::is_pointer_v<T> &&
1291 std::is_same_v<wchar_t, std::remove_cv_t<std::remove_pointer_t<T>>>) ) {
1292 pc.setError(__LINE__);
1298 pc.setError(__LINE__);
1301 pc.appendFormatted(val);
1305 template <
typename T>
1306 requires (!jau::req::pointer<T>)
1307 static constexpr bool parseAPointerFmtSpec(Result &pc,
const T &)
noexcept {
1308 if constexpr( !std::is_same_v<no_type_t, T> ) {
1311 pc.setError(__LINE__);
1314 template <
typename T>
1315 requires jau::req::pointer<T>
1316 static constexpr bool parseAPointerFmtSpec(Result &pc,
const T &val) {
1319 pc.appendFormatted((
void *)
const_cast<std::remove_const_t<T>
>(val));
1323 template <
typename T>
1324 requires (!(jau::req::unsigned_integral<T> || std::is_enum_v<T>))
1325 static constexpr bool parseSignedFmtSpec(Result &pc,
const T &)
noexcept {
1326 if constexpr( !std::is_same_v<no_type_t, T> ) {
1329 pc.setError(__LINE__);
1332 template <
typename T>
1333 requires std::is_enum_v<T> && (!jau::req::signed_integral<std::underlying_type_t<T>>)
1334 static constexpr bool parseSignedFmtSpec(Result &pc,
const T &)
noexcept {
1335 if constexpr( !std::is_same_v<no_type_t, T> ) {
1338 pc.setError(__LINE__);
1341 template <
typename T>
1342 requires std::is_enum_v<T> && jau::req::signed_integral<std::underlying_type_t<T>>
1343 static constexpr bool parseSignedFmtSpec(Result &pc,
const T &val0) {
1344 using U = std::underlying_type_t<T>;
1345 using V = make_int_unsigned_t<U>;
1346 const U u =
U(val0);
1347 pc.m_argtype_signed =
true;
1348 pc.m_argtype_size =
sizeof(
U);
1352 template <
typename T>
1353 requires jau::req::unsigned_integral<T>
1354 static constexpr bool parseSignedFmtSpec(Result &pc,
const T &val) {
1358 const unsigned int signed_argtype_size = pc.m_argtype_signed ? pc.m_argtype_size : pc.m_argtype_size + 1;
1361 pc.opts.flags &= ~flags_t
::hash;
1366 switch( pc.opts.length_mod ) {
1368 if ( signed_argtype_size >
sizeof(
char) ) {
1369 pc.setError(__LINE__);
1374 if ( signed_argtype_size >
sizeof(
short) ) {
1375 pc.setError(__LINE__);
1380 if ( signed_argtype_size >
sizeof(
int) ) {
1381 pc.setError(__LINE__);
1386 if ( signed_argtype_size >
sizeof(
long) ) {
1387 pc.setError(__LINE__);
1392 if ( signed_argtype_size >
sizeof(
long long) ) {
1393 pc.setError(__LINE__);
1398 if ( signed_argtype_size >
sizeof(intmax_t) ) {
1399 pc.setError(__LINE__);
1404 if ( signed_argtype_size >
sizeof(ssize_t) ) {
1405 pc.setError(__LINE__);
1410 if ( signed_argtype_size >
sizeof(ptrdiff_t) ) {
1411 pc.setError(__LINE__);
1416 pc.setError(__LINE__);
1419 if constexpr (jau::req::boolean<T>) {
1420 pc.appendFormatted((
unsigned int)val);
1422 pc.appendFormatted(val);
1427 template <
typename T>
1428 requires (!(jau::req::unsigned_integral<T> || std::is_enum_v<T>))
1429 static constexpr bool parseUnsignedFmtSpec(Result &pc,
const T &)
noexcept {
1430 if constexpr( !std::is_same_v<no_type_t, T> ) {
1433 pc.setError(__LINE__);
1436 template <
typename T>
1437 requires std::is_enum_v<T>
1438 static constexpr bool parseUnsignedFmtSpec(Result &pc,
const T &val0) {
1439 using U = std::underlying_type_t<T>;
1440 using V = make_int_unsigned_t<U>;
1441 const U u =
U(val0);
1442 pc.m_argtype_signed = std::is_signed_v<U>;
1443 pc.m_argtype_size =
sizeof(
U);
1447 template <
typename T>
1448 requires jau::req::unsigned_integral<T>
1449 static constexpr bool parseUnsignedFmtSpec(Result &pc,
const T &val) {
1453 if( pc.m_argval_negative ) {
1454 pc.setError(__LINE__);
1459 pc.opts.flags &= ~flags_t
::hash;
1464 switch( pc.opts.length_mod ) {
1466 if ( pc.m_argtype_size >
sizeof(
unsigned char) ) {
1467 pc.setError(__LINE__);
1472 if ( pc.m_argtype_size >
sizeof(
unsigned short) ) {
1473 pc.setError(__LINE__);
1478 if ( pc.m_argtype_size >
sizeof(
unsigned int) ) {
1479 pc.setError(__LINE__);
1484 if ( pc.m_argtype_size >
sizeof(
unsigned long) ) {
1485 pc.setError(__LINE__);
1490 if ( pc.m_argtype_size >
sizeof(
unsigned long long) ) {
1491 pc.setError(__LINE__);
1496 if ( pc.m_argtype_size >
sizeof(uintmax_t) ) {
1497 pc.setError(__LINE__);
1502 if ( pc.m_argtype_size >
sizeof(
size_t) ) {
1503 pc.setError(__LINE__);
1509 if ( pc.m_argtype_size >
sizeof(ptrdiff_t) ) {
1510 pc.setError(__LINE__);
1516 pc.setError(__LINE__);
1519 if constexpr (jau::req::boolean<T>) {
1520 pc.appendFormatted((
unsigned int)val);
1522 pc.appendFormatted(val);
1527 template <
typename T>
1528 requires (!std::floating_point<T>)
1529 static constexpr bool parseFloatFmtSpec(Result &pc,
const char ,
const T &)
noexcept {
1530 if constexpr( !std::is_same_v<no_type_t, T> ) {
1533 pc.setError(__LINE__);
1536 template <
typename T>
1537 requires std::floating_point<T>
1538 static constexpr bool parseFloatFmtSpec(Result &pc,
const char ,
const T &val) {
1541 using U = std::remove_cv_t<T>;
1543 switch( pc.opts.length_mod ) {
1546 if constexpr( !std::is_same_v<float, U> &&
1547 !std::is_same_v<double, U> ) {
1548 pc.setError(__LINE__);
1553 if constexpr( !std::is_same_v<float, U> &&
1554 !std::is_same_v<double, U> &&
1555 !std::is_same_v<long double, U> ) {
1557 pc.setError(__LINE__);
1562 pc.setError(__LINE__);
1565 pc.appendFormatted(val);
1570 typedef Parser<NullOutput> CheckParser;
1571 typedef Parser<StringOutput> FormatParser;
1590 template <
typename... Targs>
1591 inline __attribute__((always_inline))
1594 impl::StringResult ctx(impl::StringOutput(s.max_size(), s), fmt);
1596 std::exception_ptr eptr;
1598 if constexpr( 0 <
sizeof...(Targs) ) {
1599 ((impl::FormatParser::parseOne<Targs>(ctx, args)), ...);
1601 impl::FormatParser::parseOne<impl::no_type_t>(ctx, impl::no_type_t());
1603 eptr = std::current_exception();
1621 template <
typename... Targs>
1622 inline __attribute__((always_inline))
1623 std::
string format(
size_t maxLen,
std::string_view fmt, const Targs &...args) noexcept {
1625 impl::StringResult ctx(impl::StringOutput(std::min(maxLen, s.max_size()), s), fmt);
1627 std::exception_ptr eptr;
1629 if constexpr( 0 <
sizeof...(Targs) ) {
1630 ((impl::FormatParser::parseOne<Targs>(ctx, args)), ...);
1632 impl::FormatParser::parseOne<impl::no_type_t>(ctx, impl::no_type_t());
1634 eptr = std::current_exception();
1654 template <
typename... Targs>
1655 inline __attribute__((always_inline))
1657 impl::StringResult ctx(impl::StringOutput(std::min(maxLen, s.max_size()), s), fmt);
1659 std::exception_ptr eptr;
1661 if constexpr( 0 <
sizeof...(Targs) ) {
1662 ((impl::FormatParser::parseOne<Targs>(ctx, args)), ...);
1664 impl::FormatParser::parseOne<impl::no_type_t>(ctx, impl::no_type_t());
1666 eptr = std::current_exception();
1684 template <
typename... Targs>
1685 inline __attribute__((always_inline))
1687 return formatR(s, s.max_size(), fmt, args...);
1710 template <
typename... Targs>
1711 inline __attribute__((always_inline))
1712 Result formatR(const
std::
size_t strLenHint,
std::
string &s,
size_t maxLen,
std::string_view fmt, const Targs &...args) noexcept {
1713 impl::StringResult ctx(impl::StringOutput(std::min(maxLen, s.max_size()), s), fmt);
1715 std::exception_ptr eptr;
1717 s.reserve(strLenHint+1);
1718 if constexpr( 0 <
sizeof...(Targs) ) {
1719 ((impl::FormatParser::parseOne<Targs>(ctx, args)), ...);
1721 impl::FormatParser::parseOne<impl::no_type_t>(ctx, impl::no_type_t());
1723 eptr = std::current_exception();
1746 template <
typename... Targs>
1747 inline __attribute__((always_inline))
1749 return formatR(strLenHint, s, s.max_size(), fmt, args...);
1771 template <
typename... Targs>
1773 impl::CheckResult ctx(impl::NullOutput(), fmt);
1774 if constexpr( 0 <
sizeof...(Targs) ) {
1775 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1777 impl::CheckParser::checkOne<impl::no_type_t>(ctx);
1778 return ctx.arg_count;
1794 template <
typename... Targs>
1796 impl::CheckResult ctx(impl::NullOutput(), fmt);
1797 if constexpr( 0 <
sizeof...(Targs) ) {
1798 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1800 impl::CheckParser::checkOne<impl::no_type_t>(ctx);
1815 template <
typename... Targs>
1817 impl::CheckResult ctx(impl::NullOutput(), fmt);
1818 if constexpr( 0 <
sizeof...(Targs) ) {
1819 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1821 impl::CheckParser::checkOne<impl::no_type_t>(ctx);
1822 return ctx.arg_count;
1835 template <
typename... Targs>
1837 impl::CheckResult ctx(impl::NullOutput(), fmt);
1838 if constexpr( 0 <
sizeof...(Targs) ) {
1839 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1841 impl::CheckParser::checkOne<impl::no_type_t>(ctx);
1856 template <
typename... Targs>
1858 impl::CheckResult ctx(impl::NullOutput(), fmt);
1859 if constexpr( 0 <
sizeof...(Targs) ) {
1860 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1862 impl::CheckParser::checkOne<impl::no_type_t>(ctx);
1876 template <
typename... Targs>
1878 impl::CheckResult ctx(impl::NullOutput(),
format);
1879 if constexpr( 0 <
sizeof...(Targs) ) {
1880 ((impl::CheckParser::checkOne<Targs>(ctx)), ...);
1882 impl::CheckParser::checkOne<impl::no_type_t>(ctx);