116 #ifndef TINYFORMAT_H_INCLUDED
117 #define TINYFORMAT_H_INCLUDED
141 #ifndef TINYFORMAT_ASSERT
142 # define TINYFORMAT_ASSERT(cond) assert(cond)
145 #ifndef TINYFORMAT_ERROR
146 # define TINYFORMAT_ERROR(reason) assert(0 && reason)
149 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
150 # ifdef __GXX_EXPERIMENTAL_CXX0X__
151 # define TINYFORMAT_USE_VARIADIC_TEMPLATES
155 #if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
158 # define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
164 # define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
166 # define TINYFORMAT_HIDDEN
175 template <
typename T1,
typename T2>
189 # pragma warning(push)
190 # pragma warning(disable:4244)
191 # pragma warning(disable:4267)
200 # pragma warning(pop)
209 template<
int n>
struct is_wchar<const wchar_t[n]> {};
215 template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
222 template<
typename T,
typename fmtT>
225 static void invoke(std::ostream& out,
const T& value)
226 { out << static_cast<fmtT>(value); }
229 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
230 template<typename T, bool convertible = is_convertible<T, int>::value>
231 struct formatZeroIntegerWorkaround
233 static bool invoke(std::ostream& ,
const T& ) {
return false; }
236 struct formatZeroIntegerWorkaround<T,true>
238 static bool invoke(std::ostream& out,
const T& value)
240 if (
static_cast<int>(value) == 0 && out.flags() & std::ios::showpos)
252 template<typename T, bool convertible = is_convertible<T,int>::value>
258 "integer for use as variable width or precision");
266 static int invoke(
const T& value) {
return static_cast<int>(value); }
273 std::ostringstream tmp;
275 std::string result = tmp.str();
276 out.write(result.c_str(), (
std::min)(ntrunc,
static_cast<int>(result.size())));
278 #define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
279 inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
281 std::streamsize len = 0; \
282 while(len < ntrunc && value[len] != 0) \
284 out.write(value, len); \
290 #undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
313 const char* fmtEnd,
int ntrunc,
const T& value)
315 #ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
328 if(canConvertToChar && *(fmtEnd-1) ==
'c')
330 else if(canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
332 #ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
333 else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) ;
347 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
348 inline void formatValue(std::ostream& out, const char* , \
349 const char* fmtEnd, int , charType value) \
351 switch(*(fmtEnd-1)) \
353 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
354 out << static_cast<int>(value); break; \
356 out << value; break; \
363 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
371 #define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n
372 #define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n
373 #define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n
374 #define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n
412 #define TINYFORMAT_ARGTYPES_1 class T1
413 #define TINYFORMAT_ARGTYPES_2 class T1, class T2
414 #define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
415 #define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
416 #define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
417 #define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
418 #define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
419 #define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
420 #define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
421 #define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
422 #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
423 #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
424 #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
425 #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
426 #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
427 #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
429 #define TINYFORMAT_VARARGS_1 const T1& v1
430 #define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2
431 #define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3
432 #define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4
433 #define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5
434 #define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6
435 #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
436 #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
437 #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
438 #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
439 #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
440 #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
441 #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
442 #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
443 #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
444 #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
446 #define TINYFORMAT_PASSARGS_1 v1
447 #define TINYFORMAT_PASSARGS_2 v1, v2
448 #define TINYFORMAT_PASSARGS_3 v1, v2, v3
449 #define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
450 #define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
451 #define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
452 #define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
453 #define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
454 #define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
455 #define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
456 #define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
457 #define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
458 #define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
459 #define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
460 #define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
461 #define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
463 #define TINYFORMAT_PASSARGS_TAIL_1
464 #define TINYFORMAT_PASSARGS_TAIL_2 , v2
465 #define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
466 #define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
467 #define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
468 #define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
469 #define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
470 #define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
471 #define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
472 #define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
473 #define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
474 #define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
475 #define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
476 #define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
477 #define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
478 #define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
480 #define TINYFORMAT_FOREACH_ARGNUM(m) \
481 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)
503 :
m_value(static_cast<const void*>(&value)),
508 void format(std::ostream& out,
const char* fmtBegin,
509 const char* fmtEnd,
int ntrunc)
const
526 const char* fmtEnd,
int ntrunc,
const void* value)
528 formatValue(out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
539 const char* fmtEnd,
int ntrunc,
const void* value);
549 for(;*c >=
'0' && *c <=
'9'; ++c)
550 i = 10*i + (*c -
'0');
568 out.write(fmt, c - fmt);
571 out.write(fmt, c - fmt);
595 int& ntrunc,
const char* fmtStart,
597 int& argIndex,
int numFormatters)
601 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
609 out.unsetf(std::ios::adjustfield | std::ios::basefield |
610 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
611 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
612 bool precisionSet =
false;
613 bool widthSet =
false;
615 const char* c = fmtStart + 1;
622 out.setf(std::ios::showpoint | std::ios::showbase);
626 if(!(out.flags() & std::ios::left))
631 out.setf(std::ios::internal, std::ios::adjustfield);
636 out.setf(std::ios::left, std::ios::adjustfield);
640 if(!(out.flags() & std::ios::showpos))
641 spacePadPositive =
true;
644 out.setf(std::ios::showpos);
645 spacePadPositive =
false;
654 if(*c >=
'0' && *c <=
'9')
663 if(argIndex < numFormatters)
664 width = formatters[argIndex++].
toInt();
666 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width");
671 out.setf(std::ios::left, std::ios::adjustfield);
685 if(argIndex < numFormatters)
686 precision = formatters[argIndex++].
toInt();
688 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable precision");
692 if(*c >=
'0' && *c <=
'9')
697 out.precision(precision);
701 while(*c ==
'l' || *c ==
'h' || *c ==
'L' ||
702 *c ==
'j' || *c ==
'z' || *c ==
't')
707 bool intConversion =
false;
710 case 'u':
case 'd':
case 'i':
711 out.setf(std::ios::dec, std::ios::basefield);
712 intConversion =
true;
715 out.setf(std::ios::oct, std::ios::basefield);
716 intConversion =
true;
719 out.setf(std::ios::uppercase);
722 out.setf(std::ios::hex, std::ios::basefield);
723 intConversion =
true;
726 out.setf(std::ios::uppercase);
729 out.setf(std::ios::scientific, std::ios::floatfield);
730 out.setf(std::ios::dec, std::ios::basefield);
733 out.setf(std::ios::uppercase);
736 out.setf(std::ios::fixed, std::ios::floatfield);
739 out.setf(std::ios::uppercase);
742 out.setf(std::ios::dec, std::ios::basefield);
744 out.flags(out.flags() & ~std::ios::floatfield);
748 "are not supported");
755 ntrunc =
static_cast<int>(out.precision());
757 out.setf(std::ios::boolalpha);
765 "terminated by end of string");
770 if(intConversion && precisionSet && !widthSet)
776 out.width(out.precision() + widthExtra);
777 out.setf(std::ios::internal, std::ios::adjustfield);
790 std::streamsize origWidth = out.width();
791 std::streamsize origPrecision = out.precision();
792 std::ios::fmtflags origFlags = out.flags();
793 char origFill = out.fill();
795 for (
int argIndex = 0; argIndex < numFormatters; ++argIndex)
799 bool spacePadPositive =
false;
802 formatters, argIndex, numFormatters);
803 if (argIndex >= numFormatters)
809 const FormatArg& arg = formatters[argIndex];
811 if(!spacePadPositive)
812 arg.
format(out, fmt, fmtEnd, ntrunc);
819 std::ostringstream tmpStream;
820 tmpStream.copyfmt(out);
821 tmpStream.setf(std::ios::showpos);
822 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
823 std::string result = tmpStream.str();
824 for(
size_t i = 0, iend = result.size(); i < iend; ++i)
825 if(result[i] ==
'+') result[i] =
' ';
834 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
837 out.width(origWidth);
838 out.precision(origPrecision);
839 out.flags(origFlags);
858 friend void vformat(std::ostream& out,
const char* fmt,
877 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
878 template<
typename... Args>
882 { static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
885 # define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
887 template<TINYFORMAT_ARGTYPES(n)> \
888 FormatListN(TINYFORMAT_VARARGS(n)) \
889 : FormatList(&m_formatterStore[0], n) \
890 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
892 template<TINYFORMAT_ARGTYPES(n)> \
893 void init(int i, TINYFORMAT_VARARGS(n)) \
895 m_formatterStore[i] = FormatArg(v1); \
896 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
900 # undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
919 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
927 template<
typename... Args>
928 detail::FormatListN<
sizeof...(Args)>
makeFormatList(
const Args&... args)
930 return detail::FormatListN<
sizeof...(args)>(args...);
939 #define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
940 template<TINYFORMAT_ARGTYPES(n)> \
941 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
943 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
946 #undef TINYFORMAT_MAKE_MAKEFORMATLIST
960 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
963 template<
typename... Args>
964 void format(std::ostream& out,
const char* fmt,
const Args&... args)
971 template<
typename... Args>
972 std::string
format(
const char* fmt,
const Args&... args)
974 std::ostringstream oss;
975 format(oss, fmt, args...);
980 template<
typename... Args>
981 void printf(
const char* fmt,
const Args&... args)
983 format(std::cout, fmt, args...);
986 template<
typename... Args>
987 void printfln(
const char* fmt,
const Args&... args)
989 format(std::cout, fmt, args...);
996 inline void format(std::ostream& out,
const char* fmt)
1003 std::ostringstream oss;
1019 #define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1021 template<TINYFORMAT_ARGTYPES(n)> \
1022 void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1024 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1027 template<TINYFORMAT_ARGTYPES(n)> \
1028 std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1030 std::ostringstream oss; \
1031 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1035 template<TINYFORMAT_ARGTYPES(n)> \
1036 void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1038 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1041 template<TINYFORMAT_ARGTYPES(n)> \
1042 void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1044 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1045 std::cout << '\n'; \
1049 #undef TINYFORMAT_MAKE_FORMAT_FUNCS
traits::enable_if< helpers::decays_to_ctype< typename std::iterator_traits< InputIterator >::value_type >::value, typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type min(InputIterator begin, InputIterator end)