15#ifndef JAU_STRING_CFMT_HPP_
16#define JAU_STRING_CFMT_HPP_
222 default:
return "error";
301 default:
return false;
332 switch (fmt_literal) {
417 s.append(std::to_string(
width));
420 s.append(
".").append(std::to_string(
precision));
441 }
else if( 8 ==
radix ) {
443 }
else if( 2 ==
radix ) {
469 fmt = std::string_view();
481 std::string s =
"fmt `";
487 s.append(std::to_string(
width));
491 s.append(
", precision ");
497 s.append(
", length `")
500 .append(
", radix ").append(std::to_string(
radix));
507 std::string_view m_fmt;
516 : m_fmt(
f), m_pos(
pos), m_arg_count(acount), m_line(line), m_opts(o), m_success(ok) {}
519 constexpr bool success() const noexcept {
return m_success; }
525 constexpr const std::string_view&
fmt() const noexcept {
return m_fmt; }
530 constexpr size_t pos() const noexcept {
return m_pos; }
532 constexpr int errorLine() const noexcept {
return m_line; }
535 const char c = m_pos < m_fmt.length() ? m_fmt[m_pos] :
'@';
536 std::string s =
"args ";
537 s.append(std::to_string(m_arg_count))
541 .append(std::to_string(m_line))
543 .append(std::to_string(m_pos))
545 .append(std::string(1, c))
546 .append(
"`, last[").append(m_opts.toString())
547 .append(
"], fmt `").append(m_fmt)
563 void append_rev(std::string &dest,
const size_t dest_maxlen, std::string_view src,
bool prec_cut,
bool reverse,
const FormatOpts &opts)
noexcept;
564 inline void append_string(std::string &dest,
const size_t dest_maxlen, std::string_view src,
const FormatOpts &opts)
noexcept {
565 append_rev(dest, dest_maxlen, src,
true ,
false , opts);
568 void append_integral(std::string &dest,
const size_t dest_maxlen,
const uint64_t val,
bool negative,
const FormatOpts &opts,
bool inject_dot=
false) noexcept;
572 requires (!
std::is_same_v<
double, value_type>)
578 }
else if (
value < -std::numeric_limits<value_type>::max()) {
579 append_string(dest, dest_maxlen, up ?
"-INF" :
"-inf", opts);
581 }
else if (
value > std::numeric_limits<value_type>::max()) {
583 append_string(dest, dest_maxlen,
plus ? ( up ?
"+INF" :
"+inf" ) : ( up ?
"INF" :
"inf" ), opts);
592 void append_afloatF64(std::string &dest,
const size_t dest_maxlen,
const double ivalue,
const size_t ivalue_size,
const FormatOpts &iopts)
noexcept;
596 {
t.maxLen() } -> std::same_as<size_t>;
599 {
t.get() } -> std::same_as<std::string_view>;
607 constexpr
size_t maxLen() const noexcept {
return 0; }
608 constexpr bool fits(
size_t)
const noexcept {
return false; }
610 std::string_view
get() const noexcept {
return "(nil)"; }
621 requires std::is_floating_point_v<T>
625 constexpr void appendError(
size_t,
int ,
const std::string_view )
noexcept {}
631 std::size_t m_maxLen;
637 constexpr size_t maxLen() const noexcept {
return m_maxLen; }
638 constexpr bool fits(
size_t n)
const noexcept {
return 0 < m_maxLen && n <= m_maxLen - m_s.size(); }
640 std::string_view
get() const noexcept {
return m_s; }
645 std::exception_ptr eptr;
649 eptr = std::current_exception();
656 std::exception_ptr eptr;
664 eptr = std::current_exception();
671 std::exception_ptr eptr;
675 eptr = std::current_exception();
682 std::exception_ptr eptr;
685 const uintptr_t v_le =
jau::cpu_to_le(
reinterpret_cast<uintptr_t
>(v));
691 eptr = std::current_exception();
698 std::exception_ptr eptr;
702 eptr = std::current_exception();
707 requires std::is_floating_point_v<T>
709 std::exception_ptr eptr;
720 eptr = std::current_exception();
725 if(
fits(v.size()) ) {
726 std::exception_ptr eptr;
730 eptr = std::current_exception();
735 void appendError(
size_t argIdx,
int line,
const std::string_view tag)
noexcept {
736 std::exception_ptr eptr;
738 m_s.append(
"<E#").append(std::to_string(argIdx)).append(
"@").append(std::to_string(line)).append(
":").append(tag).append(
">");
740 eptr = std::current_exception();
746 template<OutputType Output>
751 template<OutputType Output>
764 unsigned int m_argtype_size;
765 bool m_argtype_signed:1;
766 bool m_argval_negative:1;
769 constexpr FResult(Output p, std::string_view fmt_) noexcept
772 m_out(std::move(p)), pos_lstart(0),
774 m_argtype_signed(
false),
775 m_argval_negative(
false)
781 constexpr operator Result() const noexcept {
794 std::string s =
"args ";
799 .append(std::to_string(
line))
801 .append(std::to_string(
pos))
803 .append(std::string(1, c))
805 .append(
opts.toString())
806 .append(
"`, type[signed ")
809 .append(std::to_string(m_argtype_size))
810 .append(
"], negative ")
823 constexpr void reset() noexcept {
826 constexpr bool nextSymbol(
char &c)
noexcept {
834 constexpr bool toConversion() noexcept {
837 }
else if (
fmt[
pos] ==
'%') {
842 }
else if (
pos <
fmt.length()) {
844 const size_t q =
fmt.find(
'%',
pos + 1);
845 if (q == std::string::npos) {
865 constexpr void setLastSpec(
size_t endpos)
noexcept {
866 if (endpos > pos_lstart) {
867 opts.fmt =
fmt.substr(pos_lstart, endpos - pos_lstart);
871 constexpr void setError(
int l)
noexcept {
875 arg_count = std::numeric_limits<ssize_t>::min();
882 requires jau::req::stringifyable_jau<T> && (!jau::req::unsigned_integral<T>) && (!std::floating_point<T>)
883 constexpr FResult &appendFormatted(
const T &v)
noexcept {
884 m_out.appendFormatted(
opts, v);
888 requires jau::req::unsigned_integral<T> && (!jau::req::boolean<T>)
889 constexpr FResult &appendFormatted(
const T &v)
noexcept {
890 m_out.appendFormattedInt(
opts, v, m_argval_negative);
895 requires std::floating_point<T>
896 constexpr FResult &appendFormatted(
const T &v)
noexcept {
897 m_out.appendFormattedFloat(
opts, v, m_argtype_size);
901 constexpr FResult &appendText(
const std::string_view v)
noexcept {
905 constexpr FResult &appendError(
const std::string_view tag)
noexcept {
915 template <jau::req::
signed_
integral T>
934 requires std::floating_point<T>
955 using make_simple_pointer_t =
typename std::conditional_t<jau::req::pointer<T>, std::type_identity<const char * const>, std::type_identity<T>>
::type;
959 template<OutputType Output>
965 template <typename T>
966 requires
std::is_integral_v<T>
968 pc.m_argtype_size =
sizeof(T);
969 pc.m_argtype_signed = std::is_signed_v<T>;
972 parseOneImpl<U>(pc, U(
abs_int(val)));
975 template <
typename T>
976 requires std::is_floating_point_v<T>
978 pc.m_argtype_size =
sizeof(T);
979 pc.m_argtype_signed =
true;
981 parseOneImpl<double>(pc,
double(val));
984 template <
typename T>
987 pc.m_argtype_size =
sizeof(T);
988 pc.m_argtype_signed =
false;
989 pc.m_argval_negative =
false;
991 parseOneImpl<U>(pc, U(val));
994 template <
typename T>
997 pc.m_argtype_size =
sizeof(T);
998 pc.m_argtype_signed =
false;
999 pc.m_argval_negative =
false;
1000 parseOneImpl<std::string_view>(pc, std::string_view(val));
1003 template <
typename T>
1006 pc.m_argtype_size =
sizeof(T);
1007 pc.m_argtype_signed = std::is_signed_v<T>;
1009 parseOneImpl<T>(pc, val);
1012 template <
typename T>
1013 requires std::is_integral_v<T>
1015 pc.m_argtype_size =
sizeof(T);
1016 pc.m_argtype_signed = std::is_signed_v<T>;
1017 pc.m_argval_negative =
false;
1019 parseOneImpl<U>(pc, U());
1022 template <
typename T>
1023 requires std::is_floating_point_v<T>
1025 pc.m_argtype_size =
sizeof(T);
1026 pc.m_argtype_signed =
true;
1027 pc.m_argval_negative =
false;
1028 parseOneImpl<double>(pc,
double());
1031 template <
typename T>
1034 pc.m_argtype_size =
sizeof(T);
1035 pc.m_argtype_signed =
false;
1036 pc.m_argval_negative =
false;
1038 parseOneImpl<U>(pc, U());
1041 template <
typename T>
1044 pc.m_argtype_size =
sizeof(T);
1045 pc.m_argtype_signed =
false;
1046 pc.m_argval_negative =
false;
1047 parseOneImpl<std::string_view>(pc, std::string_view());
1050 template <
typename T>
1053 pc.m_argtype_size =
sizeof(T);
1054 pc.m_argtype_signed = std::is_signed_v<T>;
1055 pc.m_argval_negative =
false;
1056 parseOneImpl<T>(pc, T());
1074 template <
typename T>
1075 constexpr void parseOneImpl(
Result &pc,
const T &val)
const noexcept {
1083 if( !pc.toConversion() ) {
1089 if( !pc.nextSymbol(c) ) {
1090 pc.setError(__LINE__);
1101 parseArgWidthPrecision<T>(
true, pc, val);
1104 if( !parseFmtWidthPrecision(
true, pc, c) ) {
1117 if( !pc.nextSymbol(c) ) {
1118 pc.setError(__LINE__);
1123 parseArgWidthPrecision<T>(
false, pc, val);
1126 if( !parseFmtWidthPrecision(
false, pc, c) ) {
1136 if( !parseLengthMods(pc, c) ) {
1137 pc.appendError(
"Len");
1140 pc.setLastSpec(pc.
pos);
1147 if( !parseFmtSpec<T>(pc, c, val) ) {
1148 pc.appendError(
"Cnv");
1156 }
while (loop_next);
1161 constexpr void parseFlags(
Result &pc,
char &c)
const noexcept {
1162 while( pc.
opts.
addFlag(c) && pc.nextSymbol(c) ) { }
1166 template <
typename T>
1167 requires (!jau::req::unsigned_integral<T>)
1168 constexpr void parseArgWidthPrecision(
bool,
Result &pc,
const T &)
const noexcept {
1169 pc.setError(__LINE__);
1172 template <
typename T>
1173 requires (jau::req::unsigned_integral<T>)
1174 constexpr void parseArgWidthPrecision(
bool is_width,
Result &pc,
const T &val)
const noexcept {
1175 if constexpr( std::is_same_v<no_type_t, T> ) {
1176 pc.setError(__LINE__);
1180 if ( pc.m_argtype_size >
sizeof(
int) ) {
1181 pc.setError(__LINE__);
1184 if( pc.m_argval_negative ) {
1187 pc.opts.setWidth((
size_t)val);
1189 pc.opts.setPrecision(0);
1193 pc.opts.setWidth((
size_t)val);
1195 pc.opts.setPrecision((
size_t)val);
1203 constexpr bool parseFmtWidthPrecision(
bool is_width,
Result &pc,
char &c)
const noexcept {
1205 char *s = &buffer[0];
1206 const char *s_begin = s;
1210 if( !pc.nextSymbol(c) ) {
1211 pc.setError(__LINE__);
1216 pc.setError(__LINE__);
1219 std::string_view sv(s_begin, s - s_begin);
1229 pc.opts.setWidth((
size_t)num);
1231 pc.opts.setPrecision((
size_t)num);
1237 constexpr bool parseLengthMods(
Result &pc,
char &c)
const noexcept {
1239 if( !pc.nextSymbol(c) ) {
return false; }
1241 if( !pc.nextSymbol(c) ) {
return false; }
1246 }
else if(
'l' == c ) {
1247 if( !pc.nextSymbol(c) ) {
return false; }
1249 if( !pc.nextSymbol(c) ) {
return false; }
1254 }
else if(
'q' == c ) {
1255 if( !pc.nextSymbol(c) ) {
return false; }
1257 }
else if(
'L' == c ) {
1258 if( !pc.nextSymbol(c) ) {
return false; }
1260 }
else if(
'j' == c ) {
1261 if( !pc.nextSymbol(c) ) {
return false; }
1263 }
else if(
'z' == c ||
'Z' == c ) {
1264 if( !pc.nextSymbol(c) ) {
return false; }
1266 }
else if(
't' == c ) {
1267 if( !pc.nextSymbol(c) ) {
return false; }
1275 template <
typename T>
1276 constexpr bool parseFmtSpec(
Result &pc,
char fmt_literal,
const T &val)
const noexcept {
1277 if( !pc.opts.setConversion(fmt_literal) ) {
1278 pc.setError(__LINE__);
1282 switch( pc.opts.conversion ) {
1284 return parseCharFmtSpec<T>(pc, val);
1286 return parseStringFmtSpec<T>(pc, val);
1288 return parseAPointerFmtSpec<T>(pc, val);
1290 return parseSignedFmtSpec<T>(pc, val);
1292 return parseUnsignedFmtSpec<T>(pc, val);
1297 return parseFloatFmtSpec<T>(pc, fmt_literal, val);
1299 pc.setError(__LINE__);
1304 template <
typename T>
1305 requires (!jau::req::unsigned_integral<T>)
1306 constexpr bool parseCharFmtSpec(
Result &pc,
const T &)
const noexcept
1308 if constexpr( !std::is_same_v<no_type_t, T> ) {
1311 pc.setError(__LINE__);
1315 template <
typename T>
1316 requires jau::req::unsigned_integral<T>
1317 constexpr bool parseCharFmtSpec(
Result &pc,
const T &val0)
const noexcept
1322 const V val = V(val0);
1323 const V
sign = pc.m_argval_negative ? -1 : 1;
1325 switch( pc.opts.length_mod ) {
1327 if ( !pc.m_argtype_signed ||
1328 (
sizeof(
char) != pc.m_argtype_size &&
1329 sizeof(
int) != pc.m_argtype_size ) ) {
1330 pc.setError(__LINE__);
1333 std::string s(1, (
char)(val*
sign));
1334 pc.appendFormatted(std::string_view(s));
1337 if ( !pc.m_argtype_signed ||
1338 (
sizeof(
wchar_t) != pc.m_argtype_size &&
1339 sizeof(wint_t) != pc.m_argtype_size ) ) {
1340 pc.setError(__LINE__);
1343 std::string s(1, (
char)(val*
sign));
1344 pc.appendFormatted(std::string_view(s));
1347 pc.setError(__LINE__);
1353 template <
typename T>
1354 requires (!jau::req::string_alike<T>)
1355 constexpr bool parseStringFmtSpec(
Result &pc,
const T &)
const noexcept
1357 if constexpr( !std::is_same_v<no_type_t, T> ) {
1360 pc.setError(__LINE__);
1364 template <
typename T>
1365 requires jau::req::string_alike<T>
1366 constexpr bool parseStringFmtSpec(
Result &pc,
const T &val)
const noexcept
1369 switch( pc.opts.length_mod ) {
1373 if constexpr( !(std::is_pointer_v<T> &&
1374 std::is_same_v<wchar_t, std::remove_cv_t<std::remove_pointer_t<T>>>) ) {
1375 pc.setError(__LINE__);
1381 pc.setError(__LINE__);
1384 pc.appendFormatted(val);
1388 template <
typename T>
1389 requires (!jau::req::pointer<T>)
1390 constexpr bool parseAPointerFmtSpec(
Result &pc,
const T &)
const noexcept {
1391 if constexpr( !std::is_same_v<no_type_t, T> ) {
1394 pc.setError(__LINE__);
1397 template <
typename T>
1398 requires jau::req::pointer<T>
1399 constexpr bool parseAPointerFmtSpec(
Result &pc,
const T &val)
const noexcept {
1402 pc.appendFormatted((
void *)
const_cast<std::remove_const_t<T>
>(val));
1406 template <
typename T>
1407 requires (!(jau::req::unsigned_integral<T> || std::is_enum_v<T>))
1408 constexpr bool parseSignedFmtSpec(
Result &pc,
const T &)
const {
1409 if constexpr( !std::is_same_v<no_type_t, T> ) {
1412 pc.setError(__LINE__);
1415 template <
typename T>
1416 requires std::is_enum_v<T> && (!jau::req::signed_integral<std::underlying_type_t<T>>)
1417 constexpr bool parseSignedFmtSpec(
Result &pc,
const T &)
const {
1418 if constexpr( !std::is_same_v<no_type_t, T> ) {
1421 pc.setError(__LINE__);
1424 template <
typename T>
1425 requires std::is_enum_v<T> && jau::req::signed_integral<std::underlying_type_t<T>>
1426 constexpr bool parseSignedFmtSpec(
Result &pc,
const T &val0)
const {
1427 using U = std::underlying_type_t<T>;
1429 const U u = U(val0);
1430 pc.m_argtype_signed =
true;
1431 pc.m_argtype_size =
sizeof(U);
1433 return parseSignedFmtSpec<V>(pc, V(
abs_int(u)));
1435 template <
typename T>
1436 requires jau::req::unsigned_integral<T>
1437 constexpr bool parseSignedFmtSpec(
Result &pc,
const T &val)
const {
1442 const unsigned int signed_argtype_size = pc.m_argtype_signed ? pc.m_argtype_size : pc.m_argtype_size + 1;
1444 if( !pc.m_argtype_signed ) {
1445 pc.setError(__LINE__);
1451 pc.opts.flags &= ~flags_t
::hash;
1456 switch( pc.opts.length_mod ) {
1458 if ( signed_argtype_size >
sizeof(
char) ) {
1459 pc.setError(__LINE__);
1464 if ( signed_argtype_size >
sizeof(
short) ) {
1465 pc.setError(__LINE__);
1470 if ( signed_argtype_size >
sizeof(
int) ) {
1471 pc.setError(__LINE__);
1476 if ( signed_argtype_size >
sizeof(
long) ) {
1477 pc.setError(__LINE__);
1482 if ( signed_argtype_size >
sizeof(
long long) ) {
1483 pc.setError(__LINE__);
1488 if ( signed_argtype_size >
sizeof(intmax_t) ) {
1489 pc.setError(__LINE__);
1494 if ( signed_argtype_size >
sizeof(ssize_t) ) {
1495 pc.setError(__LINE__);
1500 if ( signed_argtype_size >
sizeof(ptrdiff_t) ) {
1501 pc.setError(__LINE__);
1506 pc.setError(__LINE__);
1509 pc.appendFormatted(val);
1513 template <
typename T>
1514 requires (!(jau::req::unsigned_integral<T> || std::is_enum_v<T>))
1515 constexpr bool parseUnsignedFmtSpec(
Result &pc,
const T &)
const noexcept {
1516 if constexpr( !std::is_same_v<no_type_t, T> ) {
1519 pc.setError(__LINE__);
1522 template <
typename T>
1523 requires std::is_enum_v<T>
1524 constexpr bool parseUnsignedFmtSpec(
Result &pc,
const T &val0)
const {
1525 using U = std::underlying_type_t<T>;
1527 const U u = U(val0);
1528 pc.m_argtype_signed = std::is_signed_v<U>;
1529 pc.m_argtype_size =
sizeof(U);
1531 return parseUnsignedFmtSpec<V>(pc, V(
abs_int(u)));
1533 template <
typename T>
1534 requires jau::req::unsigned_integral<T>
1535 constexpr bool parseUnsignedFmtSpec(
Result &pc,
const T &val)
const noexcept {
1539 if( pc.m_argval_negative ) {
1540 pc.setError(__LINE__);
1545 pc.opts.flags &= ~flags_t
::hash;
1550 switch( pc.opts.length_mod ) {
1552 if ( pc.m_argtype_size >
sizeof(
unsigned char) ) {
1553 pc.setError(__LINE__);
1558 if ( pc.m_argtype_size >
sizeof(
unsigned short) ) {
1559 pc.setError(__LINE__);
1564 if ( pc.m_argtype_size >
sizeof(
unsigned int) ) {
1565 pc.setError(__LINE__);
1570 if ( pc.m_argtype_size >
sizeof(
unsigned long) ) {
1571 pc.setError(__LINE__);
1576 if ( pc.m_argtype_size >
sizeof(
unsigned long long) ) {
1577 pc.setError(__LINE__);
1582 if ( pc.m_argtype_size >
sizeof(uintmax_t) ) {
1583 pc.setError(__LINE__);
1588 if ( pc.m_argtype_size >
sizeof(
size_t) ) {
1589 pc.setError(__LINE__);
1595 if ( pc.m_argtype_size >
sizeof(ptrdiff_t) ) {
1596 pc.setError(__LINE__);
1602 pc.setError(__LINE__);
1605 pc.appendFormatted(val);
1609 template <
typename T>
1610 requires (!std::floating_point<T>)
1611 constexpr bool parseFloatFmtSpec(
Result &pc,
const char ,
const T &)
const noexcept {
1612 if constexpr( !std::is_same_v<no_type_t, T> ) {
1615 pc.setError(__LINE__);
1618 template <
typename T>
1619 requires std::floating_point<T>
1620 constexpr bool parseFloatFmtSpec(
Result &pc,
const char ,
const T &val)
const noexcept {
1623 using U = std::remove_cv_t<T>;
1625 switch( pc.opts.length_mod ) {
1628 if constexpr( !std::is_same_v<float, U> &&
1629 !std::is_same_v<double, U> ) {
1630 pc.setError(__LINE__);
1635 if constexpr( !std::is_same_v<float, U> &&
1636 !std::is_same_v<double, U> &&
1637 !std::is_same_v<long double, U> ) {
1639 pc.setError(__LINE__);
1644 pc.setError(__LINE__);
1647 pc.appendFormatted(val);
1668 template <
typename... Targs>
1669 inline std::string
format(std::string_view fmt,
const Targs &...args)
noexcept {
1673 if constexpr( 0 <
sizeof...(Targs) ) {
1674 ((p.template parseOne<Targs>(ctx, args)), ...);
1692 template <
typename... Targs>
1693 inline std::string
format(
size_t maxLen, std::string_view fmt,
const Targs &...args)
noexcept {
1697 if constexpr( 0 <
sizeof...(Targs) ) {
1698 ((p.template parseOne<Targs>(ctx, args)), ...);
1717 template <
typename... Targs>
1718 inline Result formatR(std::string &s, std::string_view fmt,
const Targs &...args)
noexcept {
1721 if constexpr( 0 <
sizeof...(Targs) ) {
1722 ((p.template parseOne<Targs>(ctx, args)), ...);
1741 template <
typename... Targs>
1742 inline Result formatR(std::string &s,
size_t maxLen, std::string_view fmt,
const Targs &...args)
noexcept {
1745 if constexpr( 0 <
sizeof...(Targs) ) {
1746 ((p.template parseOne<Targs>(ctx, args)), ...);
1764 template <
typename... Targs>
1768 if constexpr( 0 <
sizeof...(Targs) ) {
1769 ((p.template checkOne<Targs>(ctx)), ...);
1771 p.template checkOne<impl::no_type_t>(ctx);
1785 template <
typename... Targs>
1789 if constexpr( 0 <
sizeof...(Targs) ) {
1790 ((p.template checkOne<Targs>(ctx)), ...);
1792 p.template checkOne<impl::no_type_t>(ctx);
1807 template <
typename... Targs>
1811 if constexpr( 0 <
sizeof...(Targs) ) {
1812 ((p.template checkOne<Targs>(ctx)), ...);
1814 p.template checkOne<impl::no_type_t>(ctx);
1828 template <
typename... Targs>
1832 if constexpr( 0 <
sizeof...(Targs) ) {
1833 ((p.template checkOne<Targs>(ctx)), ...);
1835 p.template checkOne<impl::no_type_t>(ctx);
1850 template <
typename... Targs>
1854 if constexpr( 0 <
sizeof...(Targs) ) {
1855 ((p.template checkOne<Targs>(ctx)), ...);
1857 p.template checkOne<impl::no_type_t>(ctx);
1871 template <
typename... Targs>
1875 if constexpr( 0 <
sizeof...(Targs) ) {
1876 ((p.template checkOne<Targs>(ctx)), ...);
1878 p.template checkOne<impl::no_type_t>(ctx);
1905 template<
typename... Args>
1906 inline std::string
format_string_n(
const std::size_t maxStrLen, std::string_view format,
const Args &...args)
noexcept {
1928 template <
typename... Args>
1929 inline std::string
format_string_h(
const std::size_t strLenHint, std::string_view format,
const Args &...args)
noexcept {
1931 std::exception_ptr eptr;
1933 str.reserve(strLenHint);
1936 eptr = std::current_exception();
1960 template <
typename... Args>
1961 inline std::string
format_string(std::string_view format,
const Args &...args)
noexcept {
1995#define jau_format_string(fmt, ...) \
1996 jau::format_string((fmt) __VA_OPT__(,) __VA_ARGS__); \
1997 static_assert(0 <= jau::cfmt::check2< JAU_FOR_EACH1_LIST(JAU_DECLTYPE_VALUE, __VA_ARGS__) >(fmt));
2020#define jau_format_string_h(strLenHint, fmt, ...) \
2021 jau::format_string((strLenHint), (fmt) __VA_OPT__(,) __VA_ARGS__); \
2022 static_assert(0 <= jau::cfmt::check2< JAU_FOR_EACH1_LIST(JAU_DECLTYPE_VALUE, __VA_ARGS__) >(fmt));
2045#define jau_format_string2(fmt, ...) \
2046 jau::format_string((fmt) __VA_OPT__(,) __VA_ARGS__); \
2047 static_assert(0 == jau::cfmt::check2Line< JAU_FOR_EACH1_LIST(JAU_DECLTYPE_VALUE, __VA_ARGS__) >(fmt));
2058#define jau_string_check(fmt, ...) \
2059 static_assert(0 <= jau::cfmt::check2< JAU_FOR_EACH1_LIST(JAU_DECLTYPE_VALUE, __VA_ARGS__) >(fmt));
2070#define jau_string_checkLine(fmt, ...) \
2071 static_assert(0 == jau::cfmt::check2Line< JAU_FOR_EACH1_LIST(JAU_DECLTYPE_VALUE, __VA_ARGS__) >(fmt));
constexpr ssize_t argumentCount() const noexcept
Arguments processed.
std::string toString() const
constexpr const std::string_view & fmt() const noexcept
format string_view
constexpr int errorLine() const noexcept
error line of implementation source code or zero if success (error analysis)
constexpr const FormatOpts & opts() const noexcept
Last argument FormatOpts (error analysis)
constexpr Result(std::string_view f, FormatOpts o, size_t pos, ssize_t acount, int line, bool ok)
constexpr bool success() const noexcept
true if operation was successful, otherwise indicates error
constexpr size_t pos() const noexcept
Position of next fmt character to be read (error analysis)
constexpr FResult(Output p, std::string_view fmt_) noexcept
constexpr FResult & operator=(const FResult &x) noexcept=default
constexpr ssize_t argCount() const noexcept
std::string toString() const
constexpr FResult(const FResult &pre) noexcept=default
constexpr bool hasNext() const noexcept
constexpr bool error() const noexcept
A null OutputType for constexpr and consteval formatting dropping all output.
constexpr void appendText(std::string_view) noexcept
constexpr size_t maxLen() const noexcept
constexpr bool fits(size_t) const noexcept
std::string_view get() const noexcept
constexpr void appendError(size_t, int, const std::string_view) noexcept
constexpr void appendFormatted(const FormatOpts &, const T &) noexcept
constexpr NullOutput() noexcept=default
constexpr void appendFormattedInt(const FormatOpts &, const T &, bool) noexcept
constexpr void appendFormattedFloat(const FormatOpts &, const T &, nsize_t) noexcept
constexpr void parseOne(Result &pc, const T &val) const noexcept
constexpr void parseOne(Result &pc, const T &val) const noexcept
constexpr void checkOne(Result &pc) const noexcept
constexpr void parseOne(Result &pc, const T &val) const noexcept
constexpr void parseOne(Result &pc, const T &val) const noexcept
constexpr void checkOne(Result &pc) const noexcept
constexpr void checkOne(Result &pc) const noexcept
constexpr void parseOne(Result &pc, const T &val) const noexcept
constexpr Parser() noexcept=default
constexpr void checkOne(Result &pc) const noexcept
constexpr void checkOne(Result &pc) const noexcept
A std::string OutputType for runtime formatting into a std::string.
void appendFormatted(const FormatOpts &opts, const T &v) noexcept
void appendText(const std::string_view v) noexcept
constexpr bool fits(size_t n) const noexcept
std::string_view get() const noexcept
void appendFormattedFloat(const FormatOpts &opts, const T &v, nsize_t floatSize) noexcept
void appendError(size_t argIdx, int line, const std::string_view tag) noexcept
StringOutput(std::size_t maxLen, std::string &s) noexcept
void appendFormatted(const FormatOpts &opts, const T &v) noexcept
constexpr size_t maxLen() const noexcept
void appendFormatted(const FormatOpts &opts, const T &v) noexcept
void appendFormattedInt(const FormatOpts &opts, const T &v, bool negative) noexcept
void appendFormatted(const FormatOpts &opts, const T &v) noexcept
Concept of type-trait for bool type.
Concept of type-trait std::is_pointer.
Concept of type-trait std::is_signed and std::is_integral.
A string class, i.e. std::string, std::string_view or jau::StringLiteral.
A string literal: char (&)[N], jau::StringLiteral.
A convertible type to a string or a string itself.
Concept of type-trait std::is_unsigned and std::is_integral.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr uint16_t cpu_to_le(uint16_t const h) noexcept
#define JAU_MAKE_ENUM_STRING(type,...)
constexpr bool value(const Bool rhs) noexcept
#define JAU_MAKE_BITFIELD_ENUM_STRING(type,...)
constexpr bool is_set(const E mask, const E bits) noexcept
std::ostream & operator<<(std::ostream &os, const T v)
std::add_const_t< std::add_pointer_t< std::add_const_t< underlying_pointer_type< T > > > > const2_pointer
Returns all const pointer type w/ constant'ness in pointer and value.
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
bool handle_exception(std::exception_ptr eptr)
Handle given optional exception (nullable std::exception_ptr) and send std::exception::what() message...
constexpr bool is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an arithmetic number w/ branching in O(1)
constexpr int sign(const T x) noexcept
Returns the value of the sign function (w/o branching ?) in O(1).
uint_bytes_t< sizeof(unsigned long int)> nsize_t
Natural 'size_t' alternative using uint<XX>_t with xx = sizeof(unsigned long int)*8 as its natural si...
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
plength_t
Format length modifiers.
constexpr bool from_chars(value_type &result, std::string_view str) noexcept
constexpr bool is_digit(char c) noexcept
Result formatR(std::string &s, std::string_view fmt, const Targs &...args) noexcept
Strict format with type validation of arguments against the format string, appending to the given des...
cspec_t
Format conversion specifier (fully defined w/ radix)
constexpr const size_t num_max_slen
Maximum net number string len w/o EOS, up to uint64_t.
static constexpr const char * to_string(pstate_t s) noexcept
consteval_cxx20 int checkLine(std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
consteval_cxx20 ssize_t check2(std::string_view fmt) noexcept
Strict type validation of arguments against the format string.
consteval_cxx20 Result checkR(std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
consteval_cxx20 Result checkR2(std::string_view format) noexcept
Strict type validation of arguments against the format string.
consteval_cxx20 int check2Line(std::string_view fmt) noexcept
Strict type validation of arguments against the format string.
constexpr const size_t default_string_capacity
Default string reserved capacity w/o EOS (511)
consteval_cxx20 ssize_t check(std::string_view fmt, const Targs &...) noexcept
Strict type validation of arguments against the format string.
std::string format(std::string_view fmt, const Targs &...args) noexcept
Strict format with type validation of arguments against the format string.
@ j
intmax_t or uintmax_t integer
@ z
size_t or ssize_t integer
@ uppercase
uppercase, via conversion spec
@ thousands
actual flag ‘’`, POSIX
@ zeropad
actual flag 0, C99
@ unsigned_int
o, x or X, u, b
typename std::conditional_t< std::is_integral_v< T >||jau::req::boolean< T >, std::type_identity< uint64_t >, std::type_identity< T > >::type make_int_unsigned_t
Returns uint64_t type if: integral || boolean, otherwise returns orig type.
FResult< StringOutput > SFormatResult
A StringOutput formatting result for runtime formatting into a std::string.
constexpr T abs_int(const T x) noexcept
void append_integral(std::string &dest, const size_t dest_maxlen, const uint64_t val, bool negative, const FormatOpts &opts, bool inject_dot=false) noexcept
typename std::conditional_t< jau::req::pointer< T >, std::type_identity< const char *const >, std::type_identity< T > >::type make_simple_pointer_t
Returns a simple const char * const if: pointer, otherwise returns orig type.
FResult< NullOutput > CheckResult
Parser< StringOutput > FormatParser
void append_afloatF64(std::string &dest, const size_t dest_maxlen, const double ivalue, const size_t ivalue_size, const FormatOpts &iopts) noexcept
typename std::conditional_t< jau::req::unsigned_integral< T > &&!jau::req::boolean< T >, std::make_signed< T >, std::type_identity< T > >::type make_int_signed_t
Returns signed-type variation if: unsigned-integral && !boolean, otherwise returns orig type.
constexpr bool is_positive(const T a) noexcept
void append_rev(std::string &dest, const size_t dest_maxlen, std::string_view src, bool prec_cut, bool reverse, const FormatOpts &opts) noexcept
bool is_float_validT(std::string &dest, const size_t dest_maxlen, const value_type value, const FormatOpts &opts) noexcept
void append_string(std::string &dest, const size_t dest_maxlen, std::string_view src, const FormatOpts &opts) noexcept
void append_floatF64(std::string &dest, const size_t dest_maxlen, const double value, const FormatOpts &opts) noexcept
constexpr const double_t max_append_float
constexpr const size_t float_charbuf_maxlen
void append_efloatF64(std::string &dest, const size_t dest_maxlen, const double ivalue, const FormatOpts &iopts) noexcept
bool is_float_validF64(std::string &dest, const size_t dest_maxlen, const double value, const FormatOpts &opts) noexcept
constexpr const size_t default_float_precision
Parser< NullOutput > CheckParser
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2021-2026 Gothel Software e....
Author: Sven Gothel sgothel@jausoft.com Copyright Gothel Software e.K.
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
std::string format_string_h(const std::size_t strLenHint, std::string_view format, const Args &...args) noexcept
Safely returns a (non-truncated) string according to snprintf() formatting rules and variable number ...
std::string format_string_n(const std::size_t maxStrLen, std::string_view format, const Args &...args) noexcept
Safely returns a (potentially truncated) string according to snprintf() formatting rules and variable...
std::string format_string(std::string_view format, const Args &...args) noexcept
Safely returns a (non-truncated) string according to snprintf() formatting rules using a reserved str...
static std::string f(uint32_t v)