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
151#ifndef TINYFORMAT_ASSERT
153#define TINYFORMAT_ASSERT(cond) assert(cond)
156#ifndef TINYFORMAT_ERROR
158#define TINYFORMAT_ERROR(reason) assert(0 && reason)
161#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && \
162 !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
163#ifdef __GXX_EXPERIMENTAL_CXX0X__
164#define TINYFORMAT_USE_VARIADIC_TEMPLATES
168#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
171#define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
177#define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
179#define TINYFORMAT_HIDDEN
212#pragma warning(disable : 4244)
213#pragma warning(disable : 4267)
232 template <
int n>
struct is_wchar<const wchar_t[n]> {};
237 template <
typename T,
typename fmtT,
240 static void invoke(std::ostream & ,
const T & ) {
246 template <
typename T,
typename fmtT>
248 static void invoke(std::ostream &out,
const T &value) {
249 out << static_cast<fmtT>(value);
253#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
254 template <typename T, bool convertible = is_convertible<T, int>::value>
255 struct formatZeroIntegerWorkaround {
256 static bool invoke(std::ostream & ,
const T & ) {
260 template <
typename T>
struct formatZeroIntegerWorkaround<T, true> {
261 static bool invoke(std::ostream &out,
const T &value) {
262 if (
static_cast<int>(value) == 0 &&
263 out.flags() & std::ios::showpos) {
274 template <typename T, bool convertible = is_convertible<T, int>::value>
278 "integer for use as variable width or precision");
284 static int invoke(
const T &value) {
return static_cast<int>(value); }
288 template <
typename T>
290 std::ostringstream tmp;
292 std::string result = tmp.str();
293 out.write(result.c_str(),
294 (std::min)(ntrunc,
static_cast<int>(result.size())));
296#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
297 inline void formatTruncated(std::ostream &out, type *value, int ntrunc) { \
298 std::streamsize len = 0; \
299 while (len < ntrunc && value[len] != 0) \
301 out.write(value, len); \
307#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
328 const char *fmtEnd,
int ntrunc,
const T &value) {
329#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
342 const bool canConvertToVoidPtr =
344 if (canConvertToChar && *(fmtEnd - 1) ==
'c')
346 else if (canConvertToVoidPtr && *(fmtEnd - 1) ==
'p')
348#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
349 else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value))
352 else if (ntrunc >= 0) {
361#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
362 inline void formatValue(std::ostream &out, const char * , \
363 const char *fmtEnd, int , charType value) { \
364 switch (*(fmtEnd - 1)) { \
371 out << static_cast<int>(value); \
382#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
389#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_##n
390#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_##n
391#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_##n
392#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_##n
430#define TINYFORMAT_ARGTYPES_1 class T1
431#define TINYFORMAT_ARGTYPES_2 class T1, class T2
432#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
433#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
434#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
435#define TINYFORMAT_ARGTYPES_6 \
436 class T1, class T2, class T3, class T4, class T5, class T6
437#define TINYFORMAT_ARGTYPES_7 \
438 class T1, class T2, class T3, class T4, class T5, class T6, class T7
439#define TINYFORMAT_ARGTYPES_8 \
440 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
442#define TINYFORMAT_ARGTYPES_9 \
443 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
445#define TINYFORMAT_ARGTYPES_10 \
446 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
447 class T8, class T9, class T10
448#define TINYFORMAT_ARGTYPES_11 \
449 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
450 class T8, class T9, class T10, class T11
451#define TINYFORMAT_ARGTYPES_12 \
452 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
453 class T8, class T9, class T10, class T11, class T12
454#define TINYFORMAT_ARGTYPES_13 \
455 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
456 class T8, class T9, class T10, class T11, class T12, class T13
457#define TINYFORMAT_ARGTYPES_14 \
458 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
459 class T8, class T9, class T10, class T11, class T12, class T13, \
461#define TINYFORMAT_ARGTYPES_15 \
462 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
463 class T8, class T9, class T10, class T11, class T12, class T13, \
465#define TINYFORMAT_ARGTYPES_16 \
466 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
467 class T8, class T9, class T10, class T11, class T12, class T13, \
468 class T14, class T15, class T16
470#define TINYFORMAT_VARARGS_1 const T1 &v1
471#define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
472#define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
473#define TINYFORMAT_VARARGS_4 \
474 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
475#define TINYFORMAT_VARARGS_5 \
476 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
477#define TINYFORMAT_VARARGS_6 \
478 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
480#define TINYFORMAT_VARARGS_7 \
481 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
482 const T6 &v6, const T7 &v7
483#define TINYFORMAT_VARARGS_8 \
484 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
485 const T6 &v6, const T7 &v7, const T8 &v8
486#define TINYFORMAT_VARARGS_9 \
487 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
488 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
489#define TINYFORMAT_VARARGS_10 \
490 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
491 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
492#define TINYFORMAT_VARARGS_11 \
493 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
494 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
495 const T10 &v10, const T11 &v11
496#define TINYFORMAT_VARARGS_12 \
497 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
498 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
499 const T10 &v10, const T11 &v11, const T12 &v12
500#define TINYFORMAT_VARARGS_13 \
501 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
502 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
503 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
504#define TINYFORMAT_VARARGS_14 \
505 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
506 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
507 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
509#define TINYFORMAT_VARARGS_15 \
510 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
511 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
512 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
513 const T14 &v14, const T15 &v15
514#define TINYFORMAT_VARARGS_16 \
515 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
516 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
517 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
518 const T14 &v14, const T15 &v15, const T16 &v16
520#define TINYFORMAT_PASSARGS_1 v1
521#define TINYFORMAT_PASSARGS_2 v1, v2
522#define TINYFORMAT_PASSARGS_3 v1, v2, v3
523#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
524#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
525#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
526#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
527#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
528#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
529#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
530#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
531#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
532#define TINYFORMAT_PASSARGS_13 \
533 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
534#define TINYFORMAT_PASSARGS_14 \
535 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
536#define TINYFORMAT_PASSARGS_15 \
537 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
538#define TINYFORMAT_PASSARGS_16 \
539 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
541#define TINYFORMAT_PASSARGS_TAIL_1
542#define TINYFORMAT_PASSARGS_TAIL_2 , v2
543#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
544#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
545#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
546#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
547#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
548#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
549#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
550#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
551#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
552#define TINYFORMAT_PASSARGS_TAIL_12 \
553 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
554#define TINYFORMAT_PASSARGS_TAIL_13 \
555 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
556#define TINYFORMAT_PASSARGS_TAIL_14 \
557 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
558#define TINYFORMAT_PASSARGS_TAIL_15 \
559 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
560#define TINYFORMAT_PASSARGS_TAIL_16 \
561 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
563#define TINYFORMAT_FOREACH_ARGNUM(m) \
564 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) \
578 template <
typename T>
580 :
m_value(static_cast<const void *>(&value)),
583 void format(std::ostream &out,
const char *fmtBegin,
const char *fmtEnd,
597 template <
typename T>
599 formatImpl(std::ostream &out,
const char *fmtBegin,
const char *fmtEnd,
600 int ntrunc,
const void *value) {
602 *
static_cast<const T *
>(value));
605 template <
typename T>
612 const char *fmtEnd,
int ntrunc,
const void *value);
620 for (; *c >=
'0' && *c <=
'9'; ++c)
621 i = 10 * i + (*c -
'0');
633 int &argIndex,
int numArgs) {
634 if (*c >=
'0' && *c <=
'9') {
636 }
else if (*c ==
'*') {
639 if (positionalMode) {
643 "after a positional one");
644 if (pos >= 0 && pos < numArgs)
645 n = args[pos].
toInt();
648 "tinyformat: Positional argument out of range");
651 if (argIndex < numArgs)
652 n = args[argIndex++].
toInt();
655 "variable width or precision");
673 out.write(fmt, c - fmt);
675 }
else if (*c ==
'%') {
676 out.write(fmt, c - fmt);
677 if (*(c + 1) !=
'%')
return c;
720 bool &positionalMode,
721 bool &spacePadPositive,
722 int &ntrunc,
const char *fmtStart,
724 int &argIndex,
int numArgs) {
731 out.unsetf(std::ios::adjustfield | std::ios::basefield |
732 std::ios::floatfield | std::ios::showbase |
733 std::ios::boolalpha | std::ios::showpoint |
734 std::ios::showpos | std::ios::uppercase);
735 bool precisionSet =
false;
736 bool widthSet =
false;
738 const char *c = fmtStart + 1;
742 if (*c >=
'0' && *c <=
'9') {
743 const char tmpc = *c;
747 if (value > 0 && value <= numArgs)
748 argIndex = value - 1;
751 "tinyformat: Positional argument out of range");
753 positionalMode =
true;
754 }
else if (positionalMode) {
756 "after a positional one");
762 out.setf(std::ios::internal, std::ios::adjustfield);
770 }
else if (positionalMode) {
780 out.setf(std::ios::showpoint | std::ios::showbase);
784 if (!(out.flags() & std::ios::left)) {
788 out.setf(std::ios::internal, std::ios::adjustfield);
793 out.setf(std::ios::left, std::ios::adjustfield);
797 if (!(out.flags() & std::ios::showpos))
798 spacePadPositive =
true;
801 out.setf(std::ios::showpos);
802 spacePadPositive =
false;
818 out.setf(std::ios::left, std::ios::adjustfield);
832 precisionSet = precision >= 0;
833 if (precisionSet) out.precision(precision);
836 while (*c ==
'l' || *c ==
'h' || *c ==
'L' || *c ==
'j' || *c ==
'z' ||
843 bool intConversion =
false;
848 out.setf(std::ios::dec, std::ios::basefield);
849 intConversion =
true;
852 out.setf(std::ios::oct, std::ios::basefield);
853 intConversion =
true;
856 out.setf(std::ios::uppercase);
860 out.setf(std::ios::hex, std::ios::basefield);
861 intConversion =
true;
864 out.setf(std::ios::uppercase);
867 out.setf(std::ios::scientific, std::ios::floatfield);
868 out.setf(std::ios::dec, std::ios::basefield);
871 out.setf(std::ios::uppercase);
874 out.setf(std::ios::fixed, std::ios::floatfield);
877 out.setf(std::ios::uppercase);
887 out.setf(std::ios::fixed | std::ios::scientific,
888 std::ios::floatfield);
891 out.setf(std::ios::uppercase);
894 out.setf(std::ios::dec, std::ios::basefield);
896 out.flags(out.flags() & ~std::ios::floatfield);
902 if (precisionSet) ntrunc =
static_cast<int>(out.precision());
904 out.setf(std::ios::boolalpha);
909 "tinyformat: %n conversion spec not supported");
913 "terminated by end of string");
918 if (intConversion && precisionSet && !widthSet) {
923 out.width(out.precision() + widthExtra);
924 out.setf(std::ios::internal, std::ios::adjustfield);
934 std::streamsize origWidth = out.width();
935 std::streamsize origPrecision = out.precision();
936 std::ios::fmtflags origFlags = out.flags();
937 char origFill = out.fill();
942 bool positionalMode =
false;
947 if (!positionalMode && argIndex < numArgs) {
949 "specifiers in format string");
953 bool spacePadPositive =
false;
957 ntrunc, fmt, args, argIndex, numArgs);
961 if (argIndex >= numArgs) {
968 if (!spacePadPositive) {
969 arg.
format(out, fmt, fmtEnd, ntrunc);
975 std::ostringstream tmpStream;
976 tmpStream.copyfmt(out);
977 tmpStream.setf(std::ios::showpos);
978 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
979 std::string result = tmpStream.str();
980 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
981 if (result[i] ==
'+') result[i] =
' ';
985 if (!positionalMode) ++argIndex;
990 out.width(origWidth);
991 out.precision(origPrecision);
992 out.flags(origFlags);
1008 friend void vformat(std::ostream &out,
const char *fmt,
1024#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1025 template <
typename... Args>
1029 static_assert(
sizeof...(args) == N,
"Number of args must be N");
1033#define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
1035 template <TINYFORMAT_ARGTYPES(n)> \
1036 FormatListN(TINYFORMAT_VARARGS(n)) : FormatList(&m_formatterStore[0], n) { \
1037 TINYFORMAT_ASSERT(n == N); \
1038 init(0, TINYFORMAT_PASSARGS(n)); \
1041 template <TINYFORMAT_ARGTYPES(n)> \
1042 void init(int i, TINYFORMAT_VARARGS(n)) { \
1043 m_formatterStore[i] = FormatArg(v1); \
1044 init(i + 1 TINYFORMAT_PASSARGS_TAIL(n)); \
1048#undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1072#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1080template <
typename... Args>
1088 return detail::FormatListN<0>();
1090#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1091 template <TINYFORMAT_ARGTYPES(n)> \
1092 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) { \
1093 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1096#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1108#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1111template <
typename... Args>
1112void format(std::ostream &out,
const char *fmt,
const Args &...args) {
1118template <
typename... Args>
1119std::string
format(
const char *fmt,
const Args &...args) {
1120 std::ostringstream oss;
1121 format(oss, fmt, args...);
1126template <
typename... Args>
void printf(
const char *fmt,
const Args &...args) {
1127 format(std::cout, fmt, args...);
1130template <
typename... Args>
1132 format(std::cout, fmt, args...);
1138inline void format(std::ostream &out,
const char *fmt) {
1142inline std::string
format(
const char *fmt) {
1143 std::ostringstream oss;
1148inline void printf(
const char *fmt) {
1152inline void printfln(
const char *fmt) {
1157#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1159 template <TINYFORMAT_ARGTYPES(n)> \
1160 void format(std::ostream &out, const char *fmt, TINYFORMAT_VARARGS(n)) { \
1161 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1164 template <TINYFORMAT_ARGTYPES(n)> \
1165 std::string format(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1166 std::ostringstream oss; \
1167 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1171 template <TINYFORMAT_ARGTYPES(n)> \
1172 void printf(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1173 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1176 template <TINYFORMAT_ARGTYPES(n)> \
1177 void printfln(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1178 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1179 std::cout << '\n'; \
1183#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1188template <
typename... Args>
1189std::string
format(
const std::string &fmt,
const Args &...args) {
1190 std::ostringstream oss;
1191 format(oss, fmt.c_str(), args...);
1202#define strprintf tfm::format
Implement std::hash so RCUPtr can be used as a key for maps or sets.