@@ -943,11 +943,24 @@ func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum
943
943
return argNum , i + wid , ok
944
944
}
945
945
946
+ func (p * pp ) badArgNum (verb rune ) {
947
+ p .buf .WriteString (percentBangString )
948
+ p .buf .WriteRune (verb )
949
+ p .buf .WriteString (badIndexString )
950
+ }
951
+
952
+ func (p * pp ) missingArg (verb rune ) {
953
+ p .buf .WriteString (percentBangString )
954
+ p .buf .WriteRune (verb )
955
+ p .buf .WriteString (missingString )
956
+ }
957
+
946
958
func (p * pp ) doPrintf (format string , a []interface {}) {
947
959
end := len (format )
948
960
argNum := 0 // we process one argument per non-trivial format
949
961
afterIndex := false // previous item in format was an index like [3].
950
962
p .reordered = false
963
+ formatLoop:
951
964
for i := 0 ; i < end ; {
952
965
p .goodArgNum = true
953
966
lasti := i
@@ -967,21 +980,40 @@ func (p *pp) doPrintf(format string, a []interface{}) {
967
980
968
981
// Do we have flags?
969
982
p .fmt .clearflags ()
970
- F :
983
+ simpleFormat :
971
984
for ; i < end ; i ++ {
972
- switch format [i ] {
985
+ c := format [i ]
986
+ switch c {
973
987
case '#' :
974
988
p .fmt .sharp = true
975
989
case '0' :
976
- p .fmt .zero = true
990
+ p .fmt .zero = ! p . fmt . minus // Only allow zero padding to the left.
977
991
case '+' :
978
992
p .fmt .plus = true
979
993
case '-' :
980
994
p .fmt .minus = true
995
+ p .fmt .zero = false // Do not pad with zeros to the right.
981
996
case ' ' :
982
997
p .fmt .space = true
983
998
default :
984
- break F
999
+ // Fast path for common case of ascii lower case simple verbs
1000
+ // without precision or width or argument indices.
1001
+ if 'a' <= c && c <= 'z' && argNum < len (a ) {
1002
+ if c == 'v' {
1003
+ // Go syntax
1004
+ p .fmt .sharpV = p .fmt .sharp
1005
+ p .fmt .sharp = false
1006
+ // Struct-field syntax
1007
+ p .fmt .plusV = p .fmt .plus
1008
+ p .fmt .plus = false
1009
+ }
1010
+ p .printArg (a [argNum ], rune (c ))
1011
+ argNum ++
1012
+ i ++
1013
+ continue formatLoop
1014
+ }
1015
+ // Format is more complex than simple flags and a verb or is malformed.
1016
+ break simpleFormat
985
1017
}
986
1018
}
987
1019
@@ -1002,6 +1034,7 @@ func (p *pp) doPrintf(format string, a []interface{}) {
1002
1034
if p .fmt .wid < 0 {
1003
1035
p .fmt .wid = - p .fmt .wid
1004
1036
p .fmt .minus = true
1037
+ p .fmt .zero = false // Do not pad with zeros to the right.
1005
1038
}
1006
1039
afterIndex = false
1007
1040
} else {
@@ -1045,47 +1078,31 @@ func (p *pp) doPrintf(format string, a []interface{}) {
1045
1078
1046
1079
if i >= end {
1047
1080
p .buf .WriteString (noVerbString )
1048
- continue
1049
- }
1050
- c , w := utf8 .DecodeRuneInString (format [i :])
1051
- i += w
1052
- // percent is special - absorbs no operand
1053
- if c == '%' {
1054
- p .buf .WriteByte ('%' ) // We ignore width and prec.
1055
- continue
1056
- }
1057
- if ! p .goodArgNum {
1058
- p .buf .WriteString (percentBangString )
1059
- p .buf .WriteRune (c )
1060
- p .buf .WriteString (badIndexString )
1061
- continue
1062
- } else if argNum >= len (a ) { // out of operands
1063
- p .buf .WriteString (percentBangString )
1064
- p .buf .WriteRune (c )
1065
- p .buf .WriteString (missingString )
1066
- continue
1081
+ break
1067
1082
}
1068
1083
1069
- if c == 'v' {
1070
- if p .fmt .sharp {
1071
- // Go syntax. Set the flag in the fmt and clear the sharp flag.
1072
- p .fmt .sharp = false
1073
- p .fmt .sharpV = true
1074
- }
1075
- if p .fmt .plus {
1076
- // Struct-field syntax. Set the flag in the fmt and clear the plus flag.
1077
- p .fmt .plus = false
1078
- p .fmt .plusV = true
1079
- }
1080
- }
1084
+ verb , w := utf8 .DecodeRuneInString (format [i :])
1085
+ i += w
1081
1086
1082
- // Use space padding instead of zero padding to the right.
1083
- if p .fmt .minus {
1084
- p .fmt .zero = false
1087
+ switch {
1088
+ case verb == '%' : // Percent does not absorb operands and ignores f.wid and f.prec.
1089
+ p .buf .WriteByte ('%' )
1090
+ case ! p .goodArgNum :
1091
+ p .badArgNum (verb )
1092
+ case argNum >= len (a ): // No argument left over to print for the current verb.
1093
+ p .missingArg (verb )
1094
+ case verb == 'v' :
1095
+ // Go syntax
1096
+ p .fmt .sharpV = p .fmt .sharp
1097
+ p .fmt .sharp = false
1098
+ // Struct-field syntax
1099
+ p .fmt .plusV = p .fmt .plus
1100
+ p .fmt .plus = false
1101
+ fallthrough
1102
+ default :
1103
+ p .printArg (a [argNum ], verb )
1104
+ argNum ++
1085
1105
}
1086
-
1087
- p .printArg (a [argNum ], c )
1088
- argNum ++
1089
1106
}
1090
1107
1091
1108
// Check for extra arguments unless the call accessed the arguments
0 commit comments