type flagPrinter struct{}
-func (*flagPrinter) Format(f State, c rune) {
+func (flagPrinter) Format(f State, c rune) {
s := "%"
for i := 0; i < 128; i++ {
if f.Flag(i) {
}
}
-// Formatters did not get delivered flags correctly in all cases. Issue 8835.
-type fp struct{}
-
-func (fp) Format(f State, c rune) {
- s := "%"
- for i := 0; i < 128; i++ {
- if f.Flag(i) {
- s += string(i)
- }
- }
- if w, ok := f.Width(); ok {
- s += Sprintf("%d", w)
- }
- if p, ok := f.Precision(); ok {
- s += Sprintf(".%d", p)
- }
- s += string(c)
- io.WriteString(f, "["+s+"]")
-}
-
var formatterFlagTests = []struct {
in string
val interface{}
out string
}{
// scalar values with the (unused by fmt) 'a' verb.
- {"%a", fp{}, "[%a]"},
- {"%-a", fp{}, "[%-a]"},
- {"%+a", fp{}, "[%+a]"},
- {"%#a", fp{}, "[%#a]"},
- {"% a", fp{}, "[% a]"},
- {"%0a", fp{}, "[%0a]"},
- {"%1.2a", fp{}, "[%1.2a]"},
- {"%-1.2a", fp{}, "[%-1.2a]"},
- {"%+1.2a", fp{}, "[%+1.2a]"},
- {"%-+1.2a", fp{}, "[%+-1.2a]"},
- {"%-+1.2abc", fp{}, "[%+-1.2a]bc"},
- {"%-1.2abc", fp{}, "[%-1.2a]bc"},
+ {"%a", flagPrinter{}, "[%a]"},
+ {"%-a", flagPrinter{}, "[%-a]"},
+ {"%+a", flagPrinter{}, "[%+a]"},
+ {"%#a", flagPrinter{}, "[%#a]"},
+ {"% a", flagPrinter{}, "[% a]"},
+ {"%0a", flagPrinter{}, "[%0a]"},
+ {"%1.2a", flagPrinter{}, "[%1.2a]"},
+ {"%-1.2a", flagPrinter{}, "[%-1.2a]"},
+ {"%+1.2a", flagPrinter{}, "[%+1.2a]"},
+ {"%-+1.2a", flagPrinter{}, "[%+-1.2a]"},
+ {"%-+1.2abc", flagPrinter{}, "[%+-1.2a]bc"},
+ {"%-1.2abc", flagPrinter{}, "[%-1.2a]bc"},
// composite values with the 'a' verb
- {"%a", [1]fp{}, "[[%a]]"},
- {"%-a", [1]fp{}, "[[%-a]]"},
- {"%+a", [1]fp{}, "[[%+a]]"},
- {"%#a", [1]fp{}, "[[%#a]]"},
- {"% a", [1]fp{}, "[[% a]]"},
- {"%0a", [1]fp{}, "[[%0a]]"},
- {"%1.2a", [1]fp{}, "[[%1.2a]]"},
- {"%-1.2a", [1]fp{}, "[[%-1.2a]]"},
- {"%+1.2a", [1]fp{}, "[[%+1.2a]]"},
- {"%-+1.2a", [1]fp{}, "[[%+-1.2a]]"},
- {"%-+1.2abc", [1]fp{}, "[[%+-1.2a]]bc"},
- {"%-1.2abc", [1]fp{}, "[[%-1.2a]]bc"},
+ {"%a", [1]flagPrinter{}, "[[%a]]"},
+ {"%-a", [1]flagPrinter{}, "[[%-a]]"},
+ {"%+a", [1]flagPrinter{}, "[[%+a]]"},
+ {"%#a", [1]flagPrinter{}, "[[%#a]]"},
+ {"% a", [1]flagPrinter{}, "[[% a]]"},
+ {"%0a", [1]flagPrinter{}, "[[%0a]]"},
+ {"%1.2a", [1]flagPrinter{}, "[[%1.2a]]"},
+ {"%-1.2a", [1]flagPrinter{}, "[[%-1.2a]]"},
+ {"%+1.2a", [1]flagPrinter{}, "[[%+1.2a]]"},
+ {"%-+1.2a", [1]flagPrinter{}, "[[%+-1.2a]]"},
+ {"%-+1.2abc", [1]flagPrinter{}, "[[%+-1.2a]]bc"},
+ {"%-1.2abc", [1]flagPrinter{}, "[[%-1.2a]]bc"},
// simple values with the 'v' verb
- {"%v", fp{}, "[%v]"},
- {"%-v", fp{}, "[%-v]"},
- {"%+v", fp{}, "[%+v]"},
- {"%#v", fp{}, "[%#v]"},
- {"% v", fp{}, "[% v]"},
- {"%0v", fp{}, "[%0v]"},
- {"%1.2v", fp{}, "[%1.2v]"},
- {"%-1.2v", fp{}, "[%-1.2v]"},
- {"%+1.2v", fp{}, "[%+1.2v]"},
- {"%-+1.2v", fp{}, "[%+-1.2v]"},
- {"%-+1.2vbc", fp{}, "[%+-1.2v]bc"},
- {"%-1.2vbc", fp{}, "[%-1.2v]bc"},
-
- // composite values with the 'v' verb. Some are still broken.
- {"%v", [1]fp{}, "[[%v]]"},
- {"%-v", [1]fp{}, "[[%-v]]"},
- //{"%+v", [1]fp{}, "[[%+v]]"},
- {"%#v", [1]fp{}, "[1]fmt_test.fp{[%#v]}"},
- {"% v", [1]fp{}, "[[% v]]"},
- {"%0v", [1]fp{}, "[[%0v]]"},
- {"%1.2v", [1]fp{}, "[[%1.2v]]"},
- {"%-1.2v", [1]fp{}, "[[%-1.2v]]"},
- //{"%+1.2v", [1]fp{}, "[[%+1.2v]]"},
- //{"%-+1.2v", [1]fp{}, "[[%+-1.2v]]"},
- //{"%-+1.2vbc", [1]fp{}, "[[%+-1.2v]]bc"},
- {"%-1.2vbc", [1]fp{}, "[[%-1.2v]]bc"},
+ {"%v", flagPrinter{}, "[%v]"},
+ {"%-v", flagPrinter{}, "[%-v]"},
+ {"%+v", flagPrinter{}, "[%+v]"},
+ {"%#v", flagPrinter{}, "[%#v]"},
+ {"% v", flagPrinter{}, "[% v]"},
+ {"%0v", flagPrinter{}, "[%0v]"},
+ {"%1.2v", flagPrinter{}, "[%1.2v]"},
+ {"%-1.2v", flagPrinter{}, "[%-1.2v]"},
+ {"%+1.2v", flagPrinter{}, "[%+1.2v]"},
+ {"%-+1.2v", flagPrinter{}, "[%+-1.2v]"},
+ {"%-+1.2vbc", flagPrinter{}, "[%+-1.2v]bc"},
+ {"%-1.2vbc", flagPrinter{}, "[%-1.2v]bc"},
+
+ // composite values with the 'v' verb.
+ {"%v", [1]flagPrinter{}, "[[%v]]"},
+ {"%-v", [1]flagPrinter{}, "[[%-v]]"},
+ {"%+v", [1]flagPrinter{}, "[[%+v]]"},
+ {"%#v", [1]flagPrinter{}, "[1]fmt_test.flagPrinter{[%#v]}"},
+ {"% v", [1]flagPrinter{}, "[[% v]]"},
+ {"%0v", [1]flagPrinter{}, "[[%0v]]"},
+ {"%1.2v", [1]flagPrinter{}, "[[%1.2v]]"},
+ {"%-1.2v", [1]flagPrinter{}, "[[%-1.2v]]"},
+ {"%+1.2v", [1]flagPrinter{}, "[[%+1.2v]]"},
+ {"%-+1.2v", [1]flagPrinter{}, "[[%+-1.2v]]"},
+ {"%-+1.2vbc", [1]flagPrinter{}, "[[%+-1.2v]]bc"},
+ {"%-1.2vbc", [1]flagPrinter{}, "[[%-1.2v]]bc"},
}
func TestFormatterFlags(t *testing.T) {
New: func() interface{} { return new(pp) },
}
-// newPrinter allocates a new pp struct or grab a cached one.
+// newPrinter allocates a new pp struct or grabs a cached one.
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
case p.arg != nil:
p.buf.WriteString(reflect.TypeOf(p.arg).String())
p.add('=')
- p.printArg(p.arg, 'v', false, 0)
+ p.printArg(p.arg, 'v', 0)
case p.value.IsValid():
p.buf.WriteString(p.value.Type().String())
p.add('=')
- p.printValue(p.value, 'v', false, 0)
+ p.printValue(p.value, 'v', 0)
default:
p.buf.Write(nilAngleBytes)
}
p.buf.WriteByte(' ')
}
}
- p.printArg(c, 'v', p.fmt.plus, depth+1)
+ p.printArg(c, 'v', depth+1)
}
if p.fmt.sharpV {
p.buf.WriteByte('}')
p.add(verb)
p.buf.Write(panicBytes)
p.panicking = true
- p.printArg(err, 'v', false, 0)
+ p.printArg(err, 'v', 0)
p.panicking = false
p.buf.WriteByte(')')
}
}
// clearSpecialFlags pushes %#v back into the regular flags and returns their old state.
-func (p *pp) clearSpecialFlags() bool {
- ret := p.fmt.sharpV
- if ret {
+func (p *pp) clearSpecialFlags() (plusV, sharpV bool) {
+ plusV = p.fmt.plusV
+ if plusV {
+ p.fmt.plus = true
+ p.fmt.plusV = false
+ }
+ sharpV = p.fmt.sharpV
+ if sharpV {
p.fmt.sharp = true
p.fmt.sharpV = false
}
- return ret
+ return
}
// restoreSpecialFlags, whose argument should be a call to clearSpecialFlags,
-// restores the setting of the sharpV flag.
-func (p *pp) restoreSpecialFlags(sharpV bool) {
+// restores the setting of the plusV and sharpV flags.
+func (p *pp) restoreSpecialFlags(plusV, sharpV bool) {
+ if plusV {
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
if sharpV {
p.fmt.sharp = false
p.fmt.sharpV = true
}
}
-func (p *pp) handleMethods(verb rune, plus bool, depth int) (handled bool) {
+func (p *pp) handleMethods(verb rune, depth int) (handled bool) {
if p.erroring {
return
}
formatter.Format(p, verb)
return
}
- // Must not touch flags before Formatter looks at them.
- if plus {
- p.fmt.plus = false
- }
// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
if p.fmt.sharpV {
if stringer, ok := p.arg.(GoStringer); ok {
handled = true
- defer p.restoreSpecialFlags(p.clearSpecialFlags())
defer p.catchPanic(p.arg, verb)
// Print the result of GoString unadorned.
- p.fmtString(stringer.GoString(), 's')
+ p.fmt.fmt_s(stringer.GoString())
return
}
} else {
case error:
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.Error(), verb, plus, depth)
+ p.printArg(v.Error(), verb, depth)
return
case Stringer:
handled = true
defer p.catchPanic(p.arg, verb)
- p.printArg(v.String(), verb, plus, depth)
+ p.printArg(v.String(), verb, depth)
return
}
}
return false
}
-func (p *pp) printArg(arg interface{}, verb rune, plus bool, depth int) (wasString bool) {
+func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) {
p.arg = arg
p.value = reflect.Value{}
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(reflect.TypeOf(arg).String(), 's', false, 0)
+ p.printArg(reflect.TypeOf(arg).String(), 's', 0)
return false
case 'p':
p.fmtPointer(reflect.ValueOf(arg), verb)
return false
}
- // Clear flags for base formatters.
- // handleMethods needs them, so we must restore them later.
- // We could call handleMethods here and avoid this work, but
- // handleMethods is expensive enough to be worth delaying.
- oldPlus := p.fmt.plus
- if plus {
- p.fmt.plus = false
- }
-
// Some types can be done without reflection.
switch f := arg.(type) {
case bool:
p.fmtBytes(f, verb, nil, depth)
wasString = verb == 's'
default:
- // Restore flags in case handleMethods finds a Formatter.
- p.fmt.plus = oldPlus
// If the type is not simple, it might have methods.
- if handled := p.handleMethods(verb, plus, depth); handled {
+ if handled := p.handleMethods(verb, depth); handled {
return false
}
// Need to use reflection
- return p.printReflectValue(reflect.ValueOf(arg), verb, plus, depth)
+ return p.printReflectValue(reflect.ValueOf(arg), verb, depth)
}
p.arg = nil
return
}
// printValue is like printArg but starts with a reflect value, not an interface{} value.
-func (p *pp) printValue(value reflect.Value, verb rune, plus bool, depth int) (wasString bool) {
+func (p *pp) printValue(value reflect.Value, verb rune, depth int) (wasString bool) {
if !value.IsValid() {
if verb == 'T' || verb == 'v' {
p.buf.Write(nilAngleBytes)
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
case 'T':
- p.printArg(value.Type().String(), 's', false, 0)
+ p.printArg(value.Type().String(), 's', 0)
return false
case 'p':
p.fmtPointer(value, verb)
if value.CanInterface() {
p.arg = value.Interface()
}
- if handled := p.handleMethods(verb, plus, depth); handled {
+ if handled := p.handleMethods(verb, depth); handled {
return false
}
- return p.printReflectValue(value, verb, plus, depth)
+ return p.printReflectValue(value, verb, depth)
}
var byteType = reflect.TypeOf(byte(0))
// printReflectValue is the fallback for both printArg and printValue.
// It uses reflect to print the value.
-func (p *pp) printReflectValue(value reflect.Value, verb rune, plus bool, depth int) (wasString bool) {
+func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasString bool) {
oldValue := p.value
p.value = value
BigSwitch:
p.buf.WriteByte(' ')
}
}
- p.printValue(key, verb, plus, depth+1)
+ p.printValue(key, verb, depth+1)
p.buf.WriteByte(':')
- p.printValue(f.MapIndex(key), verb, plus, depth+1)
+ p.printValue(f.MapIndex(key), verb, depth+1)
}
if p.fmt.sharpV {
p.buf.WriteByte('}')
p.buf.WriteByte(' ')
}
}
- if plus || p.fmt.sharpV {
+ if p.fmt.plusV || p.fmt.sharpV {
if f := t.Field(i); f.Name != "" {
p.buf.WriteString(f.Name)
p.buf.WriteByte(':')
}
}
- p.printValue(getField(v, i), verb, plus, depth+1)
+ p.printValue(getField(v, i), verb, depth+1)
}
p.buf.WriteByte('}')
case reflect.Interface:
p.buf.Write(nilAngleBytes)
}
} else {
- wasString = p.printValue(value, verb, plus, depth+1)
+ wasString = p.printValue(value, verb, depth+1)
}
case reflect.Array, reflect.Slice:
// Byte slices are special:
p.buf.WriteByte(' ')
}
}
- p.printValue(f.Index(i), verb, plus, depth+1)
+ p.printValue(f.Index(i), verb, depth+1)
}
if p.fmt.sharpV {
p.buf.WriteByte('}')
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, depth+1)
+ p.printValue(a, verb, depth+1)
break BigSwitch
case reflect.Struct:
p.buf.WriteByte('&')
- p.printValue(a, verb, plus, depth+1)
+ p.printValue(a, verb, depth+1)
break BigSwitch
}
}
arg := a[argNum]
argNum++
- if c == 'v' && p.fmt.sharp {
- // Go syntax. Set the flag in the fmt and clear the sharp flag.
- p.fmt.sharp = false
- p.fmt.sharpV = true
+ if c == 'v' {
+ if p.fmt.sharp {
+ // Go syntax. Set the flag in the fmt and clear the sharp flag.
+ p.fmt.sharp = false
+ p.fmt.sharpV = true
+ }
+ if p.fmt.plus {
+ // Struct-field syntax. Set the flag in the fmt and clear the plus flag.
+ p.fmt.plus = false
+ p.fmt.plusV = true
+ }
}
- plus := c == 'v' && p.fmt.plus
- p.printArg(arg, c, plus, 0)
+ p.printArg(arg, c, 0)
}
// Check for extra arguments unless the call accessed the arguments
p.buf.WriteString(reflect.TypeOf(arg).String())
p.buf.WriteByte('=')
}
- p.printArg(arg, 'v', false, 0)
+ p.printArg(arg, 'v', 0)
if argNum+1 < len(a) {
p.buf.Write(commaSpaceBytes)
}
p.buf.WriteByte(' ')
}
}
- prevString = p.printArg(arg, 'v', false, 0)
+ prevString = p.printArg(arg, 'v', 0)
}
if addnewline {
p.buf.WriteByte('\n')