115 #ifndef TINYFORMAT_H_INCLUDED
116 #define TINYFORMAT_H_INCLUDED
126 #define TINYFORMAT_ERROR(reasonString) throw std::runtime_error(reasonString)
130 #define TINYFORMAT_USE_VARIADIC_TEMPLATES
141 #ifndef TINYFORMAT_ERROR
142 # define TINYFORMAT_ERROR(reason) assert(0 && reason)
145 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
146 # ifdef __GXX_EXPERIMENTAL_CXX0X__
147 # define TINYFORMAT_USE_VARIADIC_TEMPLATES
151 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
154 # define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
160 # define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
162 # define TINYFORMAT_HIDDEN
171 template <
typename T1,
typename T2>
185 # pragma warning(push)
186 # pragma warning(disable:4244)
187 # pragma warning(disable:4267)
196 # pragma warning(pop)
205 template<
int n>
struct is_wchar<const wchar_t[n]> {};
211 template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
214 static void invoke(std::ostream& ,
const T& ) { assert(0); }
218 template<
typename T,
typename fmtT>
221 static void invoke(std::ostream& out,
const T& value)
222 { out << static_cast<fmtT>(value); }
225 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
226 template<typename T, bool convertible = is_convertible<T, int>::value>
227 struct formatZeroIntegerWorkaround
229 static bool invoke(std::ostream& ,
const T& ) {
return false; }
232 struct formatZeroIntegerWorkaround<T,true>
234 static bool invoke(std::ostream& out,
const T& value)
236 if (
static_cast<int>(value) == 0 && out.flags() & std::ios::showpos)
248 template<typename T, bool convertible = is_convertible<T,int>::value>
254 "integer for use as variable width or precision");
262 static int invoke(
const T& value) {
return static_cast<int>(value); }
269 std::ostringstream tmp;
271 std::string result = tmp.str();
272 out.write(result.c_str(), (std::min)(ntrunc,
static_cast<int>(result.size())));
274 #define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
275 inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
277 std::streamsize len = 0; \
278 while(len < ntrunc && value[len] != 0) \
280 out.write(value, len); \
286 #undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
309 const char* fmtEnd,
int ntrunc,
const T& value)
311 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
324 if(canConvertToChar && *(fmtEnd-1) ==
'c')
326 else if(canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
328 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
329 else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) ;
343 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
344 inline void formatValue(std::ostream& out, const char* , \
345 const char* fmtEnd, int , charType value) \
347 switch(*(fmtEnd-1)) \
349 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
350 out << static_cast<int>(value); break; \
352 out << value; break; \
359 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
367 #define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n
368 #define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n
369 #define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n
370 #define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n
408 #define TINYFORMAT_ARGTYPES_1 class T1
409 #define TINYFORMAT_ARGTYPES_2 class T1, class T2
410 #define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
411 #define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
412 #define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
413 #define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
414 #define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
415 #define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
416 #define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
417 #define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
418 #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
419 #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
420 #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
421 #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
422 #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
423 #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
425 #define TINYFORMAT_VARARGS_1 const T1& v1
426 #define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2
427 #define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3
428 #define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4
429 #define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5
430 #define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6
431 #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
432 #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
433 #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
434 #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
435 #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
436 #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
437 #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
438 #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
439 #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
440 #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
442 #define TINYFORMAT_PASSARGS_1 v1
443 #define TINYFORMAT_PASSARGS_2 v1, v2
444 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
445 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
446 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
447 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
448 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
449 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
450 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
451 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
452 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
453 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
454 #define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
455 #define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
456 #define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
457 #define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
459 #define TINYFORMAT_PASSARGS_TAIL_1
460 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
461 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
462 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
463 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
464 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
465 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
466 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
467 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
468 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
469 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
470 #define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
471 #define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
472 #define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
473 #define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
474 #define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
476 #define TINYFORMAT_FOREACH_ARGNUM(m) \
477 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)
495 :
m_value(static_cast<const void*>(&value)),
500 void format(std::ostream& out,
const char* fmtBegin,
501 const char* fmtEnd,
int ntrunc)
const
514 const char* fmtEnd,
int ntrunc,
const void* value)
516 formatValue(out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
527 const char* fmtEnd,
int ntrunc,
const void* value);
537 for(;*c >=
'0' && *c <=
'9'; ++c)
538 i = 10*i + (*c -
'0');
556 out.write(fmt, c - fmt);
559 out.write(fmt, c - fmt);
583 int& ntrunc,
const char* fmtStart,
585 int& argIndex,
int numFormatters)
589 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
597 out.unsetf(std::ios::adjustfield | std::ios::basefield |
598 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
599 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
600 bool precisionSet =
false;
601 bool widthSet =
false;
603 const char* c = fmtStart + 1;
610 out.setf(std::ios::showpoint | std::ios::showbase);
614 if(!(out.flags() & std::ios::left))
619 out.setf(std::ios::internal, std::ios::adjustfield);
624 out.setf(std::ios::left, std::ios::adjustfield);
628 if(!(out.flags() & std::ios::showpos))
629 spacePadPositive =
true;
632 out.setf(std::ios::showpos);
633 spacePadPositive =
false;
642 if(*c >=
'0' && *c <=
'9')
651 if(argIndex < numFormatters)
652 width = formatters[argIndex++].
toInt();
654 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width");
659 out.setf(std::ios::left, std::ios::adjustfield);
673 if(argIndex < numFormatters)
674 precision = formatters[argIndex++].
toInt();
676 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable precision");
680 if(*c >=
'0' && *c <=
'9')
685 out.precision(precision);
689 while(*c ==
'l' || *c ==
'h' || *c ==
'L' ||
690 *c ==
'j' || *c ==
'z' || *c ==
't')
695 bool intConversion =
false;
698 case 'u':
case 'd':
case 'i':
699 out.setf(std::ios::dec, std::ios::basefield);
700 intConversion =
true;
703 out.setf(std::ios::oct, std::ios::basefield);
704 intConversion =
true;
707 out.setf(std::ios::uppercase);
709 out.setf(std::ios::hex, std::ios::basefield);
710 intConversion =
true;
713 out.setf(std::ios::uppercase);
715 out.setf(std::ios::scientific, std::ios::floatfield);
716 out.setf(std::ios::dec, std::ios::basefield);
719 out.setf(std::ios::uppercase);
721 out.setf(std::ios::fixed, std::ios::floatfield);
724 out.setf(std::ios::uppercase);
726 out.setf(std::ios::dec, std::ios::basefield);
728 out.flags(out.flags() & ~std::ios::floatfield);
732 "are not supported");
739 ntrunc =
static_cast<int>(out.precision());
741 out.setf(std::ios::boolalpha);
749 "terminated by end of string");
754 if(intConversion && precisionSet && !widthSet)
760 out.width(out.precision() + widthExtra);
761 out.setf(std::ios::internal, std::ios::adjustfield);
774 std::streamsize origWidth = out.width();
775 std::streamsize origPrecision = out.precision();
776 std::ios::fmtflags origFlags = out.flags();
777 char origFill = out.fill();
779 for (
int argIndex = 0; argIndex < numFormatters; ++argIndex)
783 bool spacePadPositive =
false;
786 formatters, argIndex, numFormatters);
787 if (argIndex >= numFormatters)
793 const FormatArg& arg = formatters[argIndex];
795 if(!spacePadPositive)
796 arg.
format(out, fmt, fmtEnd, ntrunc);
803 std::ostringstream tmpStream;
804 tmpStream.copyfmt(out);
805 tmpStream.setf(std::ios::showpos);
806 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
807 std::string result = tmpStream.str();
808 for(
size_t i = 0, iend = result.size(); i < iend; ++i)
809 if(result[i] ==
'+') result[i] =
' ';
818 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
821 out.width(origWidth);
822 out.precision(origPrecision);
823 out.flags(origFlags);
842 friend void vformat(std::ostream& out,
const char* fmt,
861 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
862 template<
typename... Args>
866 { static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
869 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
871 template<TINYFORMAT_ARGTYPES(n)> \
872 FormatListN(TINYFORMAT_VARARGS(n)) \
873 : FormatList(&m_formatterStore[0], n) \
874 { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
876 template<TINYFORMAT_ARGTYPES(n)> \
877 void init(int i, TINYFORMAT_VARARGS(n)) \
879 m_formatterStore[i] = FormatArg(v1); \
880 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
884 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
903 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
911 template<
typename... Args>
921 return detail::FormatListN<0>();
923 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
924 template<TINYFORMAT_ARGTYPES(n)> \
925 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
927 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
930 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
944 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
947 template<
typename... Args>
948 void format(std::ostream& out,
const char* fmt,
const Args&... args)
955 template<
typename... Args>
956 std::string
format(
const char* fmt,
const Args&... args)
958 std::ostringstream oss;
959 format(oss, fmt, args...);
964 template<
typename... Args>
965 void printf(
const char* fmt,
const Args&... args)
967 format(std::cout, fmt, args...);
970 template<
typename... Args>
971 void printfln(
const char* fmt,
const Args&... args)
973 format(std::cout, fmt, args...);
979 inline void format(std::ostream& out,
const char* fmt)
984 inline std::string
format(
const char* fmt)
986 std::ostringstream oss;
991 inline void printf(
const char* fmt)
996 inline void printfln(
const char* fmt)
1002 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1004 template<TINYFORMAT_ARGTYPES(n)> \
1005 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1007 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1010 template<TINYFORMAT_ARGTYPES(n)> \
1011 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1013 std::ostringstream oss; \
1014 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1018 template<TINYFORMAT_ARGTYPES(n)> \
1019 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1021 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1024 template<TINYFORMAT_ARGTYPES(n)> \
1025 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1027 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1028 std::cout << '\n'; \
1032 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
1037 template<
typename... Args>
1038 std::string
format(
const std::string &fmt,
const Args&... args)
1040 std::ostringstream oss;
1041 format(oss, fmt.c_str(), args...);
1047 #define strprintf tfm::format