125#ifndef TINYFORMAT_H_INCLUDED
126#define TINYFORMAT_H_INCLUDED
136#define TINYFORMAT_ERROR(reasonString) \
137 throw tinyformat::format_error(reasonString)
141#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) && \
162 !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
163#ifdef __GXX_EXPERIMENTAL_CXX0X__
164#define TINYFORMAT_USE_VARIADIC_TEMPLATES
168#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
171#define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
177#define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
179#define TINYFORMAT_HIDDEN
212#pragma warning(disable : 4244)
213#pragma warning(disable : 4267)
232 template <
int n>
struct is_wchar<const wchar_t[n]> {};
237 template <
typename T,
typename fmtT,
240 static void invoke(std::ostream & ,
const T & ) {
246 template <
typename T,
typename fmtT>
249 out << static_cast<fmtT>(value);
253#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
254 template <typename T, bool convertible = is_convertible<T, int>::value>
255 struct formatZeroIntegerWorkaround {
256 static bool invoke(std::ostream & ,
const T & ) {
260 template <
typename T>
struct formatZeroIntegerWorkaround<T, true> {
261 static bool invoke(std::ostream &
out,
const T &value) {
262 if (
static_cast<int>(value) == 0 &&
263 out.flags() & std::ios::showpos) {
274 template <typename T, bool convertible = is_convertible<T, int>::value>
278 "integer for use as variable width or precision");
284 static int invoke(
const T &value) {
return static_cast<int>(value); }
288 template <
typename T>
290 std::ostringstream tmp;
292 std::string result = tmp.str();
293 out.write(result.c_str(),
294 (std::min)(ntrunc,
static_cast<int>(result.size())));
296#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
297 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
328 const char *fmtEnd,
int ntrunc,
const T &value) {
329#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
342 const bool canConvertToVoidPtr =
344 if (canConvertToChar && *(fmtEnd - 1) ==
'c')
346 else if (canConvertToVoidPtr && *(fmtEnd - 1) ==
'p')
348#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
349 else if (detail::formatZeroIntegerWorkaround<T>::invoke(
out, value))
352 else if (ntrunc >= 0) {
361#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
362 inline void formatValue(std::ostream &out, const char * , \
363 const char *fmtEnd, int , charType value) { \
364 switch (*(fmtEnd - 1)) { \
371 out << static_cast<int>(value); \
382#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
389#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_##n
390#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_##n
391#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_##n
392#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_##n
430#define TINYFORMAT_ARGTYPES_1 class T1
431#define TINYFORMAT_ARGTYPES_2 class T1, class T2
432#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
433#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
434#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
435#define TINYFORMAT_ARGTYPES_6 \
436 class T1, class T2, class T3, class T4, class T5, class T6
437#define TINYFORMAT_ARGTYPES_7 \
438 class T1, class T2, class T3, class T4, class T5, class T6, class T7
439#define TINYFORMAT_ARGTYPES_8 \
440 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
442#define TINYFORMAT_ARGTYPES_9 \
443 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
445#define TINYFORMAT_ARGTYPES_10 \
446 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
447 class T8, class T9, class T10
448#define TINYFORMAT_ARGTYPES_11 \
449 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
450 class T8, class T9, class T10, class T11
451#define TINYFORMAT_ARGTYPES_12 \
452 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
453 class T8, class T9, class T10, class T11, class T12
454#define TINYFORMAT_ARGTYPES_13 \
455 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
456 class T8, class T9, class T10, class T11, class T12, class T13
457#define TINYFORMAT_ARGTYPES_14 \
458 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
459 class T8, class T9, class T10, class T11, class T12, class T13, \
461#define TINYFORMAT_ARGTYPES_15 \
462 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
463 class T8, class T9, class T10, class T11, class T12, class T13, \
465#define TINYFORMAT_ARGTYPES_16 \
466 class T1, class T2, class T3, class T4, class T5, class T6, class T7, \
467 class T8, class T9, class T10, class T11, class T12, class T13, \
468 class T14, class T15, class T16
470#define TINYFORMAT_VARARGS_1 const T1 &v1
471#define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
472#define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
473#define TINYFORMAT_VARARGS_4 \
474 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
475#define TINYFORMAT_VARARGS_5 \
476 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
477#define TINYFORMAT_VARARGS_6 \
478 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
480#define TINYFORMAT_VARARGS_7 \
481 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
482 const T6 &v6, const T7 &v7
483#define TINYFORMAT_VARARGS_8 \
484 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
485 const T6 &v6, const T7 &v7, const T8 &v8
486#define TINYFORMAT_VARARGS_9 \
487 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
488 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
489#define TINYFORMAT_VARARGS_10 \
490 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
491 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
492#define TINYFORMAT_VARARGS_11 \
493 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
494 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
495 const T10 &v10, const T11 &v11
496#define TINYFORMAT_VARARGS_12 \
497 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
498 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
499 const T10 &v10, const T11 &v11, const T12 &v12
500#define TINYFORMAT_VARARGS_13 \
501 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
502 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
503 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
504#define TINYFORMAT_VARARGS_14 \
505 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
506 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
507 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
509#define TINYFORMAT_VARARGS_15 \
510 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
511 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
512 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
513 const T14 &v14, const T15 &v15
514#define TINYFORMAT_VARARGS_16 \
515 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, \
516 const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, \
517 const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, \
518 const T14 &v14, const T15 &v15, const T16 &v16
520#define TINYFORMAT_PASSARGS_1 v1
521#define TINYFORMAT_PASSARGS_2 v1, v2
522#define TINYFORMAT_PASSARGS_3 v1, v2, v3
523#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
524#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
525#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
526#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
527#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
528#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
529#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
530#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
531#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
532#define TINYFORMAT_PASSARGS_13 \
533 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
534#define TINYFORMAT_PASSARGS_14 \
535 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
536#define TINYFORMAT_PASSARGS_15 \
537 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
538#define TINYFORMAT_PASSARGS_16 \
539 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
541#define TINYFORMAT_PASSARGS_TAIL_1
542#define TINYFORMAT_PASSARGS_TAIL_2 , v2
543#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
544#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
545#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
546#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
547#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
548#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
549#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
550#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
551#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
552#define TINYFORMAT_PASSARGS_TAIL_12 \
553 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
554#define TINYFORMAT_PASSARGS_TAIL_13 \
555 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
556#define TINYFORMAT_PASSARGS_TAIL_14 \
557 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
558#define TINYFORMAT_PASSARGS_TAIL_15 \
559 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
560#define TINYFORMAT_PASSARGS_TAIL_16 \
561 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
563#define TINYFORMAT_FOREACH_ARGNUM(m) \
564 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) \
578 template <
typename T>
580 :
m_value(static_cast<const void *>(&value)),
583 void format(std::ostream &
out,
const char *fmtBegin,
const char *fmtEnd,
597 template <
typename T>
600 int ntrunc,
const void *value) {
602 *
static_cast<const T *
>(value));
605 template <
typename T>
612 const char *fmtEnd,
int ntrunc,
613 const void *value){
nullptr};
621 for (; *c >=
'0' && *c <=
'9'; ++c)
622 i = 10 * i + (*c -
'0');
634 int &argIndex,
int numArgs) {
635 if (*c >=
'0' && *c <=
'9') {
637 }
else if (*c ==
'*') {
640 if (positionalMode) {
644 "after a positional one");
645 if (pos >= 0 && pos < numArgs)
646 n = args[pos].
toInt();
649 "tinyformat: Positional argument out of range");
652 if (argIndex < numArgs)
653 n = args[argIndex++].
toInt();
656 "variable width or precision");
674 out.write(fmt, c - fmt);
676 }
else if (*c ==
'%') {
677 out.write(fmt, c - fmt);
678 if (*(c + 1) !=
'%')
return c;
721 bool &positionalMode,
722 bool &spacePadPositive,
723 int &ntrunc,
const char *fmtStart,
725 int &argIndex,
int numArgs) {
732 out.unsetf(std::ios::adjustfield | std::ios::basefield |
733 std::ios::floatfield | std::ios::showbase |
734 std::ios::boolalpha | std::ios::showpoint |
735 std::ios::showpos | std::ios::uppercase);
736 bool precisionSet =
false;
737 bool widthSet =
false;
739 const char *c = fmtStart + 1;
743 if (*c >=
'0' && *c <=
'9') {
744 const char tmpc = *c;
748 if (value > 0 && value <= numArgs)
749 argIndex = value - 1;
752 "tinyformat: Positional argument out of range");
754 positionalMode =
true;
755 }
else if (positionalMode) {
757 "after a positional one");
763 out.setf(std::ios::internal, std::ios::adjustfield);
771 }
else if (positionalMode) {
781 out.setf(std::ios::showpoint | std::ios::showbase);
785 if (!(
out.flags() & std::ios::left)) {
789 out.setf(std::ios::internal, std::ios::adjustfield);
794 out.setf(std::ios::left, std::ios::adjustfield);
798 if (!(
out.flags() & std::ios::showpos))
799 spacePadPositive =
true;
802 out.setf(std::ios::showpos);
803 spacePadPositive =
false;
819 out.setf(std::ios::left, std::ios::adjustfield);
833 precisionSet = precision >= 0;
834 if (precisionSet)
out.precision(precision);
837 while (*c ==
'l' || *c ==
'h' || *c ==
'L' || *c ==
'j' || *c ==
'z' ||
844 bool intConversion =
false;
849 out.setf(std::ios::dec, std::ios::basefield);
850 intConversion =
true;
853 out.setf(std::ios::oct, std::ios::basefield);
854 intConversion =
true;
857 out.setf(std::ios::uppercase);
861 out.setf(std::ios::hex, std::ios::basefield);
862 intConversion =
true;
865 out.setf(std::ios::uppercase);
868 out.setf(std::ios::scientific, std::ios::floatfield);
869 out.setf(std::ios::dec, std::ios::basefield);
872 out.setf(std::ios::uppercase);
875 out.setf(std::ios::fixed, std::ios::floatfield);
878 out.setf(std::ios::uppercase);
888 out.setf(std::ios::fixed | std::ios::scientific,
889 std::ios::floatfield);
892 out.setf(std::ios::uppercase);
895 out.setf(std::ios::dec, std::ios::basefield);
897 out.flags(
out.flags() & ~std::ios::floatfield);
903 if (precisionSet) ntrunc =
static_cast<int>(
out.precision());
905 out.setf(std::ios::boolalpha);
910 "tinyformat: %n conversion spec not supported");
914 "terminated by end of string");
919 if (intConversion && precisionSet && !widthSet) {
924 out.width(
out.precision() + widthExtra);
925 out.setf(std::ios::internal, std::ios::adjustfield);
935 std::streamsize origWidth =
out.width();
936 std::streamsize origPrecision =
out.precision();
937 std::ios::fmtflags origFlags =
out.flags();
938 char origFill =
out.fill();
943 bool positionalMode =
false;
948 if (!positionalMode && argIndex < numArgs) {
950 "specifiers in format string");
954 bool spacePadPositive =
false;
958 ntrunc, fmt, args, argIndex, numArgs);
962 if (argIndex >= numArgs) {
969 if (!spacePadPositive) {
976 std::ostringstream tmpStream;
977 tmpStream.copyfmt(
out);
978 tmpStream.setf(std::ios::showpos);
979 arg.
format(tmpStream, fmt, fmtEnd, ntrunc);
980 std::string result = tmpStream.str();
981 for (
size_t i = 0, iend = result.size(); i < iend; ++i) {
982 if (result[i] ==
'+') result[i] =
' ';
986 if (!positionalMode) ++argIndex;
991 out.width(origWidth);
992 out.precision(origPrecision);
993 out.flags(origFlags);
1025#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1026 template <
typename... Args>
1030 static_assert(
sizeof...(args) == N,
"Number of args must be N");
1034#define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
1036 template <TINYFORMAT_ARGTYPES(n)> \
1037 FormatListN(TINYFORMAT_VARARGS(n)) : FormatList(&m_formatterStore[0], n) { \
1038 TINYFORMAT_ASSERT(n == N); \
1039 init(0, TINYFORMAT_PASSARGS(n)); \
1042 template <TINYFORMAT_ARGTYPES(n)> \
1043 void init(int i, TINYFORMAT_VARARGS(n)) { \
1044 m_formatterStore[i] = FormatArg(v1); \
1045 init(i + 1 TINYFORMAT_PASSARGS_TAIL(n)); \
1049#undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
1073#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1081template <
typename... Args>
1089 return detail::FormatListN<0>();
1091#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
1092 template <TINYFORMAT_ARGTYPES(n)> \
1093 detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) { \
1094 return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
1097#undef TINYFORMAT_MAKE_MAKEFORMATLIST
1109#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
1112template <
typename... Args>
1113void format(std::ostream &
out,
const char *fmt,
const Args &...args) {
1119template <
typename... Args>
1120std::string
format(
const char *fmt,
const Args &...args) {
1121 std::ostringstream oss;
1122 format(oss, fmt, args...);
1127template <
typename... Args>
void printf(
const char *fmt,
const Args &...args) {
1128 format(std::cout, fmt, args...);
1131template <
typename... Args>
1133 format(std::cout, fmt, args...);
1139inline void format(std::ostream &
out,
const char *fmt) {
1143inline std::string
format(
const char *fmt) {
1144 std::ostringstream oss;
1149inline void printf(
const char *fmt) {
1153inline void printfln(
const char *fmt) {
1158#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
1160 template <TINYFORMAT_ARGTYPES(n)> \
1161 void format(std::ostream &out, const char *fmt, TINYFORMAT_VARARGS(n)) { \
1162 vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
1165 template <TINYFORMAT_ARGTYPES(n)> \
1166 std::string format(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1167 std::ostringstream oss; \
1168 format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
1172 template <TINYFORMAT_ARGTYPES(n)> \
1173 void printf(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1174 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1177 template <TINYFORMAT_ARGTYPES(n)> \
1178 void printfln(const char *fmt, TINYFORMAT_VARARGS(n)) { \
1179 format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
1180 std::cout << '\n'; \
1184#undef TINYFORMAT_MAKE_FORMAT_FUNCS
1189template <
typename... Args>
1190std::string
format(
const std::string &fmt,
const Args &...args) {
1191 std::ostringstream oss;
1192 format(oss, fmt.c_str(), args...);
1203#define strprintf tfm::format
Implement std::hash so RCUPtr can be used as a key for maps or sets.