115 #ifndef TINYFORMAT_H_INCLUDED
116 #define TINYFORMAT_H_INCLUDED
128 #define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
132 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
143 #ifndef TINYFORMAT_ERROR
144 #define TINYFORMAT_ERROR(reason) assert(0 && reason)
147 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
148 #ifdef __GXX_EXPERIMENTAL_CXX0X__
149 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
153 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
156 #define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
162 # define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
164 # define TINYFORMAT_HIDDEN
181 template <
typename T1,
typename T2>
199 #pragma warning(push)
200 #pragma warning(disable : 4244)
201 #pragma warning(disable : 4267)
216 template <
typename T>
236 template <typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
238 static void invoke(std::ostream& ,
const T& ) { assert(0); }
242 template <
typename T,
typename fmtT>
244 static void invoke(std::ostream& out,
const T& value)
246 out << static_cast<fmtT>(value);
250 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
251 template <typename T, bool convertible = is_convertible<T, int>::value>
252 struct formatZeroIntegerWorkaround {
253 static bool invoke(std::ostream& ,
const T& ) {
return false; }
255 template <
typename T>
256 struct formatZeroIntegerWorkaround<
T,
true> {
257 static bool invoke(std::ostream& out,
const T& value)
259 if (
static_cast<int>(value) == 0 && out.flags() & std::ios::showpos) {
270 template <typename T, bool convertible = is_convertible<T, int>::value>
275 "integer for use as variable width or precision");
280 template <
typename T>
282 static int invoke(
const T& value) {
return static_cast<int>(value); }
289 std::ostringstream tmp;
291 std::string result = tmp.str();
292 out.write(result.c_str(), (std::min)(ntrunc,
static_cast<int>(result.size())));
294 #define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
295 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
323 template <
typename T>
325 const char* fmtEnd,
int ntrunc,
const T& value)
327 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
340 if (canConvertToChar && *(fmtEnd - 1) ==
'c')
342 else if (canConvertToVoidPtr && *(fmtEnd - 1) ==
'p')
344 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
345 else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) ;
359 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
360 inline void formatValue(std::ostream& out, const char* , \
361 const char* fmtEnd, int , charType value) \
363 switch (*(fmtEnd - 1)) { \
370 out << static_cast<int>(value); \
381 #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 class T1, class T2, class T3, class T4, class T5, class T6
436 #define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
437 #define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
438 #define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
439 #define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
440 #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
441 #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
442 #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
443 #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
444 #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
445 #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
447 #define TINYFORMAT_VARARGS_1 const T1& v1
448 #define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
449 #define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
450 #define TINYFORMAT_VARARGS_4 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
451 #define TINYFORMAT_VARARGS_5 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
452 #define TINYFORMAT_VARARGS_6 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6
453 #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
454 #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
455 #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
456 #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
457 #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
458 #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
459 #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
460 #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
461 #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
462 #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
464 #define TINYFORMAT_PASSARGS_1 v1
465 #define TINYFORMAT_PASSARGS_2 v1, v2
466 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
467 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
468 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
469 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
470 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
471 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
472 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
473 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
474 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
475 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
476 #define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
477 #define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
478 #define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
479 #define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
481 #define TINYFORMAT_PASSARGS_TAIL_1
482 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
483 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
484 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
485 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
486 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
487 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
488 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
489 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
490 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
491 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
492 #define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
493 #define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
494 #define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
495 #define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
496 #define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
498 #define TINYFORMAT_FOREACH_ARGNUM(m) \
499 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)
516 :
m_value(static_cast<const void*>(&value)),
521 void format(std::ostream& out,
const char* fmtBegin,
522 const char* fmtEnd,
int ntrunc)
const
535 const char* fmtEnd,
int ntrunc,
const void* value)
537 formatValue(out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
540 template <
typename T>
548 const char* fmtEnd,
int ntrunc,
const void* value);
558 for(;*c >=
'0' && *c <=
'9'; ++c)
559 i = 10*i + (*c -
'0');
576 out.write(fmt, c - fmt);
579 out.write(fmt, c - fmt);
603 int& ntrunc,
const char* fmtStart,
605 int& argIndex,
int numFormatters)
607 if (*fmtStart !=
'%') {
608 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
616 out.unsetf(std::ios::adjustfield | std::ios::basefield |
617 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
618 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
619 bool precisionSet =
false;
620 bool widthSet =
false;
622 const char* c = fmtStart + 1;
627 out.setf(std::ios::showpoint | std::ios::showbase);
631 if (!(out.flags() & std::ios::left)) {
635 out.setf(std::ios::internal, std::ios::adjustfield);
640 out.setf(std::ios::left, std::ios::adjustfield);
644 if (!(out.flags() & std::ios::showpos))
645 spacePadPositive =
true;
648 out.setf(std::ios::showpos);
649 spacePadPositive =
false;
658 if (*c >=
'0' && *c <=
'9') {
665 if(argIndex < numFormatters)
666 width = formatters[argIndex++].
toInt();
668 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width");
672 out.setf(std::ios::left, std::ios::adjustfield);
684 if(argIndex < numFormatters)
685 precision = formatters[argIndex++].
toInt();
687 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable precision");
689 if (*c >=
'0' && *c <=
'9')
694 out.precision(precision);
698 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
699 *c ==
'j' || *c ==
'z' || *c ==
't')
704 bool intConversion =
false;
709 out.setf(std::ios::dec, std::ios::basefield);
710 intConversion =
true;
713 out.setf(std::ios::oct, std::ios::basefield);
714 intConversion =
true;
717 out.setf(std::ios::uppercase);
720 out.setf(std::ios::hex, std::ios::basefield);
721 intConversion =
true;
724 out.setf(std::ios::uppercase);
726 out.setf(std::ios::scientific, std::ios::floatfield);
727 out.setf(std::ios::dec, std::ios::basefield);
730 out.setf(std::ios::uppercase);
732 out.setf(std::ios::fixed, std::ios::floatfield);
735 out.setf(std::ios::uppercase);
737 out.setf(std::ios::dec, std::ios::basefield);
739 out.flags(out.flags() & ~std::ios::floatfield);
744 "are not supported");
751 ntrunc =
static_cast<int>(out.precision());
753 out.setf(std::ios::boolalpha);
761 "terminated by end of string");
766 if (intConversion && precisionSet && !widthSet) {
771 out.width(out.precision() + widthExtra);
772 out.setf(std::ios::internal, std::ios::adjustfield);
785 std::streamsize origWidth = out.width();
786 std::streamsize origPrecision = out.precision();
787 std::ios::fmtflags origFlags = out.flags();
788 char origFill = out.fill();
790 for (
int argIndex = 0; argIndex < numFormatters; ++argIndex)
794 bool spacePadPositive =
false;
797 formatters, argIndex, numFormatters);
798 if (argIndex >= numFormatters)
804 const FormatArg& arg = formatters[argIndex];
806 if(!spacePadPositive)
807 arg.
format(out, fmt, fmtEnd, ntrunc);
814 std::ostringstream tmpStream;
815 tmpStream.copyfmt(out);
816 tmpStream.setf(std::ios::showpos);
817 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
818 std::string result = tmpStream.str();
819 for(
size_t i = 0, iend = result.size(); i < iend; ++i)
820 if(result[i] ==
'+') result[i] =
' ';
829 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
832 out.width(origWidth);
833 out.precision(origPrecision);
834 out.flags(origFlags);
853 friend void vformat(std::ostream& out,
const char* fmt,
872 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
873 template<
typename... Args>
877 { static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
880 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
882 template<TINYFORMAT_ARGTYPES(n)> \
883 explicit FormatListN(TINYFORMAT_VARARGS(n)) \
884 : FormatList(&m_formatterStore[0], n) \
885 { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
887 template<TINYFORMAT_ARGTYPES(n)> \
888 void init(int i, TINYFORMAT_VARARGS(n)) \
890 m_formatterStore[i] = FormatArg(v1); \
891 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
895 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
913 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
921 template<
typename... Args>
931 return detail::FormatListN<0>();
933 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
934 template<TINYFORMAT_ARGTYPES(n)> \
935 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
937 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
940 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
954 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
957 template<
typename... Args>
958 void format(std::ostream& out,
const char* fmt,
const Args&... args)
965 template<
typename... Args>
966 std::string
format(
const char* fmt,
const Args&... args)
968 std::ostringstream oss;
969 format(oss, fmt, args...);
974 template<
typename... Args>
975 void printf(
const char* fmt,
const Args&... args)
977 format(std::cout, fmt, args...);
980 template<
typename... Args>
981 void printfln(
const char* fmt,
const Args&... args)
983 format(std::cout, fmt, args...);
989 inline void format(std::ostream& out,
const char* fmt)
994 inline std::string
format(
const char* fmt)
996 std::ostringstream oss;
1001 inline void printf(
const char* fmt)
1006 inline void printfln(
const char* fmt)
1012 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1014 template <TINYFORMAT_ARGTYPES(n)> \
1015 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1017 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1020 template <TINYFORMAT_ARGTYPES(n)> \
1021 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1023 std::ostringstream oss; \
1024 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1028 template <TINYFORMAT_ARGTYPES(n)> \
1029 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1031 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1034 template <TINYFORMAT_ARGTYPES(n)> \
1035 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1037 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1038 std::cout << '\n'; \
1042 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1046 template<
typename... Args>
1047 std::string
format(
const std::string &fmt,
const Args&... args)
1049 std::ostringstream oss;
1050 format(oss, fmt.c_str(), args...);
1056 #define strprintf tfm::format
#define T(expected, seed, data)