@@ -658,10 +658,7 @@ inline const char* streamStateFromFormat(std::ostream& out, bool& positionalMode
658
658
const detail::FormatArg* args,
659
659
int & argIndex, int numArgs)
660
660
{
661
- if (*fmtStart != ' %' ) {
662
- TINYFORMAT_ERROR (" tinyformat: Not enough conversion specifiers in format string" );
663
- return fmtStart;
664
- }
661
+ TINYFORMAT_ASSERT (*fmtStart == ' %' );
665
662
// Reset stream state to defaults.
666
663
out.width (0 );
667
664
out.precision (6 );
@@ -873,19 +870,26 @@ inline void formatImpl(std::ostream& out, const char* fmt,
873
870
std::ios::fmtflags origFlags = out.flags ();
874
871
char origFill = out.fill ();
875
872
873
+ // "Positional mode" means all format specs should be of the form "%n$..."
874
+ // with `n` an integer. We detect this in `streamStateFromFormat`.
876
875
bool positionalMode = false ;
877
- for ( int argIndex = 0 ; positionalMode || argIndex < numArgs; ++argIndex) {
878
- // Parse the format string
876
+ int argIndex = 0 ;
877
+ while ( true ) {
879
878
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
+ }
881
883
break ;
884
+ }
882
885
bool spacePadPositive = false ;
883
886
int ntrunc = -1 ;
884
887
const char * fmtEnd = streamStateFromFormat (out, positionalMode, spacePadPositive, ntrunc, fmt,
885
888
args, argIndex, numArgs);
889
+ // NB: argIndex may be incremented by reading variable width/precision
890
+ // in `streamStateFromFormat`, so do the bounds check here.
886
891
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" );
889
893
return ;
890
894
}
891
895
const FormatArg& arg = args[argIndex];
@@ -909,14 +913,11 @@ inline void formatImpl(std::ostream& out, const char* fmt,
909
913
}
910
914
out << result;
911
915
}
916
+ if (!positionalMode)
917
+ ++argIndex;
912
918
fmt = fmtEnd;
913
919
}
914
920
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
-
920
921
// Restore stream state
921
922
out.width (origWidth);
922
923
out.precision (origPrecision);
0 commit comments