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>
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)
514 :
m_value(static_cast<const void*>(&value)),
520 const char* fmtEnd,
int ntrunc)
const
537 const char* fmtEnd,
int ntrunc,
const void* value)
539 formatValue(
out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
550 const char* fmtEnd,
int ntrunc,
const void* value){
nullptr};
560 for (;*c >=
'0' && *c <=
'9'; ++c)
561 i = 10*i + (*c -
'0');
572 int& argIndex,
int numArgs)
574 if (*c >=
'0' && *c <=
'9') {
577 else if (*c ==
'*') {
580 if (positionalMode) {
583 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
584 if (pos >= 0 && pos < numArgs)
585 n =
args[pos].toInt();
591 if (argIndex < numArgs)
592 n =
args[argIndex++].toInt();
594 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width or precision");
613 out.write(fmt, c - fmt);
616 else if (*c ==
'%') {
617 out.write(fmt, c - fmt);
661 bool& spacePadPositive,
662 int& ntrunc,
const char* fmtStart,
664 int& argIndex,
int numArgs)
672 out.unsetf(std::ios::adjustfield | std::ios::basefield |
673 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
674 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
675 bool precisionSet =
false;
676 bool widthSet =
false;
678 const char* c = fmtStart + 1;
682 if (*c >=
'0' && *c <=
'9') {
683 const char tmpc = *c;
687 if (value > 0 && value <= numArgs)
688 argIndex = value - 1;
692 positionalMode =
true;
694 else if (positionalMode) {
695 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
702 out.setf(std::ios::internal, std::ios::adjustfield);
711 else if (positionalMode) {
712 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
720 out.setf(std::ios::showpoint | std::ios::showbase);
724 if (!(
out.flags() & std::ios::left)) {
728 out.setf(std::ios::internal, std::ios::adjustfield);
733 out.setf(std::ios::left, std::ios::adjustfield);
737 if (!(
out.flags() & std::ios::showpos))
738 spacePadPositive =
true;
741 out.setf(std::ios::showpos);
742 spacePadPositive =
false;
753 args, argIndex, numArgs);
758 out.setf(std::ios::left, std::ios::adjustfield);
769 args, argIndex, numArgs);
772 precisionSet = precision >= 0;
774 out.precision(precision);
777 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
778 *c ==
'j' || *c ==
'z' || *c ==
't') {
784 bool intConversion =
false;
786 case 'u':
case 'd':
case 'i':
787 out.setf(std::ios::dec, std::ios::basefield);
788 intConversion =
true;
791 out.setf(std::ios::oct, std::ios::basefield);
792 intConversion =
true;
795 out.setf(std::ios::uppercase);
798 out.setf(std::ios::hex, std::ios::basefield);
799 intConversion =
true;
802 out.setf(std::ios::uppercase);
805 out.setf(std::ios::scientific, std::ios::floatfield);
806 out.setf(std::ios::dec, std::ios::basefield);
809 out.setf(std::ios::uppercase);
812 out.setf(std::ios::fixed, std::ios::floatfield);
815 out.setf(std::ios::uppercase);
824 out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
827 out.setf(std::ios::uppercase);
830 out.setf(std::ios::dec, std::ios::basefield);
832 out.flags(
out.flags() & ~std::ios::floatfield);
839 ntrunc =
static_cast<int>(
out.precision());
841 out.setf(std::ios::boolalpha);
849 "terminated by end of string");
854 if (intConversion && precisionSet && !widthSet) {
859 out.width(
out.precision() + widthExtra);
860 out.setf(std::ios::internal, std::ios::adjustfield);
873 std::streamsize origWidth =
out.width();
874 std::streamsize origPrecision =
out.precision();
875 std::ios::fmtflags origFlags =
out.flags();
876 char origFill =
out.fill();
880 bool positionalMode =
false;
885 if (!positionalMode && argIndex < numArgs) {
886 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
890 bool spacePadPositive =
false;
893 args, argIndex, numArgs);
896 if (argIndex >= numArgs) {
897 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
902 if (!spacePadPositive) {
910 std::ostringstream tmpStream;
911 tmpStream.copyfmt(
out);
912 tmpStream.setf(std::ios::showpos);
913 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
914 std::string result = tmpStream.str();
915 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
916 if (result[i] ==
'+')
927 out.width(origWidth);
928 out.precision(origPrecision);
929 out.flags(origFlags);
967 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
968 template<
typename... Args>
972 { static_assert(
sizeof...(
args) == N,
"Number of args must be N"); }
975 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
977 template<TINYFORMAT_ARGTYPES(n)> \
978 FormatListN(TINYFORMAT_VARARGS(n)) \
979 : FormatList(&m_formatterStore[0], n) \
980 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
982 template<TINYFORMAT_ARGTYPES(n)> \
983 void init(int i, TINYFORMAT_VARARGS(n)) \
985 m_formatterStore[i] = FormatArg(v1); \
986 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
990 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1014 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1022 template<
typename... Args>
1032 return detail::FormatListN<0>();
1034 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1035 template<TINYFORMAT_ARGTYPES(n)> \
1036 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
1038 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1041 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
1055 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1058 template<
typename... Args>
1066 template<
typename... Args>
1069 std::ostringstream oss;
1075 template<
typename... Args>
1081 template<
typename... Args>
1091 inline void format(std::ostream&
out,
const char* fmt)
1096 inline std::string
format(
const char* fmt)
1098 std::ostringstream oss;
1103 inline void printf(
const char* fmt)
1108 inline void printfln(
const char* fmt)
1114 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1116 template<TINYFORMAT_ARGTYPES(n)> \
1117 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1119 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1122 template<TINYFORMAT_ARGTYPES(n)> \
1123 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1125 std::ostringstream oss; \
1126 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1130 template<TINYFORMAT_ARGTYPES(n)> \
1131 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1133 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1136 template<TINYFORMAT_ARGTYPES(n)> \
1137 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1139 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1140 std::cout << '\n'; \
1144 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1149 template<
typename... Args>
1152 std::ostringstream oss;
1161 #define strprintf tfm::format
std::unique_ptr< interfaces::Init > init
#define T(expected, seed, data)