@@ -658,10 +658,7 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& positionalMode
658658 const detail::FormatArg* args,
659659 int & argIndex, int numArgs)
660660{
661- if (*fmtStart != ' %' ) {
662- TINYFORMAT_ERROR (" tinyformat: Not enough conversion specifiers in format string" );
663- return fmtStart;
664- }
661+ TINYFORMAT_ASSERT (*fmtStart == ' %' );
665662 // Reset stream state to defaults.
666663 out.width (0 );
667664 out.precision (6 );
@@ -873,19 +870,26 @@ inline void formatImpl(std::ostream& out, const char* fmt,
873870 std::ios::fmtflags origFlags = out.flags ();
874871 char origFill = out.fill ();
875872
873+ // "Positional mode" means all format specs should be of the form "%n$..."
874+ // with `n` an integer. We detect this in `streamStateFromFormat`.
876875 bool positionalMode = false ;
877- for ( int argIndex = 0 ; positionalMode || argIndex < numArgs; ++argIndex) {
878- // Parse the format string
876+ int argIndex = 0 ;
877+ while ( true ) {
879878 fmt = printFormatStringLiteral (out, fmt);
880- if (positionalMode && *fmt == ' \0 ' )
879+ if (*fmt == ' \0 ' ) {
880+ if (!positionalMode && argIndex < numArgs) {
881+ TINYFORMAT_ERROR (" tinyformat: Not enough conversion specifiers in format string" );
882+ }
881883 break ;
884+ }
882885 bool spacePadPositive = false ;
883886 int ntrunc = -1 ;
884887 const char * fmtEnd = streamStateFromFormat (out, positionalMode, spacePadPositive, ntrunc, fmt,
885888 args, argIndex, numArgs);
889+ // NB: argIndex may be incremented by reading variable width/precision
890+ // in `streamStateFromFormat`, so do the bounds check here.
886891 if (argIndex >= numArgs) {
887- // Check args remain after reading any variable width/precision
888- TINYFORMAT_ERROR (" tinyformat: Not enough format arguments" );
892+ TINYFORMAT_ERROR (" tinyformat: Too many conversion specifiers in format string" );
889893 return ;
890894 }
891895 const FormatArg& arg = args[argIndex];
@@ -909,14 +913,11 @@ inline void formatImpl(std::ostream& out, const char* fmt,
909913 }
910914 out << result;
911915 }
916+ if (!positionalMode)
917+ ++argIndex;
912918 fmt = fmtEnd;
913919 }
914920
915- // Print remaining part of format string.
916- fmt = printFormatStringLiteral (out, fmt);
917- if (*fmt != ' \0 ' )
918- TINYFORMAT_ERROR (" tinyformat: Too many conversion specifiers in format string" );
919-
920921 // Restore stream state
921922 out.width (origWidth);
922923 out.precision (origPrecision);
0 commit comments