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>
198 struct fail {
char dummy[2]; };
201 static fail tryConvert(...);
202 static succeed tryConvert(
const T2&);
203 static const T1& makeT1();
207 # pragma warning(push) 208 # pragma warning(disable:4244) 209 # pragma warning(disable:4267) 215 static const bool value =
216 sizeof(tryConvert(makeT1())) ==
sizeof(
succeed);
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) {
265 #endif // TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND 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) 518 : m_value(static_cast<const void*>(&value)),
520 m_toIntImpl(&toIntImpl<T>)
523 void format(std::ostream& out,
const char* fmtBegin,
524 const char* fmtEnd,
int ntrunc)
const 528 m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
535 return m_toIntImpl(m_value);
541 const char* fmtEnd,
int ntrunc,
const void* value)
543 formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));
553 void (*m_formatImpl)(std::ostream& out,
const char* fmtBegin,
554 const char* fmtEnd,
int ntrunc,
const void* value);
555 int (*m_toIntImpl)(
const void* value);
564 for (;*c >=
'0' && *c <=
'9'; ++c)
565 i = 10*i + (*c -
'0');
576 int& argIndex,
int numArgs)
578 if (*c >=
'0' && *c <=
'9') {
581 else if (*c ==
'*') {
584 if (positionalMode) {
587 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
588 if (pos >= 0 && pos < numArgs)
589 n = args[pos].
toInt();
595 if (argIndex < numArgs)
596 n = args[argIndex++].
toInt();
598 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width or precision");
617 out.write(fmt, c - fmt);
620 else if (*c ==
'%') {
621 out.write(fmt, c - fmt);
665 bool& spacePadPositive,
666 int& ntrunc,
const char* fmtStart,
668 int& argIndex,
int numArgs)
676 out.unsetf(std::ios::adjustfield | std::ios::basefield |
677 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
678 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
679 bool precisionSet =
false;
680 bool widthSet =
false;
682 const char* c = fmtStart + 1;
686 if (*c >=
'0' && *c <=
'9') {
687 const char tmpc = *c;
691 if (value > 0 && value <= numArgs)
692 argIndex = value - 1;
696 positionalMode =
true;
698 else if (positionalMode) {
699 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
706 out.setf(std::ios::internal, std::ios::adjustfield);
715 else if (positionalMode) {
716 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
724 out.setf(std::ios::showpoint | std::ios::showbase);
728 if (!(out.flags() & std::ios::left)) {
732 out.setf(std::ios::internal, std::ios::adjustfield);
737 out.setf(std::ios::left, std::ios::adjustfield);
741 if (!(out.flags() & std::ios::showpos))
742 spacePadPositive =
true;
745 out.setf(std::ios::showpos);
746 spacePadPositive =
false;
757 args, argIndex, numArgs);
762 out.setf(std::ios::left, std::ios::adjustfield);
773 args, argIndex, numArgs);
776 precisionSet = precision >= 0;
778 out.precision(precision);
781 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
782 *c ==
'j' || *c ==
'z' || *c ==
't') {
788 bool intConversion =
false;
790 case 'u':
case 'd':
case 'i':
791 out.setf(std::ios::dec, std::ios::basefield);
792 intConversion =
true;
795 out.setf(std::ios::oct, std::ios::basefield);
796 intConversion =
true;
799 out.setf(std::ios::uppercase);
802 out.setf(std::ios::hex, std::ios::basefield);
803 intConversion =
true;
806 out.setf(std::ios::uppercase);
809 out.setf(std::ios::scientific, std::ios::floatfield);
810 out.setf(std::ios::dec, std::ios::basefield);
813 out.setf(std::ios::uppercase);
816 out.setf(std::ios::fixed, std::ios::floatfield);
819 out.setf(std::ios::uppercase);
828 out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
831 out.setf(std::ios::uppercase);
834 out.setf(std::ios::dec, std::ios::basefield);
836 out.flags(out.flags() & ~
std::ios::floatfield);
843 ntrunc =
static_cast<int>(out.precision());
845 out.setf(std::ios::boolalpha);
853 "terminated by end of string");
858 if (intConversion && precisionSet && !widthSet) {
863 out.width(out.precision() + widthExtra);
864 out.setf(std::ios::internal, std::ios::adjustfield);
877 std::streamsize origWidth = out.width();
878 std::streamsize origPrecision = out.precision();
879 std::ios::fmtflags origFlags = out.flags();
880 char origFill = out.fill();
884 bool positionalMode =
false;
889 if (!positionalMode && argIndex < numArgs) {
890 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
894 bool spacePadPositive =
false;
897 args, argIndex, numArgs);
900 if (argIndex >= numArgs) {
901 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
906 if (!spacePadPositive) {
907 arg.
format(out, fmt, fmtEnd, ntrunc);
914 std::ostringstream tmpStream;
915 tmpStream.copyfmt(out);
916 tmpStream.setf(std::ios::showpos);
917 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
918 std::string result = tmpStream.str();
919 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
920 if (result[i] ==
'+')
931 out.width(origWidth);
932 out.precision(origPrecision);
933 out.flags(origFlags);
950 : m_args(args), m_N(N) { }
952 friend void vformat(std::ostream& out,
const char* fmt,
971 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES 972 template<
typename... Args>
976 { static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
977 #else // C++98 version 979 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \ 981 template<TINYFORMAT_ARGTYPES(n)> \ 982 FormatListN(TINYFORMAT_VARARGS(n)) \ 983 : FormatList(&m_formatterStore[0], n) \ 984 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \ 986 template<TINYFORMAT_ARGTYPES(n)> \ 987 void init(int i, TINYFORMAT_VARARGS(n)) \ 989 m_formatterStore[i] = FormatArg(v1); \ 990 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \ 994 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR 999 &m_formatterStore[0]); }
1017 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES 1025 template<
typename... Args>
1031 #else // C++98 version 1037 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \ 1038 template<TINYFORMAT_ARGTYPES(n)> \ 1039 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \ 1041 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \ 1044 #undef TINYFORMAT_MAKE_MAKEFORMATLIST 1052 inline void vformat(std::ostream& out,
const char* fmt, FormatListRef list)
1058 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES 1061 template<
typename... Args>
1062 void format(std::ostream& out,
const char* fmt,
const Args&... args)
1069 template<
typename... Args>
1070 std::string
format(
const char* fmt,
const Args&... args)
1072 std::ostringstream oss;
1073 format(oss, fmt, args...);
1078 template<
typename... Args>
1079 void printf(
const char* fmt,
const Args&... args)
1081 format(std::cout, fmt, args...);
1084 template<
typename... Args>
1087 format(std::cout, fmt, args...);
1092 #else // C++98 version 1094 inline void format(std::ostream& out,
const char* fmt)
1099 inline std::string
format(
const char* fmt)
1101 std::ostringstream oss;
1106 inline void printf(
const char* fmt)
1111 inline void printfln(
const char* fmt)
1117 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \ 1119 template<TINYFORMAT_ARGTYPES(n)> \ 1120 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \ 1122 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \ 1125 template<TINYFORMAT_ARGTYPES(n)> \ 1126 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \ 1128 std::ostringstream oss; \ 1129 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \ 1133 template<TINYFORMAT_ARGTYPES(n)> \ 1134 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \ 1136 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ 1139 template<TINYFORMAT_ARGTYPES(n)> \ 1140 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \ 1142 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \ 1143 std::cout << '\n'; \ 1147 #undef TINYFORMAT_MAKE_FORMAT_FUNCS 1152 template<
typename... Args>
1153 std::string
format(
const std::string &fmt,
const Args&... args)
1155 std::ostringstream oss;
1156 format(oss, fmt.c_str(), args...);
1164 #define strprintf tfm::format 1166 #endif // TINYFORMAT_H_INCLUDED