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
150#ifndef TINYFORMAT_ASSERT
152# define TINYFORMAT_ASSERT(cond) assert(cond)
155#ifndef TINYFORMAT_ERROR
157# define TINYFORMAT_ERROR(reason) assert(0 && reason)
160#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
161# ifdef __GXX_EXPERIMENTAL_CXX0X__
162# define TINYFORMAT_USE_VARIADIC_TEMPLATES
166#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
169# define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
175# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
177# define TINYFORMAT_HIDDEN
185template <
unsigned num_params>
190 operator const char*() {
return fmt; }
206template <
typename T1,
typename T2>
211 struct fail {
char dummy[2]; };
220# pragma warning(push)
221# pragma warning(disable:4244)
222# pragma warning(disable:4267)
228 static const bool value =
229 sizeof(tryConvert(makeT1())) ==
sizeof(
succeed);
240template<
int n>
struct is_wchar<const wchar_t[n]> {};
246template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
253template<
typename T,
typename fmtT>
257 { out << static_cast<fmtT>(value); }
260#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
261template<typename T, bool convertible = is_convertible<T, int>::value>
262struct formatZeroIntegerWorkaround
264 static bool invoke(std::ostream& ,
const T& ) {
return false; }
267struct formatZeroIntegerWorkaround<
T,true>
269 static bool invoke(std::ostream&
out,
const T& value)
271 if (
static_cast<int>(value) == 0 &&
out.flags() & std::ios::showpos) {
282template<typename T, bool convertible = is_convertible<T,int>::value>
288 "integer for use as variable width or precision");
296 static int invoke(
const T& value) {
return static_cast<int>(value); }
303 std::ostringstream tmp;
305 std::string result = tmp.str();
306 out.write(result.c_str(), (std::min)(ntrunc,
static_cast<int>(result.size())));
308#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
309inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
311 std::streamsize len = 0; \
312 while (len < ntrunc && value[len] != 0) \
314 out.write(value, len); \
320#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
343 const char* fmtEnd,
int ntrunc,
const T& value)
345#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
358 if (canConvertToChar && *(fmtEnd-1) ==
'c')
360 else if (canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
362#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
363 else if (detail::formatZeroIntegerWorkaround<T>::invoke(
out, value)) ;
365 else if (ntrunc >= 0) {
376#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
377inline void formatValue(std::ostream& out, const char* , \
378 const char* fmtEnd, int , charType value) \
380 switch (*(fmtEnd-1)) { \
381 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
382 out << static_cast<int>(value); break; \
384 out << value; break; \
391#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
399#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n
400#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n
401#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n
402#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n
440#define TINYFORMAT_ARGTYPES_1 class T1
441#define TINYFORMAT_ARGTYPES_2 class T1, class T2
442#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
443#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
444#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
445#define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
446#define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
447#define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
448#define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
449#define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
450#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
451#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
452#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
453#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
454#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
455#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
457#define TINYFORMAT_VARARGS_1 const T1& v1
458#define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2
459#define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3
460#define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4
461#define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5
462#define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6
463#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
464#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
465#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
466#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
467#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
468#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
469#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
470#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
471#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
472#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
474#define TINYFORMAT_PASSARGS_1 v1
475#define TINYFORMAT_PASSARGS_2 v1, v2
476#define TINYFORMAT_PASSARGS_3 v1, v2, v3
477#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
478#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
479#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
480#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
481#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
482#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
483#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
484#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
485#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
486#define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
487#define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
488#define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
489#define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
491#define TINYFORMAT_PASSARGS_TAIL_1
492#define TINYFORMAT_PASSARGS_TAIL_2 , v2
493#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
494#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
495#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
496#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
497#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
498#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
499#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
500#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
501#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
502#define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
503#define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
504#define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
505#define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
506#define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
508#define TINYFORMAT_FOREACH_ARGNUM(m) \
509 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)
527 : m_value(static_cast<const void*>(&value)),
529 m_toIntImpl(&toIntImpl<
T>)
533 const char* fmtEnd,
int ntrunc)
const
537 m_formatImpl(
out, fmtBegin, fmtEnd, ntrunc, m_value);
544 return m_toIntImpl(m_value);
550 const char* fmtEnd,
int ntrunc,
const void* value)
552 formatValue(
out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
561 const void* m_value{
nullptr};
562 void (*m_formatImpl)(std::ostream&
out,
const char* fmtBegin,
563 const char* fmtEnd,
int ntrunc,
const void* value){
nullptr};
564 int (*m_toIntImpl)(
const void* value){
nullptr};
573 for (;*c >=
'0' && *c <=
'9'; ++c)
574 i = 10*i + (*c -
'0');
585 int& argIndex,
int numArgs)
587 if (*c >=
'0' && *c <=
'9') {
590 else if (*c ==
'*') {
593 if (positionalMode) {
596 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
597 if (pos >= 0 && pos < numArgs)
598 n =
args[pos].toInt();
604 if (argIndex < numArgs)
605 n =
args[argIndex++].toInt();
607 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width or precision");
626 out.write(fmt, c - fmt);
629 else if (*c ==
'%') {
630 out.write(fmt, c - fmt);
674 bool& spacePadPositive,
675 int& ntrunc,
const char* fmtStart,
677 int& argIndex,
int numArgs)
685 out.unsetf(std::ios::adjustfield | std::ios::basefield |
686 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
687 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
688 bool precisionSet =
false;
689 bool widthSet =
false;
691 const char* c = fmtStart + 1;
695 if (*c >=
'0' && *c <=
'9') {
696 const char tmpc = *c;
700 if (value > 0 && value <= numArgs)
701 argIndex = value - 1;
705 positionalMode =
true;
707 else if (positionalMode) {
708 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
715 out.setf(std::ios::internal, std::ios::adjustfield);
724 else if (positionalMode) {
725 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
733 out.setf(std::ios::showpoint | std::ios::showbase);
737 if (!(
out.flags() & std::ios::left)) {
741 out.setf(std::ios::internal, std::ios::adjustfield);
746 out.setf(std::ios::left, std::ios::adjustfield);
750 if (!(
out.flags() & std::ios::showpos))
751 spacePadPositive =
true;
754 out.setf(std::ios::showpos);
755 spacePadPositive =
false;
766 args, argIndex, numArgs);
771 out.setf(std::ios::left, std::ios::adjustfield);
782 args, argIndex, numArgs);
785 precisionSet = precision >= 0;
787 out.precision(precision);
790 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
791 *c ==
'j' || *c ==
'z' || *c ==
't') {
797 bool intConversion =
false;
799 case 'u':
case 'd':
case 'i':
800 out.setf(std::ios::dec, std::ios::basefield);
801 intConversion =
true;
804 out.setf(std::ios::oct, std::ios::basefield);
805 intConversion =
true;
808 out.setf(std::ios::uppercase);
811 out.setf(std::ios::hex, std::ios::basefield);
812 intConversion =
true;
815 out.setf(std::ios::uppercase);
818 out.setf(std::ios::scientific, std::ios::floatfield);
819 out.setf(std::ios::dec, std::ios::basefield);
822 out.setf(std::ios::uppercase);
825 out.setf(std::ios::fixed, std::ios::floatfield);
828 out.setf(std::ios::uppercase);
837 out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
840 out.setf(std::ios::uppercase);
843 out.setf(std::ios::dec, std::ios::basefield);
845 out.flags(
out.flags() & ~std::ios::floatfield);
852 ntrunc =
static_cast<int>(
out.precision());
854 out.setf(std::ios::boolalpha);
862 "terminated by end of string");
867 if (intConversion && precisionSet && !widthSet) {
872 out.width(
out.precision() + widthExtra);
873 out.setf(std::ios::internal, std::ios::adjustfield);
886 std::streamsize origWidth =
out.width();
887 std::streamsize origPrecision =
out.precision();
888 std::ios::fmtflags origFlags =
out.flags();
889 char origFill =
out.fill();
893 bool positionalMode =
false;
898 if (!positionalMode && argIndex < numArgs) {
899 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
903 bool spacePadPositive =
false;
906 args, argIndex, numArgs);
909 if (argIndex >= numArgs) {
910 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
915 if (!spacePadPositive) {
923 std::ostringstream tmpStream;
924 tmpStream.copyfmt(
out);
925 tmpStream.setf(std::ios::showpos);
926 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
927 std::string result = tmpStream.str();
928 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
929 if (result[i] ==
'+')
940 out.width(origWidth);
941 out.precision(origPrecision);
942 out.flags(origFlags);
959 : m_args(
args), m_N(N) { }
980#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
981 template<
typename... Args>
985 {
static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
988# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
990 template<TINYFORMAT_ARGTYPES(n)> \
991 FormatListN(TINYFORMAT_VARARGS(n)) \
992 : FormatList(&m_formatterStore[0], n) \
993 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
995 template<TINYFORMAT_ARGTYPES(n)> \
996 void init(int i, TINYFORMAT_VARARGS(n)) \
998 m_formatterStore[i] = FormatArg(v1); \
999 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
1003# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1008 &m_formatterStore[0]); }
1027#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1035template<
typename... Args>
1045 return detail::FormatListN<0>();
1047#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1048template<TINYFORMAT_ARGTYPES(n)> \
1049detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
1051 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1054#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1068#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1071template<
typename... Args>
1079template<
typename... Args>
1082 std::ostringstream oss;
1088template<
typename... Args>
1094template<
typename... Args>
1104inline void format(std::ostream&
out,
const char* fmt)
1109inline std::string
format(
const char* fmt)
1111 std::ostringstream oss;
1116inline void printf(
const char* fmt)
1121inline void printfln(
const char* fmt)
1127#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1129template<TINYFORMAT_ARGTYPES(n)> \
1130void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1132 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1135template<TINYFORMAT_ARGTYPES(n)> \
1136std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1138 std::ostringstream oss; \
1139 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1143template<TINYFORMAT_ARGTYPES(n)> \
1144void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1146 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1149template<TINYFORMAT_ARGTYPES(n)> \
1150void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1152 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1153 std::cout << '\n'; \
1157#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1165#define strprintf tfm::format
std::unique_ptr< interfaces::Init > init
#define T(expected, seed, data)