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
151#ifndef TINYFORMAT_ASSERT
153# define TINYFORMAT_ASSERT(cond) assert(cond)
156#ifndef TINYFORMAT_ERROR
158# define TINYFORMAT_ERROR(reason) assert(0 && reason)
161#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
162# ifdef __GXX_EXPERIMENTAL_CXX0X__
163# define TINYFORMAT_USE_VARIADIC_TEMPLATES
167#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
170# define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
176# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
178# define TINYFORMAT_HIDDEN
192template <
unsigned num_params>
197 operator const char*() {
return fmt; }
213template <
typename T1,
typename T2>
218 struct fail {
char dummy[2]; };
227# pragma warning(push)
228# pragma warning(disable:4244)
229# pragma warning(disable:4267)
235 static const bool value =
236 sizeof(tryConvert(makeT1())) ==
sizeof(
succeed);
247template<
int n>
struct is_wchar<const wchar_t[n]> {};
253template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
260template<
typename T,
typename fmtT>
264 { out << static_cast<fmtT>(value); }
267#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
268template<typename T, bool convertible = is_convertible<T, int>::value>
269struct formatZeroIntegerWorkaround
271 static bool invoke(std::ostream& ,
const T& ) {
return false; }
274struct formatZeroIntegerWorkaround<
T,true>
276 static bool invoke(std::ostream&
out,
const T& value)
278 if (
static_cast<int>(value) == 0 &&
out.flags() & std::ios::showpos) {
289template<typename T, bool convertible = is_convertible<T,int>::value>
295 "integer for use as variable width or precision");
303 static int invoke(
const T& value) {
return static_cast<int>(value); }
310 std::ostringstream tmp;
312 std::string result = tmp.str();
313 out.write(result.c_str(), (std::min)(ntrunc,
static_cast<int>(result.size())));
315#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
316inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
318 std::streamsize len = 0; \
319 while (len < ntrunc && value[len] != 0) \
321 out.write(value, len); \
327#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
350 const char* fmtEnd,
int ntrunc,
const T& value)
352#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
365 if (canConvertToChar && *(fmtEnd-1) ==
'c')
367 else if (canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
369#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
370 else if (detail::formatZeroIntegerWorkaround<T>::invoke(
out, value)) ;
372 else if (ntrunc >= 0) {
383#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
384inline void formatValue(std::ostream& out, const char* , \
385 const char* fmtEnd, int , charType value) \
387 switch (*(fmtEnd-1)) { \
388 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
389 out << static_cast<int>(value); break; \
391 out << value; break; \
398#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
406#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_ ## n
407#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_ ## n
408#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_ ## n
409#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_ ## n
447#define TINYFORMAT_ARGTYPES_1 class T1
448#define TINYFORMAT_ARGTYPES_2 class T1, class T2
449#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
450#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
451#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
452#define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
453#define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
454#define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
455#define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
456#define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
457#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
458#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
459#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
460#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
461#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
462#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
464#define TINYFORMAT_VARARGS_1 const T1& v1
465#define TINYFORMAT_VARARGS_2 const T1& v1, const T2& v2
466#define TINYFORMAT_VARARGS_3 const T1& v1, const T2& v2, const T3& v3
467#define TINYFORMAT_VARARGS_4 const T1& v1, const T2& v2, const T3& v3, const T4& v4
468#define TINYFORMAT_VARARGS_5 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5
469#define TINYFORMAT_VARARGS_6 const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6
470#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
471#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
472#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
473#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
474#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
475#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
476#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
477#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
478#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
479#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
481#define TINYFORMAT_PASSARGS_1 v1
482#define TINYFORMAT_PASSARGS_2 v1, v2
483#define TINYFORMAT_PASSARGS_3 v1, v2, v3
484#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
485#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
486#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
487#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
488#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
489#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
490#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
491#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
492#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
493#define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
494#define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
495#define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
496#define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
498#define TINYFORMAT_PASSARGS_TAIL_1
499#define TINYFORMAT_PASSARGS_TAIL_2 , v2
500#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
501#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
502#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
503#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
504#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
505#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
506#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
507#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
508#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
509#define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
510#define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
511#define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
512#define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
513#define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
515#define TINYFORMAT_FOREACH_ARGNUM(m) \
516 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)
534 : m_value(static_cast<const void*>(&value)),
536 m_toIntImpl(&toIntImpl<
T>)
540 const char* fmtEnd,
int ntrunc)
const
544 m_formatImpl(
out, fmtBegin, fmtEnd, ntrunc, m_value);
551 return m_toIntImpl(m_value);
557 const char* fmtEnd,
int ntrunc,
const void* value)
559 formatValue(
out, fmtBegin, fmtEnd, ntrunc, *
static_cast<const T*
>(value));
568 const void* m_value{
nullptr};
569 void (*m_formatImpl)(std::ostream&
out,
const char* fmtBegin,
570 const char* fmtEnd,
int ntrunc,
const void* value){
nullptr};
571 int (*m_toIntImpl)(
const void* value){
nullptr};
580 for (;*c >=
'0' && *c <=
'9'; ++c)
581 i = 10*i + (*c -
'0');
592 int& argIndex,
int numArgs)
594 if (*c >=
'0' && *c <=
'9') {
597 else if (*c ==
'*') {
600 if (positionalMode) {
603 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
604 if (pos >= 0 && pos < numArgs)
605 n =
args[pos].toInt();
611 if (argIndex < numArgs)
612 n =
args[argIndex++].toInt();
614 TINYFORMAT_ERROR(
"tinyformat: Not enough arguments to read variable width or precision");
633 out.write(fmt, c - fmt);
636 else if (*c ==
'%') {
637 out.write(fmt, c - fmt);
681 bool& spacePadPositive,
682 int& ntrunc,
const char* fmtStart,
684 int& argIndex,
int numArgs)
692 out.unsetf(std::ios::adjustfield | std::ios::basefield |
693 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
694 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
695 bool precisionSet =
false;
696 bool widthSet =
false;
698 const char* c = fmtStart + 1;
702 if (*c >=
'0' && *c <=
'9') {
703 const char tmpc = *c;
707 if (value > 0 && value <= numArgs)
708 argIndex = value - 1;
712 positionalMode =
true;
714 else if (positionalMode) {
715 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
722 out.setf(std::ios::internal, std::ios::adjustfield);
731 else if (positionalMode) {
732 TINYFORMAT_ERROR(
"tinyformat: Non-positional argument used after a positional one");
740 out.setf(std::ios::showpoint | std::ios::showbase);
744 if (!(
out.flags() & std::ios::left)) {
748 out.setf(std::ios::internal, std::ios::adjustfield);
753 out.setf(std::ios::left, std::ios::adjustfield);
757 if (!(
out.flags() & std::ios::showpos))
758 spacePadPositive =
true;
761 out.setf(std::ios::showpos);
762 spacePadPositive =
false;
773 args, argIndex, numArgs);
778 out.setf(std::ios::left, std::ios::adjustfield);
789 args, argIndex, numArgs);
792 precisionSet = precision >= 0;
794 out.precision(precision);
797 while (*c ==
'l' || *c ==
'h' || *c ==
'L' ||
798 *c ==
'j' || *c ==
'z' || *c ==
't') {
804 bool intConversion =
false;
806 case 'u':
case 'd':
case 'i':
807 out.setf(std::ios::dec, std::ios::basefield);
808 intConversion =
true;
811 out.setf(std::ios::oct, std::ios::basefield);
812 intConversion =
true;
815 out.setf(std::ios::uppercase);
818 out.setf(std::ios::hex, std::ios::basefield);
819 intConversion =
true;
822 out.setf(std::ios::uppercase);
825 out.setf(std::ios::scientific, std::ios::floatfield);
826 out.setf(std::ios::dec, std::ios::basefield);
829 out.setf(std::ios::uppercase);
832 out.setf(std::ios::fixed, std::ios::floatfield);
835 out.setf(std::ios::uppercase);
844 out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
847 out.setf(std::ios::uppercase);
850 out.setf(std::ios::dec, std::ios::basefield);
852 out.flags(
out.flags() & ~std::ios::floatfield);
859 ntrunc =
static_cast<int>(
out.precision());
861 out.setf(std::ios::boolalpha);
869 "terminated by end of string");
874 if (intConversion && precisionSet && !widthSet) {
879 out.width(
out.precision() + widthExtra);
880 out.setf(std::ios::internal, std::ios::adjustfield);
893 std::streamsize origWidth =
out.width();
894 std::streamsize origPrecision =
out.precision();
895 std::ios::fmtflags origFlags =
out.flags();
896 char origFill =
out.fill();
900 bool positionalMode =
false;
905 if (!positionalMode && argIndex < numArgs) {
906 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
910 bool spacePadPositive =
false;
913 args, argIndex, numArgs);
916 if (argIndex >= numArgs) {
917 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
922 if (!spacePadPositive) {
930 std::ostringstream tmpStream;
931 tmpStream.copyfmt(
out);
932 tmpStream.setf(std::ios::showpos);
933 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
934 std::string result = tmpStream.str();
935 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
936 if (result[i] ==
'+')
947 out.width(origWidth);
948 out.precision(origPrecision);
949 out.flags(origFlags);
966 : m_args(
args), m_N(N) { }
987#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
988 template<
typename... Args>
992 {
static_assert(
sizeof...(args) == N,
"Number of args must be N"); }
995# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
997 template<TINYFORMAT_ARGTYPES(n)> \
998 FormatListN(TINYFORMAT_VARARGS(n)) \
999 : FormatList(&m_formatterStore[0], n) \
1000 { TINYFORMAT_ASSERT(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
1002 template<TINYFORMAT_ARGTYPES(n)> \
1003 void init(int i, TINYFORMAT_VARARGS(n)) \
1005 m_formatterStore[i] = FormatArg(v1); \
1006 init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
1010# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1015 &m_formatterStore[0]); }
1034#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1042template<
typename... Args>
1052 return detail::FormatListN<0>();
1054#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1055template<TINYFORMAT_ARGTYPES(n)> \
1056detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
1058 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1061#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1075#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1078template<
typename... Args>
1086template<
typename... Args>
1089 std::ostringstream oss;
1095template<
typename... Args>
1101template<
typename... Args>
1111inline void format(std::ostream&
out,
const char* fmt)
1116inline std::string
format(
const char* fmt)
1118 std::ostringstream oss;
1123inline void printf(
const char* fmt)
1128inline void printfln(
const char* fmt)
1134#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1136template<TINYFORMAT_ARGTYPES(n)> \
1137void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
1139 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1142template<TINYFORMAT_ARGTYPES(n)> \
1143std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
1145 std::ostringstream oss; \
1146 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1150template<TINYFORMAT_ARGTYPES(n)> \
1151void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
1153 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1156template<TINYFORMAT_ARGTYPES(n)> \
1157void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
1159 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1160 std::cout << '\n'; \
1164#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1172#define strprintf tfm::format
std::unique_ptr< interfaces::Init > init
#define T(expected, seed, data)