106 #ifndef TINYFORMAT_H_INCLUDED
107 #define TINYFORMAT_H_INCLUDED
109 namespace tinyformat {}
114 namespace tfm = tinyformat;
130 #ifndef TINYFORMAT_ERROR
131 # define TINYFORMAT_ERROR(reason) assert(0 && reason)
134 #if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
135 # ifdef __GXX_EXPERIMENTAL_CXX0X__
136 # define TINYFORMAT_USE_VARIADIC_TEMPLATES
141 # define TINYFORMAT_NOINLINE __attribute__((noinline))
142 #elif defined(_MSC_VER)
143 # define TINYFORMAT_NOINLINE __declspec(noinline)
145 # define TINYFORMAT_NOINLINE
149 namespace tinyformat {
155 template <
typename T1,
typename T2>
160 struct fail {
char dummy[2]; };
161 struct succeed {
char dummy; };
163 static fail tryConvert(...);
164 static succeed tryConvert(
const T2&);
165 static const T1& makeT1();
169 # pragma warning(push)
170 # pragma warning(disable:4244)
176 static const bool value =
177 sizeof(tryConvert(makeT1())) ==
sizeof(succeed);
179 # pragma warning(pop)
186 template<typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
189 static void invoke(std::ostream& out,
const T& value) { assert(0); }
193 template<
typename T,
typename fmtT>
196 static void invoke(std::ostream& out,
const T& value)
197 { out << static_cast<fmtT>(value); }
203 template<typename T, bool convertible = is_convertible<T,int>::value>
206 static int invoke(
const T& value)
208 TINYFORMAT_ERROR(
"tinyformat: Cannot convert from argument type to "
209 "integer for use as variable width or precision");
217 static int invoke(
const T& value) {
return static_cast<int>(value); }
238 inline void formatValue(std::ostream& out,
const char* fmtBegin,
239 const char* fmtEnd,
const T& value)
248 if(canConvertToChar && *(fmtEnd-1) ==
'c')
250 else if(canConvertToVoidPtr && *(fmtEnd-1) ==
'p')
258 #define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
259 inline void formatValue(std::ostream& out, const char* fmtBegin, \
260 const char* fmtEnd, charType value) \
262 switch(*(fmtEnd-1)) \
264 case 'u': case 'd': case 'i': case 'o': case 'X': case 'x': \
265 out << static_cast<int>(value); break; \
267 out << value; break; \
271 TINYFORMAT_DEFINE_FORMATVALUE_CHAR(
char)
272 TINYFORMAT_DEFINE_FORMATVALUE_CHAR(
signed char)
273 TINYFORMAT_DEFINE_FORMATVALUE_CHAR(
unsigned char)
274 #undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
285 enum ExtraFormatFlags
287 Flag_TruncateToPrecision = 1<<0,
288 Flag_SpacePadPositive = 1<<1,
289 Flag_VariableWidth = 1<<2,
290 Flag_VariablePrecision = 1<<3,
299 m_wantPrecision(
false),
301 m_variablePrecision(0),
302 m_origWidth(out.width()),
303 m_origPrecision(out.precision()),
304 m_origFlags(out.flags()),
305 m_origFill(out.fill())
313 m_fmt = printFormatStringLiteral(m_out, m_fmt);
315 TINYFORMAT_ERROR(
"tinyformat: Too many conversion specifiers in format string");
321 m_out.width(m_origWidth);
322 m_out.precision(m_origPrecision);
323 m_out.flags(m_origFlags);
324 m_out.fill(m_origFill);
328 void accept(
const T& value);
333 static int parseIntAndAdvance(
const char*& c)
336 for(;*c >=
'0' && *c <=
'9'; ++c)
337 i = 10*i + (*c -
'0');
345 static bool formatCStringTruncate(std::ostream& out,
const T& value,
346 std::streamsize truncLen)
350 # define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type) \
351 static bool formatCStringTruncate(std::ostream& out, type* value, \
352 std::streamsize truncLen) \
354 std::streamsize len = 0; \
355 while(len < truncLen && value[len] != 0) \
357 out.write(value, len); \
363 TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(
const char)
364 TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(
char)
365 # undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE
373 static const char* printFormatStringLiteral(std::ostream& out,
382 out.write(fmt, static_cast<std::streamsize>(c - fmt));
385 out.write(fmt, static_cast<std::streamsize>(c - fmt));
395 static const char* streamStateFromFormat(std::ostream& out,
396 unsigned int& extraFlags,
397 const char* fmtStart,
399 int variablePrecision);
404 unsigned int m_extraFlags;
407 bool m_wantPrecision;
409 int m_variablePrecision;
411 std::streamsize m_origWidth;
412 std::streamsize m_origPrecision;
413 std::ios::fmtflags m_origFlags;
421 void FormatIterator::accept(
const T& value)
424 const char* fmtEnd = 0;
425 if(m_extraFlags == 0 && !m_wantWidth && !m_wantPrecision)
427 m_fmt = printFormatStringLiteral(m_out, m_fmt);
428 fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0);
429 m_wantWidth = (m_extraFlags & Flag_VariableWidth) != 0;
430 m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0;
433 if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision))
435 if(m_wantWidth || m_wantPrecision)
437 int v = convertToInt<T>::invoke(value);
443 else if(m_wantPrecision)
445 m_variablePrecision = v;
446 m_wantPrecision =
false;
452 fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt,
453 m_variableWidth, m_variablePrecision);
457 if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision)))
458 formatValue(m_out, m_fmt, fmtEnd, value);
465 std::ostringstream tmpStream;
466 tmpStream.copyfmt(m_out);
467 if(m_extraFlags & Flag_SpacePadPositive)
468 tmpStream.setf(std::ios::showpos);
472 if(!( (m_extraFlags & Flag_TruncateToPrecision) &&
473 formatCStringTruncate(tmpStream, value, m_out.precision()) ))
476 formatValue(tmpStream, m_fmt, fmtEnd, value);
478 std::string result = tmpStream.str();
479 if(m_extraFlags & Flag_SpacePadPositive)
481 for(
size_t i = 0, iend = result.size(); i < iend; ++i)
485 if((m_extraFlags & Flag_TruncateToPrecision) &&
486 (int)result.size() > (int)m_out.precision())
487 m_out.write(result.c_str(), m_out.precision());
504 inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
505 unsigned int& extraFlags,
506 const char* fmtStart,
508 int variablePrecision)
512 TINYFORMAT_ERROR(
"tinyformat: Not enough conversion specifiers in format string");
520 out.unsetf(std::ios::adjustfield | std::ios::basefield |
521 std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
522 std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
524 bool precisionSet =
false;
525 bool widthSet =
false;
526 const char* c = fmtStart + 1;
533 out.setf(std::ios::showpoint | std::ios::showbase);
537 if(!(out.flags() & std::ios::left))
542 out.setf(std::ios::internal, std::ios::adjustfield);
547 out.setf(std::ios::left, std::ios::adjustfield);
551 if(!(out.flags() & std::ios::showpos))
552 extraFlags |= Flag_SpacePadPositive;
555 out.setf(std::ios::showpos);
556 extraFlags &= ~Flag_SpacePadPositive;
562 if(*c >=
'0' && *c <=
'9')
565 out.width(parseIntAndAdvance(c));
570 if(variableWidth < 0)
574 out.setf(std::ios::left, std::ios::adjustfield);
575 variableWidth = -variableWidth;
577 out.width(variableWidth);
578 extraFlags |= Flag_VariableWidth;
589 extraFlags |= Flag_VariablePrecision;
590 precision = variablePrecision;
594 if(*c >=
'0' && *c <=
'9')
595 precision = parseIntAndAdvance(c);
597 parseIntAndAdvance(++c);
599 out.precision(precision);
603 while(*c ==
'l' || *c ==
'h' || *c ==
'L' ||
604 *c ==
'j' || *c ==
'z' || *c ==
't')
609 bool intConversion =
false;
612 case 'u':
case 'd':
case 'i':
613 out.setf(std::ios::dec, std::ios::basefield);
614 intConversion =
true;
617 out.setf(std::ios::oct, std::ios::basefield);
618 intConversion =
true;
621 out.setf(std::ios::uppercase);
623 out.setf(std::ios::hex, std::ios::basefield);
624 intConversion =
true;
627 out.setf(std::ios::uppercase);
629 out.setf(std::ios::scientific, std::ios::floatfield);
630 out.setf(std::ios::dec, std::ios::basefield);
633 out.setf(std::ios::uppercase);
635 out.setf(std::ios::fixed, std::ios::floatfield);
638 out.setf(std::ios::uppercase);
640 out.setf(std::ios::dec, std::ios::basefield);
642 out.flags(out.flags() & ~std::ios::floatfield);
651 extraFlags |= Flag_TruncateToPrecision;
653 out.setf(std::ios::boolalpha);
657 TINYFORMAT_ERROR(
"tinyformat: %n conversion spec not supported");
660 TINYFORMAT_ERROR(
"tinyformat: Conversion spec incorrectly "
661 "terminated by end of string");
664 if(intConversion && precisionSet && !widthSet)
670 out.width(out.precision());
671 out.setf(std::ios::internal, std::ios::adjustfield);
681 inline void format(FormatIterator& fmtIter)
689 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
692 template<
typename T1,
typename... Args>
693 void format(FormatIterator& fmtIter,
const T1& value1,
const Args&... args)
695 fmtIter.accept(value1);
696 format(fmtIter, args...);
746 template<
typename T1>
747 void format(FormatIterator& fmtIter ,
const T1& v1)
752 template<
typename T1,
typename T2>
753 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2)
758 template<
typename T1,
typename T2,
typename T3>
759 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3)
762 format(fmtIter, v2, v3);
764 template<
typename T1,
typename T2,
typename T3,
typename T4>
765 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4)
768 format(fmtIter, v2, v3, v4);
770 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
771 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5)
774 format(fmtIter, v2, v3, v4, v5);
776 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
777 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5,
const T6& v6)
780 format(fmtIter, v2, v3, v4, v5, v6);
782 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7>
783 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5,
const T6& v6,
const T7& v7)
786 format(fmtIter, v2, v3, v4, v5, v6, v7);
788 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8>
789 void format(FormatIterator& fmtIter ,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5,
const T6& v6,
const T7& v7,
const T8& v8)
792 format(fmtIter, v2, v3, v4, v5, v6, v7, v8);
794 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9>
795 void format(FormatIterator& fmtIter ,
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)
798 format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9);
800 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10>
801 void format(FormatIterator& fmtIter ,
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)
804 format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10);
806 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename T11>
807 void format(FormatIterator& fmtIter ,
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)
810 format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
812 template<
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename T11,
typename T12>
813 void format(FormatIterator& fmtIter ,
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)
816 format(fmtIter, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
820 #endif // End C++98 variadic template emulation for format()
854 #ifndef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
855 #define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
859 #define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix, \
860 bodyPrefix, streamName, bodySuffix) \
862 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
866 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
867 tinyformat::detail::format(fmtIter); \
870 template<typename T1> \
871 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
872 , const T1& v1) funcDeclSuffix \
875 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
876 tinyformat::detail::format(fmtIter, v1); \
879 template<typename T1, typename T2> \
880 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
881 , const T1& v1, const T2& v2) funcDeclSuffix \
884 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
885 tinyformat::detail::format(fmtIter, v1, v2); \
888 template<typename T1, typename T2, typename T3> \
889 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
890 , const T1& v1, const T2& v2, const T3& v3) funcDeclSuffix \
893 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
894 tinyformat::detail::format(fmtIter, v1, v2, v3); \
897 template<typename T1, typename T2, typename T3, typename T4> \
898 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
899 , const T1& v1, const T2& v2, const T3& v3, const T4& v4) funcDeclSuffix \
902 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
903 tinyformat::detail::format(fmtIter, v1, v2, v3, v4); \
906 template<typename T1, typename T2, typename T3, typename T4, typename T5> \
907 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
908 , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5) funcDeclSuffix \
911 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
912 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5); \
915 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> \
916 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
917 , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) funcDeclSuffix \
920 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
921 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6); \
924 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> \
925 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
926 , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7) funcDeclSuffix \
929 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
930 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7); \
933 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> \
934 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
935 , const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7, const T8& v8) funcDeclSuffix \
938 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
939 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8); \
942 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> \
943 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
944 , 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) funcDeclSuffix \
947 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
948 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9); \
951 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> \
952 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
953 , 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) funcDeclSuffix \
956 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
957 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); \
960 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11> \
961 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
962 , 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) funcDeclSuffix \
965 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
966 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); \
969 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12> \
970 returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
971 , 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) funcDeclSuffix \
974 tinyformat::detail::FormatIterator fmtIter(streamName, fmt); \
975 tinyformat::detail::format(fmtIter, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); \
986 #ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
989 template<
typename... Args>
990 void format(std::ostream& out,
const char* fmt,
const Args&... args)
992 detail::FormatIterator fmtIter(out, fmt);
993 format(fmtIter, args...);
996 template<
typename... Args>
997 std::string format(
const char* fmt,
const Args&... args)
999 std::ostringstream oss;
1000 format(oss, fmt, args...);
1004 template<
typename... Args>
1005 void printf(
const char* fmt,
const Args&... args)
1007 format(std::cout, fmt, args...);
1016 #undef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
1017 #define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS std::ostream& out,
1018 TINYFORMAT_WRAP_FORMAT(
void, format, , , out, )
1019 #undef TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
1022 #define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
1025 TINYFORMAT_WRAP_FORMAT(std::string, format, ,
1026 std::ostringstream oss;, oss,
1030 TINYFORMAT_WRAP_FORMAT(
void, printf, , , std::cout, )
1036 #endif // TINYFORMAT_H_INCLUDED