125 #ifndef TINYFORMAT_H_INCLUDED
126 #define TINYFORMAT_H_INCLUDED
136 #define TINYFORMAT_ERROR(reasonString) \
137 throw tinyformat::format_error(reasonString)
141 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
150 #ifndef TINYFORMAT_ASSERT
152 #define TINYFORMAT_ASSERT(cond) assert(cond)
155 #ifndef TINYFORMAT_ERROR
157 #define TINYFORMAT_ERROR(reason) assert(0 && reason)
160 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && \
161 !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
162 #ifdef __GXX_EXPERIMENTAL_CXX0X__
163 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
167 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
170 #define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
176 #define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
178 #define TINYFORMAT_HIDDEN
186 explicit format_error(
const std::string &what) : std::runtime_error(what) {}
210 #pragma warning(push)
211 #pragma warning(disable : 4244)
212 #pragma warning(disable : 4267)
231 template <
int n>
struct is_wchar<const wchar_t[n]> {};
236 template <
typename T,
typename fmtT,
239 static void invoke(std::ostream & ,
const T & ) {
245 template <
typename T,
typename fmtT>
247 static void invoke(std::ostream &out,
const T &value) {
248 out << static_cast<fmtT>(value);
252 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
253 template <typename T, bool convertible = is_convertible<T, int>::value>
254 struct formatZeroIntegerWorkaround {
255 static bool invoke(std::ostream & ,
const T & ) {
259 template <
typename T>
struct formatZeroIntegerWorkaround<T, true> {
260 static bool invoke(std::ostream &out,
const T &value) {
261 if (
static_cast<int>(value) == 0 &&
262 out.flags() & std::ios::showpos) {
273 template <typename T, bool convertible = is_convertible<T, int>::value>
277 "integer for use as variable width or precision");
283 static int invoke(
const T &value) {
return static_cast<int>(value); }
287 template <
typename T>
289 std::ostringstream tmp;
291 std::string result = tmp.str();
292 out.write(result.c_str(),
293 (std::min)(ntrunc,
static_cast<int>(result.size())));
295 #define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
296 inline void formatTruncated(std::ostream &out, type *value, int ntrunc) { \
297 std::streamsize len = 0; \
298 while (len < ntrunc && value[len] != 0) \
300 out.write(value, len); \
306 #undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
325 template <
typename T>
327 const char *fmtEnd,
int ntrunc,
const T &value) {
328 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
341 const bool canConvertToVoidPtr =
343 if (canConvertToChar && *(fmtEnd - 1) ==
'c')
345 else if (canConvertToVoidPtr && *(fmtEnd - 1) ==
'p')
347 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
348 else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value))
351 else if (ntrunc >= 0) {
360 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
361 inline void formatValue(std::ostream &out, const char * , \
362 const char *fmtEnd, int , charType value) { \
363 switch (*(fmtEnd - 1)) { \
370 out << static_cast<int>(value); \
381 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
388 #define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_##n
389 #define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_##n
390 #define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_##n
391 #define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_##n
429 #define TINYFORMAT_ARGTYPES_1 class T1
430 #define TINYFORMAT_ARGTYPES_2 class T1, class T2
431 #define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
432 #define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
433 #define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
434 #define TINYFORMAT_ARGTYPES_6 \
435 class T1, class T2, class T3, class T4, class T5, class T6
436 #define TINYFORMAT_ARGTYPES_7 \
437 class T1, class T2, class T3, class T4, class T5, class T6, class T7
438 #define TINYFORMAT_ARGTYPES_8 \
439 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
441 #define TINYFORMAT_ARGTYPES_9 \
442 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
444 #define TINYFORMAT_ARGTYPES_10 \
445 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
446 class T8, class T9, class T10
447 #define TINYFORMAT_ARGTYPES_11 \
448 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
449 class T8, class T9, class T10, class T11
450 #define TINYFORMAT_ARGTYPES_12 \
451 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
452 class T8, class T9, class T10, class T11, class T12
453 #define TINYFORMAT_ARGTYPES_13 \
454 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
455 class T8, class T9, class T10, class T11, class T12, class T13
456 #define TINYFORMAT_ARGTYPES_14 \
457 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
458 class T8, class T9, class T10, class T11, class T12, class T13, \
460 #define TINYFORMAT_ARGTYPES_15 \
461 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
462 class T8, class T9, class T10, class T11, class T12, class T13, \
464 #define TINYFORMAT_ARGTYPES_16 \
465 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
466 class T8, class T9, class T10, class T11, class T12, class T13, \
467 class T14, class T15, class T16
469 #define TINYFORMAT_VARARGS_1 const T1 &v1
470 #define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
471 #define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
472 #define TINYFORMAT_VARARGS_4 \
473 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
474 #define TINYFORMAT_VARARGS_5 \
475 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
476 #define TINYFORMAT_VARARGS_6 \
477 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
479 #define TINYFORMAT_VARARGS_7 \
480 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
481 const T6 &v6, const T7 &v7
482 #define TINYFORMAT_VARARGS_8 \
483 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
484 const T6 &v6, const T7 &v7, const T8 &v8
485 #define TINYFORMAT_VARARGS_9 \
486 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
487 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
488 #define TINYFORMAT_VARARGS_10 \
489 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
490 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
491 #define TINYFORMAT_VARARGS_11 \
492 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
493 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
494 const T10 &v10, const T11 &v11
495 #define TINYFORMAT_VARARGS_12 \
496 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
497 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
498 const T10 &v10, const T11 &v11, const T12 &v12
499 #define TINYFORMAT_VARARGS_13 \
500 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
501 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
502 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
503 #define TINYFORMAT_VARARGS_14 \
504 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
505 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
506 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
508 #define TINYFORMAT_VARARGS_15 \
509 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
510 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
511 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
512 const T14 &v14, const T15 &v15
513 #define TINYFORMAT_VARARGS_16 \
514 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
515 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
516 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
517 const T14 &v14, const T15 &v15, const T16 &v16
519 #define TINYFORMAT_PASSARGS_1 v1
520 #define TINYFORMAT_PASSARGS_2 v1, v2
521 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
522 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
523 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
524 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
525 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
526 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
527 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
528 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
529 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
530 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
531 #define TINYFORMAT_PASSARGS_13 \
532 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
533 #define TINYFORMAT_PASSARGS_14 \
534 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
535 #define TINYFORMAT_PASSARGS_15 \
536 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
537 #define TINYFORMAT_PASSARGS_16 \
538 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
540 #define TINYFORMAT_PASSARGS_TAIL_1
541 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
542 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
543 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
544 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
545 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
546 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
547 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
548 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
549 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
550 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
551 #define TINYFORMAT_PASSARGS_TAIL_12 \
552 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
553 #define TINYFORMAT_PASSARGS_TAIL_13 \
554 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
555 #define TINYFORMAT_PASSARGS_TAIL_14 \
556 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
557 #define TINYFORMAT_PASSARGS_TAIL_15 \
558 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
559 #define TINYFORMAT_PASSARGS_TAIL_16 \
560 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
562 #define TINYFORMAT_FOREACH_ARGNUM(m) \
563 m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) m(10) m(11) m(12) m(13) m(14) \
577 template <
typename T>
579 :
m_value(static_cast<const void *>(&value)),
582 void format(std::ostream &out,
const char *fmtBegin,
const char *fmtEnd,
596 template <
typename T>
598 formatImpl(std::ostream &out,
const char *fmtBegin,
const char *fmtEnd,
599 int ntrunc,
const void *value) {
601 *
static_cast<const T *
>(value));
604 template <
typename T>
611 const char *fmtEnd,
int ntrunc,
const void *value);
619 for (; *c >=
'0' && *c <=
'9'; ++c)
620 i = 10 * i + (*c -
'0');
632 int &argIndex,
int numArgs) {
633 if (*c >=
'0' && *c <=
'9') {
635 }
else if (*c ==
'*') {
638 if (positionalMode) {
642 "after a positional one");
643 if (pos >= 0 && pos < numArgs)
644 n = args[pos].
toInt();
647 "tinyformat: Positional argument out of range");
650 if (argIndex < numArgs)
651 n = args[argIndex++].
toInt();
654 "variable width or precision");
672 out.write(fmt, c - fmt);
674 }
else if (*c ==
'%') {
675 out.write(fmt, c - fmt);
676 if (*(c + 1) !=
'%')
return c;
719 bool &positionalMode,
720 bool &spacePadPositive,
721 int &ntrunc,
const char *fmtStart,
723 int &argIndex,
int numArgs) {
730 out.unsetf(std::ios::adjustfield | std::ios::basefield |
731 std::ios::floatfield | std::ios::showbase |
732 std::ios::boolalpha | std::ios::showpoint |
733 std::ios::showpos | std::ios::uppercase);
734 bool precisionSet =
false;
735 bool widthSet =
false;
737 const char *c = fmtStart + 1;
741 if (*c >=
'0' && *c <=
'9') {
742 const char tmpc = *c;
746 if (value > 0 && value <= numArgs)
747 argIndex = value - 1;
750 "tinyformat: Positional argument out of range");
752 positionalMode =
true;
753 }
else if (positionalMode) {
755 "after a positional one");
761 out.setf(std::ios::internal, std::ios::adjustfield);
769 }
else if (positionalMode) {
779 out.setf(std::ios::showpoint | std::ios::showbase);
783 if (!(out.flags() & std::ios::left)) {
787 out.setf(std::ios::internal, std::ios::adjustfield);
792 out.setf(std::ios::left, std::ios::adjustfield);
796 if (!(out.flags() & std::ios::showpos))
797 spacePadPositive =
true;
800 out.setf(std::ios::showpos);
801 spacePadPositive =
false;
817 out.setf(std::ios::left, std::ios::adjustfield);
831 precisionSet = precision >= 0;
832 if (precisionSet) out.precision(precision);
835 while (*c ==
'l' || *c ==
'h' || *c ==
'L' || *c ==
'j' || *c ==
'z' ||
842 bool intConversion =
false;
847 out.setf(std::ios::dec, std::ios::basefield);
848 intConversion =
true;
851 out.setf(std::ios::oct, std::ios::basefield);
852 intConversion =
true;
855 out.setf(std::ios::uppercase);
859 out.setf(std::ios::hex, std::ios::basefield);
860 intConversion =
true;
863 out.setf(std::ios::uppercase);
866 out.setf(std::ios::scientific, std::ios::floatfield);
867 out.setf(std::ios::dec, std::ios::basefield);
870 out.setf(std::ios::uppercase);
873 out.setf(std::ios::fixed, std::ios::floatfield);
876 out.setf(std::ios::uppercase);
886 out.setf(std::ios::fixed | std::ios::scientific,
887 std::ios::floatfield);
890 out.setf(std::ios::uppercase);
893 out.setf(std::ios::dec, std::ios::basefield);
895 out.flags(out.flags() & ~std::ios::floatfield);
901 if (precisionSet) ntrunc =
static_cast<int>(out.precision());
903 out.setf(std::ios::boolalpha);
908 "tinyformat: %n conversion spec not supported");
912 "terminated by end of string");
917 if (intConversion && precisionSet && !widthSet) {
922 out.width(out.precision() + widthExtra);
923 out.setf(std::ios::internal, std::ios::adjustfield);
933 std::streamsize origWidth = out.width();
934 std::streamsize origPrecision = out.precision();
935 std::ios::fmtflags origFlags = out.flags();
936 char origFill = out.fill();
941 bool positionalMode =
false;
946 if (!positionalMode && argIndex < numArgs) {
948 "specifiers in format string");
952 bool spacePadPositive =
false;
956 ntrunc, fmt, args, argIndex, numArgs);
960 if (argIndex >= numArgs) {
967 if (!spacePadPositive) {
968 arg.
format(out, fmt, fmtEnd, ntrunc);
974 std::ostringstream tmpStream;
975 tmpStream.copyfmt(out);
976 tmpStream.setf(std::ios::showpos);
977 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
978 std::string result = tmpStream.str();
979 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
980 if (result[i] ==
'+') result[i] =
' ';
984 if (!positionalMode) ++argIndex;
989 out.width(origWidth);
990 out.precision(origPrecision);
991 out.flags(origFlags);
1007 friend void vformat(std::ostream &out,
const char *fmt,
1023 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1024 template <
typename... Args>
1028 static_assert(
sizeof...(args) == N,
"Number of args must be N");
1032 #define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
1034 template <TINYFORMAT_ARGTYPES(n)> \
1035 FormatListN(TINYFORMAT_VARARGS(n)) : FormatList(&m_formatterStore[0], n) { \
1036 TINYFORMAT_ASSERT(n == N); \
1037 init(0, TINYFORMAT_PASSARGS(n)); \
1040 template <TINYFORMAT_ARGTYPES(n)> \
1041 void init(int i, TINYFORMAT_VARARGS(n)) { \
1042 m_formatterStore[i] = FormatArg(v1); \
1043 init(i + 1 TINYFORMAT_PASSARGS_TAIL(n)); \
1047 #undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1071 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1079 template <
typename... Args>
1087 return detail::FormatListN<0>();
1089 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1090 template <TINYFORMAT_ARGTYPES(n)> \
1091 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) { \
1092 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1095 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
1107 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1110 template <
typename... Args>
1111 void format(std::ostream &out,
const char *fmt,
const Args &...args) {
1117 template <
typename... Args>
1118 std::string
format(
const char *fmt,
const Args &...args) {
1119 std::ostringstream oss;
1120 format(oss, fmt, args...);
1125 template <
typename... Args>
void printf(
const char *fmt,
const Args &...args) {
1126 format(std::cout, fmt, args...);
1129 template <
typename... Args>
1131 format(std::cout, fmt, args...);
1137 inline void format(std::ostream &out,
const char *fmt) {
1141 inline std::string
format(
const char *fmt) {
1142 std::ostringstream oss;
1147 inline void printf(
const char *fmt) {
1151 inline void printfln(
const char *fmt) {
1156 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1158 template <TINYFORMAT_ARGTYPES(n)> \
1159 void format(std::ostream &out, const char *fmt, TINYFORMAT_VARARGS(n)) { \
1160 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1163 template <TINYFORMAT_ARGTYPES(n)> \
1164 std::string format(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1165 std::ostringstream oss; \
1166 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1170 template <TINYFORMAT_ARGTYPES(n)> \
1171 void printf(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1172 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1175 template <TINYFORMAT_ARGTYPES(n)> \
1176 void printfln(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1177 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1178 std::cout << '\n'; \
1182 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1187 template <
typename... Args>
1188 std::string
format(
const std::string &fmt,
const Args &...args) {
1189 std::ostringstream oss;
1190 format(oss, fmt.c_str(), args...);
1201 #define strprintf tfm::format