Add config pointers to format and dump states.

This paves the way to support individual configuration options through a
separate type while still providing the simple global config and package
level methods.
This commit is contained in:
Dave Collins 2013-01-10 20:31:03 -06:00
parent 04998fcda3
commit 184d118062
3 changed files with 19 additions and 17 deletions

View File

@ -125,7 +125,7 @@ func catchPanic(w io.Writer, v reflect.Value) {
//
// It handles panics in any called methods by catching and displaying the error
// as the formatted value.
func handleMethods(w io.Writer, v reflect.Value) (handled bool) {
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
// We need an interface to check if the type implements the error or
// Stringer interface. However, the reflect package won't give us an
// an interface on certain things like unexported struct fields in order
@ -142,7 +142,7 @@ func handleMethods(w io.Writer, v reflect.Value) (handled bool) {
// Stringer interface with a pointer receiver should not be mutating their
// state inside these interface methods.
var viface interface{}
if !Config.DisablePointerMethods {
if !cs.DisablePointerMethods {
if !v.CanAddr() {
v = unsafeReflectValue(v)
}

View File

@ -32,16 +32,17 @@ type dumpState struct {
pointers map[uintptr]int
ignoreNextType bool
ignoreNextPad bool
cs *ConfigState
}
// pad performs indentation according to the depth level and Config.Indent
// pad performs indentation according to the depth level and cs.Indent
// option.
func (d *dumpState) pad() {
if d.ignoreNextPad {
d.ignoreNextPad = false
return
}
d.w.Write(bytes.Repeat([]byte(Config.Indent), d.depth))
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
}
// dumpPtr handles formatting of pointers by indirecting them as necessary.
@ -146,9 +147,9 @@ func (d *dumpState) dump(v reflect.Value) {
// Call error/Stringer interfaces if they exist and the handle methods flag
// is enabled
if !Config.DisableMethods {
if !d.cs.DisableMethods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(d.w, v); handled {
if handled := handleMethods(d.cs, d.w, v); handled {
return
}
}
@ -182,7 +183,7 @@ func (d *dumpState) dump(v reflect.Value) {
case reflect.Array, reflect.Slice:
d.w.Write(openBraceNewlineBytes)
d.depth++
if (Config.MaxDepth != 0) && (d.depth > Config.MaxDepth) {
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.pad()
d.w.Write(maxNewlineBytes)
} else {
@ -213,7 +214,7 @@ func (d *dumpState) dump(v reflect.Value) {
case reflect.Map:
d.w.Write(openBraceNewlineBytes)
d.depth++
if (Config.MaxDepth != 0) && (d.depth > Config.MaxDepth) {
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.pad()
d.w.Write(maxNewlineBytes)
} else {
@ -238,7 +239,7 @@ func (d *dumpState) dump(v reflect.Value) {
case reflect.Struct:
d.w.Write(openBraceNewlineBytes)
d.depth++
if (Config.MaxDepth != 0) && (d.depth > Config.MaxDepth) {
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.pad()
d.w.Write(maxNewlineBytes)
} else {
@ -291,7 +292,7 @@ func Fdump(w io.Writer, a ...interface{}) {
continue
}
d := dumpState{w: w}
d := dumpState{w: w, cs: &Config}
d.pointers = make(map[uintptr]int)
d.dump(reflect.ValueOf(arg))
d.w.Write(newlineBytes)

View File

@ -37,6 +37,7 @@ type formatState struct {
depth int
pointers map[uintptr]int // Holds map of points and depth they were seen at
fs fmt.State
cs *ConfigState
}
// buildDefaultFormat recreates the original format string without precision
@ -175,9 +176,9 @@ func (f *formatState) format(v reflect.Value) {
// Call error/Stringer interfaces if they exist and the handle methods
// flag is enabled.
kind := v.Kind()
if !Config.DisableMethods {
if !f.cs.DisableMethods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(&f.buffer, v); handled {
if handled := handleMethods(f.cs, &f.buffer, v); handled {
return
}
}
@ -211,7 +212,7 @@ func (f *formatState) format(v reflect.Value) {
case reflect.Array, reflect.Slice:
f.buffer.WriteRune('[')
f.depth++
if (Config.MaxDepth != 0) && (f.depth > Config.MaxDepth) {
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes)
} else {
numEntries := v.Len()
@ -234,7 +235,7 @@ func (f *formatState) format(v reflect.Value) {
case reflect.Map:
f.buffer.Write(openMapBytes)
f.depth++
if (Config.MaxDepth != 0) && (f.depth > Config.MaxDepth) {
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes)
} else {
keys := v.MapKeys()
@ -257,7 +258,7 @@ func (f *formatState) format(v reflect.Value) {
numFields := v.NumField()
f.buffer.WriteRune('{')
f.depth++
if (Config.MaxDepth != 0) && (f.depth > Config.MaxDepth) {
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.buffer.Write(maxShortBytes)
} else {
vt := v.Type()
@ -331,8 +332,8 @@ Typically this function shouldn't be called directly. It is much easier to make
use of the custom formatter by calling one of the convenience functions such as
Printf, Println, or Printf.
*/
func NewFormatter(v interface{}) (f fmt.Formatter) {
fs := &formatState{value: v}
func NewFormatter(v interface{}) fmt.Formatter {
fs := &formatState{value: v, cs: &Config}
fs.pointers = make(map[uintptr]int)
return fs
}