Use writer directly in formatter.

Write directly to the fmt.State output writer to avoid the overhead
of a buffer in the formatter code.
This commit is contained in:
Dave Collins 2013-01-14 00:23:18 -06:00
parent 638b62b9f5
commit bd6dd81322
2 changed files with 44 additions and 45 deletions

View File

@ -76,8 +76,8 @@ var (
openBraceBytes = []byte("{") openBraceBytes = []byte("{")
openBraceNewlineBytes = []byte("{\n") openBraceNewlineBytes = []byte("{\n")
closeBraceBytes = []byte("}") closeBraceBytes = []byte("}")
closeBraceNewlinBytes = []byte("}\n")
asteriskBytes = []byte("*") asteriskBytes = []byte("*")
colonBytes = []byte(":")
colonSpaceBytes = []byte(": ") colonSpaceBytes = []byte(": ")
openParenBytes = []byte("(") openParenBytes = []byte("(")
closeParenBytes = []byte(")") closeParenBytes = []byte(")")
@ -89,6 +89,8 @@ var (
circularBytes = []byte("<already shown>") circularBytes = []byte("<already shown>")
circularShortBytes = []byte("<shown>") circularShortBytes = []byte("<shown>")
invalidAngleBytes = []byte("<invalid>") invalidAngleBytes = []byte("<invalid>")
openBracketBytes = []byte("[")
closeBracketBytes = []byte("]")
percentBytes = []byte("%") percentBytes = []byte("%")
precisionBytes = []byte(".") precisionBytes = []byte(".")
openAngleBytes = []byte("<") openAngleBytes = []byte("<")

View File

@ -33,7 +33,6 @@ const supportedFlags = "0-+# "
// in standard fmt package printing calls. // in standard fmt package printing calls.
type formatState struct { type formatState struct {
value interface{} value interface{}
buffer bytes.Buffer
depth int depth int
pointers map[uintptr]int // Holds map of points and depth they were seen at pointers map[uintptr]int // Holds map of points and depth they were seen at
fs fmt.State fs fmt.State
@ -88,9 +87,9 @@ func (f *formatState) constructOrigFormat(verb rune) (format string) {
// formatPtr handles formatting of pointers by indirecting them as necessary. // formatPtr handles formatting of pointers by indirecting them as necessary.
func (f *formatState) formatPtr(v reflect.Value) { func (f *formatState) formatPtr(v reflect.Value) {
// Display nil if top level poiner is nil. // Display nil if top level pointer is nil.
if v.IsNil() { if v.IsNil() {
f.buffer.Write(nilAngleBytes) f.fs.Write(nilAngleBytes)
return return
} }
@ -139,29 +138,29 @@ func (f *formatState) formatPtr(v reflect.Value) {
} }
// Display indirection level. // Display indirection level.
f.buffer.Write(openAngleBytes) f.fs.Write(openAngleBytes)
f.buffer.WriteString(strings.Repeat("*", indirects)) f.fs.Write([]byte(strings.Repeat("*", indirects)))
f.buffer.Write(closeAngleBytes) f.fs.Write(closeAngleBytes)
// Display pointer information depending on flags. // Display pointer information depending on flags.
if plusSyntax && (len(pointerChain) > 0) { if plusSyntax && (len(pointerChain) > 0) {
f.buffer.Write(openParenBytes) f.fs.Write(openParenBytes)
for i, addr := range pointerChain { for i, addr := range pointerChain {
if i > 0 { if i > 0 {
f.buffer.Write(pointerChainBytes) f.fs.Write(pointerChainBytes)
} }
printHexPtr(&f.buffer, addr) printHexPtr(f.fs, addr)
} }
f.buffer.Write(closeParenBytes) f.fs.Write(closeParenBytes)
} }
// Display dereferenced value. // Display dereferenced value.
switch { switch {
case nilFound == true: case nilFound == true:
f.buffer.Write(nilAngleBytes) f.fs.Write(nilAngleBytes)
case cycleFound == true: case cycleFound == true:
f.buffer.Write(circularShortBytes) f.fs.Write(circularShortBytes)
default: default:
f.format(ve) f.format(ve)
@ -173,12 +172,12 @@ func (f *formatState) formatPtr(v reflect.Value) {
// dealing with and formats it appropriately. It is a recursive function, // dealing with and formats it appropriately. It is a recursive function,
// however circular data structures are detected and handled properly. // however circular data structures are detected and handled properly.
func (f *formatState) format(v reflect.Value) { func (f *formatState) format(v reflect.Value) {
// Call error/Stringer interfaces if they exist and the handle methods // Call Stringer/error interfaces if they exist and the handle methods
// flag is enabled. // flag is enabled.
kind := v.Kind() kind := v.Kind()
if !f.cs.DisableMethods { if !f.cs.DisableMethods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) { if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(f.cs, &f.buffer, v); handled { if handled := handleMethods(f.cs, f.fs, v); handled {
return return
} }
} }
@ -186,111 +185,111 @@ func (f *formatState) format(v reflect.Value) {
switch kind { switch kind {
case reflect.Invalid: case reflect.Invalid:
f.buffer.Write(invalidAngleBytes) f.fs.Write(invalidAngleBytes)
case reflect.Bool: case reflect.Bool:
printBool(&f.buffer, v.Bool()) printBool(f.fs, v.Bool())
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
printInt(&f.buffer, v.Int()) printInt(f.fs, v.Int())
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
printUint(&f.buffer, v.Uint()) printUint(f.fs, v.Uint())
case reflect.Float32: case reflect.Float32:
printFloat(&f.buffer, v.Float(), 32) printFloat(f.fs, v.Float(), 32)
case reflect.Float64: case reflect.Float64:
printFloat(&f.buffer, v.Float(), 64) printFloat(f.fs, v.Float(), 64)
case reflect.Complex64: case reflect.Complex64:
printComplex(&f.buffer, v.Complex(), 32) printComplex(f.fs, v.Complex(), 32)
case reflect.Complex128: case reflect.Complex128:
printComplex(&f.buffer, v.Complex(), 64) printComplex(f.fs, v.Complex(), 64)
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
f.buffer.WriteRune('[') f.fs.Write(openBracketBytes)
f.depth++ f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes) f.fs.Write(maxShortBytes)
} else { } else {
numEntries := v.Len() numEntries := v.Len()
for i := 0; i < numEntries; i++ { for i := 0; i < numEntries; i++ {
if i > 0 { if i > 0 {
f.buffer.WriteRune(' ') f.fs.Write(spaceBytes)
} }
f.format(unpackValue(v.Index(i))) f.format(unpackValue(v.Index(i)))
} }
} }
f.depth-- f.depth--
f.buffer.WriteRune(']') f.fs.Write(closeBracketBytes)
case reflect.String: case reflect.String:
f.buffer.WriteString(v.String()) f.fs.Write([]byte(v.String()))
case reflect.Interface: case reflect.Interface:
// Do nothing. We should never get here due to unpackValue calls // Do nothing. We should never get here due to unpackValue calls
case reflect.Map: case reflect.Map:
f.buffer.Write(openMapBytes) f.fs.Write(openMapBytes)
f.depth++ f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes) f.fs.Write(maxShortBytes)
} else { } else {
keys := v.MapKeys() keys := v.MapKeys()
for i, key := range keys { for i, key := range keys {
if i > 0 { if i > 0 {
f.buffer.WriteRune(' ') f.fs.Write(spaceBytes)
} }
f.format(unpackValue(key)) f.format(unpackValue(key))
f.buffer.WriteRune(':') f.fs.Write(colonBytes)
f.format(unpackValue(v.MapIndex(key))) f.format(unpackValue(v.MapIndex(key)))
} }
} }
f.depth-- f.depth--
f.buffer.Write(closeMapBytes) f.fs.Write(closeMapBytes)
case reflect.Ptr: case reflect.Ptr:
f.formatPtr(v) f.formatPtr(v)
case reflect.Struct: case reflect.Struct:
numFields := v.NumField() numFields := v.NumField()
f.buffer.WriteRune('{') f.fs.Write(openBraceBytes)
f.depth++ f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes) f.fs.Write(maxShortBytes)
} else { } else {
vt := v.Type() vt := v.Type()
for i := 0; i < numFields; i++ { for i := 0; i < numFields; i++ {
if i > 0 { if i > 0 {
f.buffer.WriteRune(' ') f.fs.Write(spaceBytes)
} }
vtf := vt.Field(i) vtf := vt.Field(i)
if f.fs.Flag('+') { if f.fs.Flag('+') {
f.buffer.WriteString(vtf.Name) f.fs.Write([]byte(vtf.Name))
f.buffer.WriteRune(':') f.fs.Write(colonBytes)
} }
f.format(unpackValue(v.Field(i))) f.format(unpackValue(v.Field(i)))
} }
} }
f.depth-- f.depth--
f.buffer.WriteRune('}') f.fs.Write(closeBraceBytes)
case reflect.Uintptr: case reflect.Uintptr:
printHexPtr(&f.buffer, uintptr(v.Uint())) printHexPtr(f.fs, uintptr(v.Uint()))
case reflect.UnsafePointer, reflect.Chan, reflect.Func: case reflect.UnsafePointer, reflect.Chan, reflect.Func:
printHexPtr(&f.buffer, v.Pointer()) printHexPtr(f.fs, v.Pointer())
// There were not any other types at the time this code was written, but // There were not any other types at the time this code was written, but
// fall back to letting the default fmt package handle it if any get added. // fall back to letting the default fmt package handle it if any get added.
default: default:
format := f.buildDefaultFormat() format := f.buildDefaultFormat()
if v.CanInterface() { if v.CanInterface() {
f.buffer.WriteString(fmt.Sprintf(format, v.Interface())) fmt.Fprintf(f.fs, format, v.Interface())
} else { } else {
f.buffer.WriteString(fmt.Sprintf(format, v.String())) fmt.Fprintf(f.fs, format, v.String())
} }
} }
} }
@ -311,9 +310,7 @@ func (f *formatState) Format(fs fmt.State, verb rune) {
fmt.Fprint(fs, string(nilAngleBytes)) fmt.Fprint(fs, string(nilAngleBytes))
return return
} }
f.format(reflect.ValueOf(f.value)) f.format(reflect.ValueOf(f.value))
f.buffer.WriteTo(fs)
} }
// newFormatter is a helper function to consolidate the logic from the various // newFormatter is a helper function to consolidate the logic from the various