diff options
Diffstat (limited to 'src/pkg/fmt/print.go')
-rw-r--r-- | src/pkg/fmt/print.go | 245 |
1 files changed, 151 insertions, 94 deletions
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go index c18a8ea38d..1042315ed9 100644 --- a/src/pkg/fmt/print.go +++ b/src/pkg/fmt/print.go @@ -259,10 +259,8 @@ func Sprintln(a ...interface{}) string { // the thing inside the interface, not the interface itself. func getField(v reflect.Value, i int) reflect.Value { val := v.Field(i) - if i := val; i.Kind() == reflect.Interface { - if inter := i.Interface(); inter != nil { - return reflect.ValueOf(inter) - } + if val.Kind() == reflect.Interface && !val.IsNil() { + val = val.Elem() } return val } @@ -289,27 +287,32 @@ func (p *pp) unknownType(v interface{}) { p.buf.WriteByte('?') } -func (p *pp) badVerb(verb int, val interface{}) { +func (p *pp) badVerb(verb int, val interface{}, val1 reflect.Value) { p.add('%') p.add('!') p.add(verb) p.add('(') - if val == nil { - p.buf.Write(nilAngleBytes) - } else { + switch { + case val != nil: p.buf.WriteString(reflect.TypeOf(val).String()) p.add('=') p.printField(val, 'v', false, false, 0) + case val1.IsValid(): + p.buf.WriteString(val1.Type().String()) + p.add('=') + p.printValue(val1, 'v', false, false, 0) + default: + p.buf.Write(nilAngleBytes) } p.add(')') } -func (p *pp) fmtBool(v bool, verb int, value interface{}) { +func (p *pp) fmtBool(v bool, verb int, value interface{}, value1 reflect.Value) { switch verb { case 't', 'v': p.fmt.fmt_boolean(v) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } @@ -323,7 +326,7 @@ func (p *pp) fmtC(c int64) { p.fmt.pad(p.runeBuf[0:w]) } -func (p *pp) fmtInt64(v int64, verb int, value interface{}) { +func (p *pp) fmtInt64(v int64, verb int, value interface{}, value1 reflect.Value) { switch verb { case 'b': p.fmt.integer(v, 2, signed, ldigits) @@ -337,7 +340,7 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) { if 0 <= v && v <= unicode.MaxRune { p.fmt.fmt_qc(v) } else { - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } case 'x': p.fmt.integer(v, 16, signed, ldigits) @@ -346,7 +349,7 @@ func (p *pp) fmtInt64(v int64, verb int, value interface{}) { case 'X': p.fmt.integer(v, 16, signed, udigits) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } @@ -376,7 +379,7 @@ func (p *pp) fmtUnicode(v int64) { p.fmt.precPresent = precPresent } -func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { +func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}, value1 reflect.Value) { switch verb { case 'b': p.fmt.integer(int64(v), 2, unsigned, ldigits) @@ -396,7 +399,7 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { if 0 <= v && v <= unicode.MaxRune { p.fmt.fmt_qc(int64(v)) } else { - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } case 'x': p.fmt.integer(int64(v), 16, unsigned, ldigits) @@ -405,11 +408,11 @@ func (p *pp) fmtUint64(v uint64, verb int, goSyntax bool, value interface{}) { case 'U': p.fmtUnicode(int64(v)) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtFloat32(v float32, verb int, value interface{}) { +func (p *pp) fmtFloat32(v float32, verb int, value interface{}, value1 reflect.Value) { switch verb { case 'b': p.fmt.fmt_fb32(v) @@ -424,11 +427,11 @@ func (p *pp) fmtFloat32(v float32, verb int, value interface{}) { case 'G': p.fmt.fmt_G32(v) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtFloat64(v float64, verb int, value interface{}) { +func (p *pp) fmtFloat64(v float64, verb int, value interface{}, value1 reflect.Value) { switch verb { case 'b': p.fmt.fmt_fb64(v) @@ -443,33 +446,33 @@ func (p *pp) fmtFloat64(v float64, verb int, value interface{}) { case 'G': p.fmt.fmt_G64(v) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtComplex64(v complex64, verb int, value interface{}) { +func (p *pp) fmtComplex64(v complex64, verb int, value interface{}, value1 reflect.Value) { switch verb { case 'e', 'E', 'f', 'F', 'g', 'G': p.fmt.fmt_c64(v, verb) case 'v': p.fmt.fmt_c64(v, 'g') default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtComplex128(v complex128, verb int, value interface{}) { +func (p *pp) fmtComplex128(v complex128, verb int, value interface{}, value1 reflect.Value) { switch verb { case 'e', 'E', 'f', 'F', 'g', 'G': p.fmt.fmt_c128(v, verb) case 'v': p.fmt.fmt_c128(v, 'g') default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) { +func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}, value1 reflect.Value) { switch verb { case 'v': if goSyntax { @@ -486,11 +489,11 @@ func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) { case 'q': p.fmt.fmt_q(v) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } -func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}) { +func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}, value1 reflect.Value) { if verb == 'v' || verb == 'd' { if goSyntax { p.buf.Write(bytesBytes) @@ -525,7 +528,7 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf case 'q': p.fmt.fmt_q(s) default: - p.badVerb(verb, value) + p.badVerb(verb, value, value1) } } @@ -535,12 +538,12 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: u = value.Pointer() default: - p.badVerb(verb, field) + p.badVerb(verb, field, value) return } if goSyntax { p.add('(') - p.buf.WriteString(reflect.TypeOf(field).String()) + p.buf.WriteString(value.Type().String()) p.add(')') p.add('(') if u == 0 { @@ -561,12 +564,48 @@ var ( uintptrBits = reflect.TypeOf(uintptr(0)).Bits() ) +func (p *pp) handleMethods(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString, handled bool) { + // Is it a Formatter? + if formatter, ok := field.(Formatter); ok { + handled = true + wasString = false + 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 field knows how to supply it, take care of it now. + if goSyntax { + p.fmt.sharp = false + if stringer, ok := field.(GoStringer); ok { + wasString = false + handled = true + // Print the result of GoString unadorned. + p.fmtString(stringer.GoString(), 's', false, field, reflect.Value{}) + return + } + } else { + // Is it a Stringer? + if stringer, ok := field.(Stringer); ok { + wasString = false + handled = true + p.printField(stringer.String(), verb, plus, false, depth) + return + } + } + handled = false + return +} + func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) { if field == nil { if verb == 'T' || verb == 'v' { p.buf.Write(nilAngleBytes) } else { - p.badVerb(verb, field) + p.badVerb(verb, field, reflect.Value{}) } return false } @@ -581,115 +620,133 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax) return false } - // Is it a Formatter? - if formatter, ok := field.(Formatter); ok { - formatter.Format(p, verb) - return false // this value is not a string - } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } - // If we're doing Go syntax and the field knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false - if stringer, ok := field.(GoStringer); ok { - // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false, field) - return false // this value is not a string - } - } else { - // Is it a Stringer? - if stringer, ok := field.(Stringer); ok { - p.printField(stringer.String(), verb, plus, false, depth) - return false // this value is not a string - } + if wasString, handled := p.handleMethods(field, verb, plus, goSyntax, depth); handled { + return wasString } // Some types can be done without reflection. switch f := field.(type) { case bool: - p.fmtBool(f, verb, field) + p.fmtBool(f, verb, field, reflect.Value{}) return false case float32: - p.fmtFloat32(f, verb, field) + p.fmtFloat32(f, verb, field, reflect.Value{}) return false case float64: - p.fmtFloat64(f, verb, field) + p.fmtFloat64(f, verb, field, reflect.Value{}) return false case complex64: - p.fmtComplex64(complex64(f), verb, field) + p.fmtComplex64(complex64(f), verb, field, reflect.Value{}) return false case complex128: - p.fmtComplex128(f, verb, field) + p.fmtComplex128(f, verb, field, reflect.Value{}) return false case int: - p.fmtInt64(int64(f), verb, field) + p.fmtInt64(int64(f), verb, field, reflect.Value{}) return false case int8: - p.fmtInt64(int64(f), verb, field) + p.fmtInt64(int64(f), verb, field, reflect.Value{}) return false case int16: - p.fmtInt64(int64(f), verb, field) + p.fmtInt64(int64(f), verb, field, reflect.Value{}) return false case int32: - p.fmtInt64(int64(f), verb, field) + p.fmtInt64(int64(f), verb, field, reflect.Value{}) return false case int64: - p.fmtInt64(f, verb, field) + p.fmtInt64(f, verb, field, reflect.Value{}) return false case uint: - p.fmtUint64(uint64(f), verb, goSyntax, field) + p.fmtUint64(uint64(f), verb, goSyntax, field, reflect.Value{}) return false case uint8: - p.fmtUint64(uint64(f), verb, goSyntax, field) + p.fmtUint64(uint64(f), verb, goSyntax, field, reflect.Value{}) return false case uint16: - p.fmtUint64(uint64(f), verb, goSyntax, field) + p.fmtUint64(uint64(f), verb, goSyntax, field, reflect.Value{}) return false case uint32: - p.fmtUint64(uint64(f), verb, goSyntax, field) + p.fmtUint64(uint64(f), verb, goSyntax, field, reflect.Value{}) return false case uint64: - p.fmtUint64(f, verb, goSyntax, field) + p.fmtUint64(f, verb, goSyntax, field, reflect.Value{}) return false case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax, field) + p.fmtUint64(uint64(f), verb, goSyntax, field, reflect.Value{}) return false case string: - p.fmtString(f, verb, goSyntax, field) + p.fmtString(f, verb, goSyntax, field, reflect.Value{}) return verb == 's' || verb == 'v' case []byte: - p.fmtBytes(f, verb, goSyntax, depth, field) + p.fmtBytes(f, verb, goSyntax, depth, field, reflect.Value{}) return verb == 's' } // Need to use reflection - value := reflect.ValueOf(field) + return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth) +} + +// printValue is like printField but starts with a reflect value, not an interface{} value. +func (p *pp) printValue(value reflect.Value, verb int, plus, goSyntax bool, depth int) (wasString bool) { + if !value.IsValid() { + if verb == 'T' || verb == 'v' { + p.buf.Write(nilAngleBytes) + } else { + p.badVerb(verb, nil, value) + } + return false + } + + // Special processing considerations. + // %T (the value's type) and %p (its address) are special; we always do them first. + switch verb { + case 'T': + p.printField(value.Type().String(), 's', false, false, 0) + return false + case 'p': + p.fmtPointer(nil, value, verb, goSyntax) + return false + } + // Handle values with special methods. + // Call always, even when field == nil, because handleMethods clears p.fmt.plus for us. + var field interface{} + if value.CanInterface() { + field = value.Interface() + } + if wasString, handled := p.handleMethods(field, verb, plus, goSyntax, depth); handled { + return wasString + } + + return p.printReflectValue(value, verb, plus, goSyntax, depth) +} + +// printReflectValue is the fallback for both printField and printValue. +// It uses reflect to print the value. +func (p *pp) printReflectValue(value reflect.Value, verb int, plus, goSyntax bool, depth int) (wasString bool) { BigSwitch: switch f := value; f.Kind() { case reflect.Bool: - p.fmtBool(f.Bool(), verb, field) + p.fmtBool(f.Bool(), verb, nil, value) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p.fmtInt64(f.Int(), verb, field) + p.fmtInt64(f.Int(), verb, nil, value) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(uint64(f.Uint()), verb, goSyntax, field) + p.fmtUint64(uint64(f.Uint()), verb, goSyntax, nil, value) case reflect.Float32, reflect.Float64: if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Float()), verb, field) + p.fmtFloat32(float32(f.Float()), verb, nil, value) } else { - p.fmtFloat64(float64(f.Float()), verb, field) + p.fmtFloat64(float64(f.Float()), verb, nil, value) } case reflect.Complex64, reflect.Complex128: if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Complex()), verb, field) + p.fmtComplex64(complex64(f.Complex()), verb, nil, value) } else { - p.fmtComplex128(complex128(f.Complex()), verb, field) + p.fmtComplex128(complex128(f.Complex()), verb, nil, value) } case reflect.String: - p.fmtString(f.String(), verb, goSyntax, field) + p.fmtString(f.String(), verb, goSyntax, nil, value) case reflect.Map: if goSyntax { p.buf.WriteString(f.Type().String()) @@ -706,9 +763,9 @@ BigSwitch: p.buf.WriteByte(' ') } } - p.printField(key.Interface(), verb, plus, goSyntax, depth+1) + p.printValue(key, verb, plus, goSyntax, depth+1) p.buf.WriteByte(':') - p.printField(f.MapIndex(key).Interface(), verb, plus, goSyntax, depth+1) + p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1) } if goSyntax { p.buf.WriteByte('}') @@ -717,7 +774,7 @@ BigSwitch: } case reflect.Struct: if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) + p.buf.WriteString(value.Type().String()) } p.add('{') v := f @@ -736,20 +793,20 @@ BigSwitch: p.buf.WriteByte(':') } } - p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1) + p.printValue(getField(v, i), verb, plus, goSyntax, depth+1) } p.buf.WriteByte('}') case reflect.Interface: value := f.Elem() if !value.IsValid() { if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) + p.buf.WriteString(value.Type().String()) p.buf.Write(nilParenBytes) } else { p.buf.Write(nilAngleBytes) } } else { - return p.printField(value.Interface(), verb, plus, goSyntax, depth+1) + return p.printValue(value, verb, plus, goSyntax, depth+1) } case reflect.Array, reflect.Slice: // Byte slices are special. @@ -765,11 +822,11 @@ BigSwitch: for i := range bytes { bytes[i] = byte(f.Index(i).Uint()) } - p.fmtBytes(bytes, verb, goSyntax, depth, field) + p.fmtBytes(bytes, verb, goSyntax, depth, nil, value) return verb == 's' } if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) + p.buf.WriteString(value.Type().String()) p.buf.WriteByte('{') } else { p.buf.WriteByte('[') @@ -782,7 +839,7 @@ BigSwitch: p.buf.WriteByte(' ') } } - p.printField(f.Index(i).Interface(), verb, plus, goSyntax, depth+1) + p.printValue(f.Index(i), verb, plus, goSyntax, depth+1) } if goSyntax { p.buf.WriteByte('}') @@ -797,17 +854,17 @@ BigSwitch: switch a := f.Elem(); a.Kind() { case reflect.Array, reflect.Slice: p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) + p.printValue(a, verb, plus, goSyntax, depth+1) break BigSwitch case reflect.Struct: p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) + p.printValue(a, verb, plus, goSyntax, depth+1) break BigSwitch } } if goSyntax { p.buf.WriteByte('(') - p.buf.WriteString(reflect.TypeOf(field).String()) + p.buf.WriteString(value.Type().String()) p.buf.WriteByte(')') p.buf.WriteByte('(') if v == 0 { @@ -824,7 +881,7 @@ BigSwitch: } p.fmt0x64(uint64(v), true) case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(field, value, verb, goSyntax) + p.fmtPointer(nil, value, verb, goSyntax) default: p.unknownType(f) } |