124 #ifndef TINYFORMAT_H_INCLUDED
125 #define TINYFORMAT_H_INCLUDED
135 #define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
139 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
149 #ifndef TINYFORMAT_ASSERT
151 # define TINYFORMAT_ASSERT(cond) assert(cond)
154 #ifndef TINYFORMAT_ERROR
156 # define TINYFORMAT_ERROR(reason) assert(0 && reason)
159 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
160 # ifdef __GXX_EXPERIMENTAL_CXX0X__
161 # define TINYFORMAT_USE_VARIADIC_TEMPLATES
165 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
168 # define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
174 # define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
176 # define TINYFORMAT_HIDDEN
193 template <
typename T1,
typename T2>
207 # pragma warning(push)
208 # pragma warning(disable:4244)
209 # pragma warning(disable:4267)
218 # pragma warning(pop)
227 template<
int n>
struct is_wchar<const wchar_t[n]> {};
233 template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
240 template<
typename T,
typename fmtT>
243 static void invoke(std::ostream& out,
const T& value)
244 { out << static_cast<fmtT>(value); }
247 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
248 template<typename T, bool convertible = is_convertible<T, int>::value>
249 struct formatZeroIntegerWorkaround
251 static bool invoke(std::ostream& ,
const T& ) {
return false; }
254 struct formatZeroIntegerWorkaround<
T,true>
256 static bool invoke(std::ostream& out,
const T& value)
258 if (
static_cast<int>(value) == 0 && out.flags() & std::ios::showpos) {
269 template<typename T, bool convertible = is_convertible<T,int>::value>
275 "integer for use as variable width or precision");
283 static int invoke(
const T& value) {
return static_cast<int>(value); }
290 std::ostringstream tmp;
292 std::string result = tmp.str();
293 out.write(result.c_str(), (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) \
298 std::streamsize len = 0; \
299 while (len < ntrunc && value[len] != 0) \
301 out.write(value, len); \
307 #undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
330 const char* fmtEnd,
int ntrunc,
const T& value)
332 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
345 if (canConvertToChar && *(fmtEnd-1) ==
'c')
347 else if (canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
349 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
350 else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) ;
352 else if (ntrunc >= 0) {
363 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
364 inline void formatValue(std::ostream& out, const char* , \
365 const char* fmtEnd, int , charType value) \
367 switch (*(fmtEnd-1)) { \
368 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
369 out << static_cast<int>(value); break; \
371 out << value; break; \
378 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
386 #define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n
387 #define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n
388 #define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n
389 #define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n
427 #define TINYFORMAT_ARGTYPES_1 class T1
428 #define TINYFORMAT_ARGTYPES_2 class T1, class T2
429 #define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
430 #define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
431 #define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
432 #define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
433 #define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
434 #define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
435 #define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
436 #define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
437 #define TINYFORMAT_ARGTYPES_11 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11
438 #define TINYFORMAT_ARGTYPES_12 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12
439 #define TINYFORMAT_ARGTYPES_13 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13
440 #define TINYFORMAT_ARGTYPES_14 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14
441 #define TINYFORMAT_ARGTYPES_15 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15
442 #define TINYFORMAT_ARGTYPES_16 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16
444 #define TINYFORMAT_VARARGS_1 const T1& v1
445 #define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2
446 #define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3
447 #define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4
448 #define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5
449 #define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6
450 #define TINYFORMAT_VARARGS_7 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7
451 #define TINYFORMAT_VARARGS_8 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8
452 #define TINYFORMAT_VARARGS_9 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9
453 #define TINYFORMAT_VARARGS_10 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10
454 #define TINYFORMAT_VARARGS_11 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11
455 #define TINYFORMAT_VARARGS_12 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12
456 #define TINYFORMAT_VARARGS_13 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13
457 #define TINYFORMAT_VARARGS_14 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14
458 #define TINYFORMAT_VARARGS_15 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14, const T15& v15
459 #define TINYFORMAT_VARARGS_16 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8, const T9& v9, const T10& v10, const T11& v11, const T12& v12, const T13& v13, const T14& v14, const T15& v15, const T16& v16
461 #define TINYFORMAT_PASSARGS_1 v1
462 #define TINYFORMAT_PASSARGS_2 v1, v2
463 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
464 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
465 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
466 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
467 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
468 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
469 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
470 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
471 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
472 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
473 #define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
474 #define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
475 #define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
476 #define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
478 #define TINYFORMAT_PASSARGS_TAIL_1
479 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
480 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
481 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
482 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
483 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
484 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
485 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
486 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
487 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
488 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
489 #define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
490 #define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
491 #define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
492 #define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
493 #define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
495 #define TINYFORMAT_FOREACH_ARGNUM(m) \
496 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) m(15) m(16)
515 :
m_value(static_cast<const void*>(&value)),
520 void format(std::ostream& out,
const char* fmtBegin,
521 const char* fmtEnd,
int ntrunc)
const
538 const char* fmtEnd,
int ntrunc,
const void* value)
540 formatValue(out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
551 const char* fmtEnd,
int ntrunc,
const void* value){
nullptr};
561 for (;*c >=
'0' && *c <=
'9'; ++c)
562 i = 10*i + (*c -
'0');
573 int& argIndex,
int numArgs)
575 if (*c >=
'0' && *c <=
'9') {
578 else if (*c ==
'*') {
581 if (positionalMode) {
584 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
585 if (pos >= 0 && pos < numArgs)
586 n =
args[pos].toInt();
592 if (argIndex < numArgs)
593 n =
args[argIndex++].toInt();
595 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width or precision");
614 out.write(fmt, c - fmt);
617 else if (*c ==
'%') {
618 out.write(fmt, c - fmt);
662 bool& spacePadPositive,
663 int& ntrunc,
const char* fmtStart,
665 int& argIndex,
int numArgs)
673 out.unsetf(std::ios::adjustfield | std::ios::basefield |
674 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
675 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
676 bool precisionSet =
false;
677 bool widthSet =
false;
679 const char* c = fmtStart + 1;
683 if (*c >=
'0' && *c <=
'9') {
684 const char tmpc = *c;
688 if (value > 0 && value <= numArgs)
689 argIndex = value - 1;
693 positionalMode =
true;
695 else if (positionalMode) {
696 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
703 out.setf(std::ios::internal, std::ios::adjustfield);
712 else if (positionalMode) {
713 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
721 out.setf(std::ios::showpoint | std::ios::showbase);
725 if (!(out.flags() & std::ios::left)) {
729 out.setf(std::ios::internal, std::ios::adjustfield);
734 out.setf(std::ios::left, std::ios::adjustfield);
738 if (!(out.flags() & std::ios::showpos))
739 spacePadPositive =
true;
742 out.setf(std::ios::showpos);
743 spacePadPositive =
false;
754 args, argIndex, numArgs);
759 out.setf(std::ios::left, std::ios::adjustfield);
770 args, argIndex, numArgs);
773 precisionSet = precision >= 0;
775 out.precision(precision);
778 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
779 *c ==
'j' || *c ==
'z' || *c ==
't') {
785 bool intConversion =
false;
787 case 'u':
case 'd':
case 'i':
788 out.setf(std::ios::dec, std::ios::basefield);
789 intConversion =
true;
792 out.setf(std::ios::oct, std::ios::basefield);
793 intConversion =
true;
796 out.setf(std::ios::uppercase);
799 out.setf(std::ios::hex, std::ios::basefield);
800 intConversion =
true;
803 out.setf(std::ios::uppercase);
806 out.setf(std::ios::scientific, std::ios::floatfield);
807 out.setf(std::ios::dec, std::ios::basefield);
810 out.setf(std::ios::uppercase);
813 out.setf(std::ios::fixed, std::ios::floatfield);
816 out.setf(std::ios::uppercase);
825 out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
828 out.setf(std::ios::uppercase);
831 out.setf(std::ios::dec, std::ios::basefield);
833 out.flags(out.flags() & ~std::ios::floatfield);
840 ntrunc =
static_cast<int>(out.precision());
842 out.setf(std::ios::boolalpha);
850 "terminated by end of string");
855 if (intConversion && precisionSet && !widthSet) {
860 out.width(out.precision() + widthExtra);
861 out.setf(std::ios::internal, std::ios::adjustfield);
874 std::streamsize origWidth = out.width();
875 std::streamsize origPrecision = out.precision();
876 std::ios::fmtflags origFlags = out.flags();
877 char origFill = out.fill();
881 bool positionalMode =
false;
886 if (!positionalMode && argIndex < numArgs) {
887 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
891 bool spacePadPositive =
false;
894 args, argIndex, numArgs);
897 if (argIndex >= numArgs) {
898 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
903 if (!spacePadPositive) {
904 arg.
format(out, fmt, fmtEnd, ntrunc);
911 std::ostringstream tmpStream;
912 tmpStream.copyfmt(out);
913 tmpStream.setf(std::ios::showpos);
914 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
915 std::string result = tmpStream.str();
916 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
917 if (result[i] ==
'+')
928 out.width(origWidth);
929 out.precision(origPrecision);
930 out.flags(origFlags);
949 friend void vformat(std::ostream& out,
const char* fmt,
968 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
969 template<
typename... Args>
973 { static_assert(
sizeof...(
args) == N,
"Number of args must be N"); }
976 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
978 template<TINYFORMAT_ARGTYPES(n)> \
979 FormatListN(TINYFORMAT_VARARGS(n)) \
980 : FormatList(&m_formatterStore[0], n) \
981 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
983 template<TINYFORMAT_ARGTYPES(n)> \
984 void init(int i, TINYFORMAT_VARARGS(n)) \
986 m_formatterStore[i] = FormatArg(v1); \
987 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
991 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1015 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1023 template<
typename... Args>
1033 return detail::FormatListN<0>();
1035 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1036 template<TINYFORMAT_ARGTYPES(n)> \
1037 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
1039 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1042 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
1056 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1059 template<
typename... Args>
1060 void format(std::ostream& out,
const char* fmt,
const Args&...
args)
1067 template<
typename... Args>
1070 std::ostringstream oss;
1076 template<
typename... Args>
1082 template<
typename... Args>
1092 inline void format(std::ostream& out,
const char* fmt)
1097 inline std::string
format(
const char* fmt)
1099 std::ostringstream oss;
1104 inline void printf(
const char* fmt)
1109 inline void printfln(
const char* fmt)
1115 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1117 template<TINYFORMAT_ARGTYPES(n)> \
1118 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1120 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1123 template<TINYFORMAT_ARGTYPES(n)> \
1124 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1126 std::ostringstream oss; \
1127 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1131 template<TINYFORMAT_ARGTYPES(n)> \
1132 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1134 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1137 template<TINYFORMAT_ARGTYPES(n)> \
1138 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1140 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1141 std::cout << '\n'; \
1145 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1150 template<
typename... Args>
1153 std::ostringstream oss;
1162 #define strprintf tfm::format
std::unique_ptr< interfaces::Init > init
#define T(expected, seed, data)