Blame vendor/github.com/davecgh/go-spew/spew/dump.go

Packit Service 4d2de5
/*
Packit Service 4d2de5
 * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
Packit Service 4d2de5
 *
Packit Service 4d2de5
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 4d2de5
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 4d2de5
 * copyright notice and this permission notice appear in all copies.
Packit Service 4d2de5
 *
Packit Service 4d2de5
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Packit Service 4d2de5
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Packit Service 4d2de5
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Packit Service 4d2de5
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit Service 4d2de5
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
Packit Service 4d2de5
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Packit Service 4d2de5
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit Service 4d2de5
 */
Packit Service 4d2de5
Packit Service 4d2de5
package spew
Packit Service 4d2de5
Packit Service 4d2de5
import (
Packit Service 4d2de5
	"bytes"
Packit Service 4d2de5
	"encoding/hex"
Packit Service 4d2de5
	"fmt"
Packit Service 4d2de5
	"io"
Packit Service 4d2de5
	"os"
Packit Service 4d2de5
	"reflect"
Packit Service 4d2de5
	"regexp"
Packit Service 4d2de5
	"strconv"
Packit Service 4d2de5
	"strings"
Packit Service 4d2de5
)
Packit Service 4d2de5
Packit Service 4d2de5
var (
Packit Service 4d2de5
	// uint8Type is a reflect.Type representing a uint8.  It is used to
Packit Service 4d2de5
	// convert cgo types to uint8 slices for hexdumping.
Packit Service 4d2de5
	uint8Type = reflect.TypeOf(uint8(0))
Packit Service 4d2de5
Packit Service 4d2de5
	// cCharRE is a regular expression that matches a cgo char.
Packit Service 4d2de5
	// It is used to detect character arrays to hexdump them.
Packit Service 4d2de5
	cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
Packit Service 4d2de5
Packit Service 4d2de5
	// cUnsignedCharRE is a regular expression that matches a cgo unsigned
Packit Service 4d2de5
	// char.  It is used to detect unsigned character arrays to hexdump
Packit Service 4d2de5
	// them.
Packit Service 4d2de5
	cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
Packit Service 4d2de5
Packit Service 4d2de5
	// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
Packit Service 4d2de5
	// It is used to detect uint8_t arrays to hexdump them.
Packit Service 4d2de5
	cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
Packit Service 4d2de5
)
Packit Service 4d2de5
Packit Service 4d2de5
// dumpState contains information about the state of a dump operation.
Packit Service 4d2de5
type dumpState struct {
Packit Service 4d2de5
	w                io.Writer
Packit Service 4d2de5
	depth            int
Packit Service 4d2de5
	pointers         map[uintptr]int
Packit Service 4d2de5
	ignoreNextType   bool
Packit Service 4d2de5
	ignoreNextIndent bool
Packit Service 4d2de5
	cs               *ConfigState
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// indent performs indentation according to the depth level and cs.Indent
Packit Service 4d2de5
// option.
Packit Service 4d2de5
func (d *dumpState) indent() {
Packit Service 4d2de5
	if d.ignoreNextIndent {
Packit Service 4d2de5
		d.ignoreNextIndent = false
Packit Service 4d2de5
		return
Packit Service 4d2de5
	}
Packit Service 4d2de5
	d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// unpackValue returns values inside of non-nil interfaces when possible.
Packit Service 4d2de5
// This is useful for data types like structs, arrays, slices, and maps which
Packit Service 4d2de5
// can contain varying types packed inside an interface.
Packit Service 4d2de5
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
Packit Service 4d2de5
	if v.Kind() == reflect.Interface && !v.IsNil() {
Packit Service 4d2de5
		v = v.Elem()
Packit Service 4d2de5
	}
Packit Service 4d2de5
	return v
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// dumpPtr handles formatting of pointers by indirecting them as necessary.
Packit Service 4d2de5
func (d *dumpState) dumpPtr(v reflect.Value) {
Packit Service 4d2de5
	// Remove pointers at or below the current depth from map used to detect
Packit Service 4d2de5
	// circular refs.
Packit Service 4d2de5
	for k, depth := range d.pointers {
Packit Service 4d2de5
		if depth >= d.depth {
Packit Service 4d2de5
			delete(d.pointers, k)
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Keep list of all dereferenced pointers to show later.
Packit Service 4d2de5
	pointerChain := make([]uintptr, 0)
Packit Service 4d2de5
Packit Service 4d2de5
	// Figure out how many levels of indirection there are by dereferencing
Packit Service 4d2de5
	// pointers and unpacking interfaces down the chain while detecting circular
Packit Service 4d2de5
	// references.
Packit Service 4d2de5
	nilFound := false
Packit Service 4d2de5
	cycleFound := false
Packit Service 4d2de5
	indirects := 0
Packit Service 4d2de5
	ve := v
Packit Service 4d2de5
	for ve.Kind() == reflect.Ptr {
Packit Service 4d2de5
		if ve.IsNil() {
Packit Service 4d2de5
			nilFound = true
Packit Service 4d2de5
			break
Packit Service 4d2de5
		}
Packit Service 4d2de5
		indirects++
Packit Service 4d2de5
		addr := ve.Pointer()
Packit Service 4d2de5
		pointerChain = append(pointerChain, addr)
Packit Service 4d2de5
		if pd, ok := d.pointers[addr]; ok && pd < d.depth {
Packit Service 4d2de5
			cycleFound = true
Packit Service 4d2de5
			indirects--
Packit Service 4d2de5
			break
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.pointers[addr] = d.depth
Packit Service 4d2de5
Packit Service 4d2de5
		ve = ve.Elem()
Packit Service 4d2de5
		if ve.Kind() == reflect.Interface {
Packit Service 4d2de5
			if ve.IsNil() {
Packit Service 4d2de5
				nilFound = true
Packit Service 4d2de5
				break
Packit Service 4d2de5
			}
Packit Service 4d2de5
			ve = ve.Elem()
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Display type information.
Packit Service 4d2de5
	d.w.Write(openParenBytes)
Packit Service 4d2de5
	d.w.Write(bytes.Repeat(asteriskBytes, indirects))
Packit Service 4d2de5
	d.w.Write([]byte(ve.Type().String()))
Packit Service 4d2de5
	d.w.Write(closeParenBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	// Display pointer information.
Packit Service 4d2de5
	if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
Packit Service 4d2de5
		d.w.Write(openParenBytes)
Packit Service 4d2de5
		for i, addr := range pointerChain {
Packit Service 4d2de5
			if i > 0 {
Packit Service 4d2de5
				d.w.Write(pointerChainBytes)
Packit Service 4d2de5
			}
Packit Service 4d2de5
			printHexPtr(d.w, addr)
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.w.Write(closeParenBytes)
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Display dereferenced value.
Packit Service 4d2de5
	d.w.Write(openParenBytes)
Packit Service 4d2de5
	switch {
Packit Service 4d2de5
	case nilFound == true:
Packit Service 4d2de5
		d.w.Write(nilAngleBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	case cycleFound == true:
Packit Service 4d2de5
		d.w.Write(circularBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	default:
Packit Service 4d2de5
		d.ignoreNextType = true
Packit Service 4d2de5
		d.dump(ve)
Packit Service 4d2de5
	}
Packit Service 4d2de5
	d.w.Write(closeParenBytes)
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// dumpSlice handles formatting of arrays and slices.  Byte (uint8 under
Packit Service 4d2de5
// reflection) arrays and slices are dumped in hexdump -C fashion.
Packit Service 4d2de5
func (d *dumpState) dumpSlice(v reflect.Value) {
Packit Service 4d2de5
	// Determine whether this type should be hex dumped or not.  Also,
Packit Service 4d2de5
	// for types which should be hexdumped, try to use the underlying data
Packit Service 4d2de5
	// first, then fall back to trying to convert them to a uint8 slice.
Packit Service 4d2de5
	var buf []uint8
Packit Service 4d2de5
	doConvert := false
Packit Service 4d2de5
	doHexDump := false
Packit Service 4d2de5
	numEntries := v.Len()
Packit Service 4d2de5
	if numEntries > 0 {
Packit Service 4d2de5
		vt := v.Index(0).Type()
Packit Service 4d2de5
		vts := vt.String()
Packit Service 4d2de5
		switch {
Packit Service 4d2de5
		// C types that need to be converted.
Packit Service 4d2de5
		case cCharRE.MatchString(vts):
Packit Service 4d2de5
			fallthrough
Packit Service 4d2de5
		case cUnsignedCharRE.MatchString(vts):
Packit Service 4d2de5
			fallthrough
Packit Service 4d2de5
		case cUint8tCharRE.MatchString(vts):
Packit Service 4d2de5
			doConvert = true
Packit Service 4d2de5
Packit Service 4d2de5
		// Try to use existing uint8 slices and fall back to converting
Packit Service 4d2de5
		// and copying if that fails.
Packit Service 4d2de5
		case vt.Kind() == reflect.Uint8:
Packit Service 4d2de5
			// We need an addressable interface to convert the type
Packit Service 4d2de5
			// to a byte slice.  However, the reflect package won't
Packit Service 4d2de5
			// give us an interface on certain things like
Packit Service 4d2de5
			// unexported struct fields in order to enforce
Packit Service 4d2de5
			// visibility rules.  We use unsafe, when available, to
Packit Service 4d2de5
			// bypass these restrictions since this package does not
Packit Service 4d2de5
			// mutate the values.
Packit Service 4d2de5
			vs := v
Packit Service 4d2de5
			if !vs.CanInterface() || !vs.CanAddr() {
Packit Service 4d2de5
				vs = unsafeReflectValue(vs)
Packit Service 4d2de5
			}
Packit Service 4d2de5
			if !UnsafeDisabled {
Packit Service 4d2de5
				vs = vs.Slice(0, numEntries)
Packit Service 4d2de5
Packit Service 4d2de5
				// Use the existing uint8 slice if it can be
Packit Service 4d2de5
				// type asserted.
Packit Service 4d2de5
				iface := vs.Interface()
Packit Service 4d2de5
				if slice, ok := iface.([]uint8); ok {
Packit Service 4d2de5
					buf = slice
Packit Service 4d2de5
					doHexDump = true
Packit Service 4d2de5
					break
Packit Service 4d2de5
				}
Packit Service 4d2de5
			}
Packit Service 4d2de5
Packit Service 4d2de5
			// The underlying data needs to be converted if it can't
Packit Service 4d2de5
			// be type asserted to a uint8 slice.
Packit Service 4d2de5
			doConvert = true
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		// Copy and convert the underlying type if needed.
Packit Service 4d2de5
		if doConvert && vt.ConvertibleTo(uint8Type) {
Packit Service 4d2de5
			// Convert and copy each element into a uint8 byte
Packit Service 4d2de5
			// slice.
Packit Service 4d2de5
			buf = make([]uint8, numEntries)
Packit Service 4d2de5
			for i := 0; i < numEntries; i++ {
Packit Service 4d2de5
				vv := v.Index(i)
Packit Service 4d2de5
				buf[i] = uint8(vv.Convert(uint8Type).Uint())
Packit Service 4d2de5
			}
Packit Service 4d2de5
			doHexDump = true
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Hexdump the entire slice as needed.
Packit Service 4d2de5
	if doHexDump {
Packit Service 4d2de5
		indent := strings.Repeat(d.cs.Indent, d.depth)
Packit Service 4d2de5
		str := indent + hex.Dump(buf)
Packit Service 4d2de5
		str = strings.Replace(str, "\n", "\n"+indent, -1)
Packit Service 4d2de5
		str = strings.TrimRight(str, d.cs.Indent)
Packit Service 4d2de5
		d.w.Write([]byte(str))
Packit Service 4d2de5
		return
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Recursively call dump for each item.
Packit Service 4d2de5
	for i := 0; i < numEntries; i++ {
Packit Service 4d2de5
		d.dump(d.unpackValue(v.Index(i)))
Packit Service 4d2de5
		if i < (numEntries - 1) {
Packit Service 4d2de5
			d.w.Write(commaNewlineBytes)
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			d.w.Write(newlineBytes)
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// dump is the main workhorse for dumping a value.  It uses the passed reflect
Packit Service 4d2de5
// value to figure out what kind of object we are dealing with and formats it
Packit Service 4d2de5
// appropriately.  It is a recursive function, however circular data structures
Packit Service 4d2de5
// are detected and handled properly.
Packit Service 4d2de5
func (d *dumpState) dump(v reflect.Value) {
Packit Service 4d2de5
	// Handle invalid reflect values immediately.
Packit Service 4d2de5
	kind := v.Kind()
Packit Service 4d2de5
	if kind == reflect.Invalid {
Packit Service 4d2de5
		d.w.Write(invalidAngleBytes)
Packit Service 4d2de5
		return
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Handle pointers specially.
Packit Service 4d2de5
	if kind == reflect.Ptr {
Packit Service 4d2de5
		d.indent()
Packit Service 4d2de5
		d.dumpPtr(v)
Packit Service 4d2de5
		return
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Print type information unless already handled elsewhere.
Packit Service 4d2de5
	if !d.ignoreNextType {
Packit Service 4d2de5
		d.indent()
Packit Service 4d2de5
		d.w.Write(openParenBytes)
Packit Service 4d2de5
		d.w.Write([]byte(v.Type().String()))
Packit Service 4d2de5
		d.w.Write(closeParenBytes)
Packit Service 4d2de5
		d.w.Write(spaceBytes)
Packit Service 4d2de5
	}
Packit Service 4d2de5
	d.ignoreNextType = false
Packit Service 4d2de5
Packit Service 4d2de5
	// Display length and capacity if the built-in len and cap functions
Packit Service 4d2de5
	// work with the value's kind and the len/cap itself is non-zero.
Packit Service 4d2de5
	valueLen, valueCap := 0, 0
Packit Service 4d2de5
	switch v.Kind() {
Packit Service 4d2de5
	case reflect.Array, reflect.Slice, reflect.Chan:
Packit Service 4d2de5
		valueLen, valueCap = v.Len(), v.Cap()
Packit Service 4d2de5
	case reflect.Map, reflect.String:
Packit Service 4d2de5
		valueLen = v.Len()
Packit Service 4d2de5
	}
Packit Service 4d2de5
	if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
Packit Service 4d2de5
		d.w.Write(openParenBytes)
Packit Service 4d2de5
		if valueLen != 0 {
Packit Service 4d2de5
			d.w.Write(lenEqualsBytes)
Packit Service 4d2de5
			printInt(d.w, int64(valueLen), 10)
Packit Service 4d2de5
		}
Packit Service 4d2de5
		if !d.cs.DisableCapacities && valueCap != 0 {
Packit Service 4d2de5
			if valueLen != 0 {
Packit Service 4d2de5
				d.w.Write(spaceBytes)
Packit Service 4d2de5
			}
Packit Service 4d2de5
			d.w.Write(capEqualsBytes)
Packit Service 4d2de5
			printInt(d.w, int64(valueCap), 10)
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.w.Write(closeParenBytes)
Packit Service 4d2de5
		d.w.Write(spaceBytes)
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	// Call Stringer/error interfaces if they exist and the handle methods flag
Packit Service 4d2de5
	// is enabled
Packit Service 4d2de5
	if !d.cs.DisableMethods {
Packit Service 4d2de5
		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
Packit Service 4d2de5
			if handled := handleMethods(d.cs, d.w, v); handled {
Packit Service 4d2de5
				return
Packit Service 4d2de5
			}
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
Packit Service 4d2de5
	switch kind {
Packit Service 4d2de5
	case reflect.Invalid:
Packit Service 4d2de5
		// Do nothing.  We should never get here since invalid has already
Packit Service 4d2de5
		// been handled above.
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Bool:
Packit Service 4d2de5
		printBool(d.w, v.Bool())
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
Packit Service 4d2de5
		printInt(d.w, v.Int(), 10)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
Packit Service 4d2de5
		printUint(d.w, v.Uint(), 10)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Float32:
Packit Service 4d2de5
		printFloat(d.w, v.Float(), 32)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Float64:
Packit Service 4d2de5
		printFloat(d.w, v.Float(), 64)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Complex64:
Packit Service 4d2de5
		printComplex(d.w, v.Complex(), 32)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Complex128:
Packit Service 4d2de5
		printComplex(d.w, v.Complex(), 64)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Slice:
Packit Service 4d2de5
		if v.IsNil() {
Packit Service 4d2de5
			d.w.Write(nilAngleBytes)
Packit Service 4d2de5
			break
Packit Service 4d2de5
		}
Packit Service 4d2de5
		fallthrough
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Array:
Packit Service 4d2de5
		d.w.Write(openBraceNewlineBytes)
Packit Service 4d2de5
		d.depth++
Packit Service 4d2de5
		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
Packit Service 4d2de5
			d.indent()
Packit Service 4d2de5
			d.w.Write(maxNewlineBytes)
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			d.dumpSlice(v)
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.depth--
Packit Service 4d2de5
		d.indent()
Packit Service 4d2de5
		d.w.Write(closeBraceBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.String:
Packit Service 4d2de5
		d.w.Write([]byte(strconv.Quote(v.String())))
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Interface:
Packit Service 4d2de5
		// The only time we should get here is for nil interfaces due to
Packit Service 4d2de5
		// unpackValue calls.
Packit Service 4d2de5
		if v.IsNil() {
Packit Service 4d2de5
			d.w.Write(nilAngleBytes)
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Ptr:
Packit Service 4d2de5
		// Do nothing.  We should never get here since pointers have already
Packit Service 4d2de5
		// been handled above.
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Map:
Packit Service 4d2de5
		// nil maps should be indicated as different than empty maps
Packit Service 4d2de5
		if v.IsNil() {
Packit Service 4d2de5
			d.w.Write(nilAngleBytes)
Packit Service 4d2de5
			break
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		d.w.Write(openBraceNewlineBytes)
Packit Service 4d2de5
		d.depth++
Packit Service 4d2de5
		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
Packit Service 4d2de5
			d.indent()
Packit Service 4d2de5
			d.w.Write(maxNewlineBytes)
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			numEntries := v.Len()
Packit Service 4d2de5
			keys := v.MapKeys()
Packit Service 4d2de5
			if d.cs.SortKeys {
Packit Service 4d2de5
				sortValues(keys, d.cs)
Packit Service 4d2de5
			}
Packit Service 4d2de5
			for i, key := range keys {
Packit Service 4d2de5
				d.dump(d.unpackValue(key))
Packit Service 4d2de5
				d.w.Write(colonSpaceBytes)
Packit Service 4d2de5
				d.ignoreNextIndent = true
Packit Service 4d2de5
				d.dump(d.unpackValue(v.MapIndex(key)))
Packit Service 4d2de5
				if i < (numEntries - 1) {
Packit Service 4d2de5
					d.w.Write(commaNewlineBytes)
Packit Service 4d2de5
				} else {
Packit Service 4d2de5
					d.w.Write(newlineBytes)
Packit Service 4d2de5
				}
Packit Service 4d2de5
			}
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.depth--
Packit Service 4d2de5
		d.indent()
Packit Service 4d2de5
		d.w.Write(closeBraceBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Struct:
Packit Service 4d2de5
		d.w.Write(openBraceNewlineBytes)
Packit Service 4d2de5
		d.depth++
Packit Service 4d2de5
		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
Packit Service 4d2de5
			d.indent()
Packit Service 4d2de5
			d.w.Write(maxNewlineBytes)
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			vt := v.Type()
Packit Service 4d2de5
			numFields := v.NumField()
Packit Service 4d2de5
			for i := 0; i < numFields; i++ {
Packit Service 4d2de5
				d.indent()
Packit Service 4d2de5
				vtf := vt.Field(i)
Packit Service 4d2de5
				d.w.Write([]byte(vtf.Name))
Packit Service 4d2de5
				d.w.Write(colonSpaceBytes)
Packit Service 4d2de5
				d.ignoreNextIndent = true
Packit Service 4d2de5
				d.dump(d.unpackValue(v.Field(i)))
Packit Service 4d2de5
				if i < (numFields - 1) {
Packit Service 4d2de5
					d.w.Write(commaNewlineBytes)
Packit Service 4d2de5
				} else {
Packit Service 4d2de5
					d.w.Write(newlineBytes)
Packit Service 4d2de5
				}
Packit Service 4d2de5
			}
Packit Service 4d2de5
		}
Packit Service 4d2de5
		d.depth--
Packit Service 4d2de5
		d.indent()
Packit Service 4d2de5
		d.w.Write(closeBraceBytes)
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.Uintptr:
Packit Service 4d2de5
		printHexPtr(d.w, uintptr(v.Uint()))
Packit Service 4d2de5
Packit Service 4d2de5
	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
Packit Service 4d2de5
		printHexPtr(d.w, v.Pointer())
Packit Service 4d2de5
Packit Service 4d2de5
	// There were not any other types at the time this code was written, but
Packit Service 4d2de5
	// fall back to letting the default fmt package handle it in case any new
Packit Service 4d2de5
	// types are added.
Packit Service 4d2de5
	default:
Packit Service 4d2de5
		if v.CanInterface() {
Packit Service 4d2de5
			fmt.Fprintf(d.w, "%v", v.Interface())
Packit Service 4d2de5
		} else {
Packit Service 4d2de5
			fmt.Fprintf(d.w, "%v", v.String())
Packit Service 4d2de5
		}
Packit Service 4d2de5
	}
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// fdump is a helper function to consolidate the logic from the various public
Packit Service 4d2de5
// methods which take varying writers and config states.
Packit Service 4d2de5
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
Packit Service 4d2de5
	for _, arg := range a {
Packit Service 4d2de5
		if arg == nil {
Packit Service 4d2de5
			w.Write(interfaceBytes)
Packit Service 4d2de5
			w.Write(spaceBytes)
Packit Service 4d2de5
			w.Write(nilAngleBytes)
Packit Service 4d2de5
			w.Write(newlineBytes)
Packit Service 4d2de5
			continue
Packit Service 4d2de5
		}
Packit Service 4d2de5
Packit Service 4d2de5
		d := dumpState{w: w, cs: cs}
Packit Service 4d2de5
		d.pointers = make(map[uintptr]int)
Packit Service 4d2de5
		d.dump(reflect.ValueOf(arg))
Packit Service 4d2de5
		d.w.Write(newlineBytes)
Packit Service 4d2de5
	}
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// Fdump formats and displays the passed arguments to io.Writer w.  It formats
Packit Service 4d2de5
// exactly the same as Dump.
Packit Service 4d2de5
func Fdump(w io.Writer, a ...interface{}) {
Packit Service 4d2de5
	fdump(&Config, w, a...)
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
// Sdump returns a string with the passed arguments formatted exactly the same
Packit Service 4d2de5
// as Dump.
Packit Service 4d2de5
func Sdump(a ...interface{}) string {
Packit Service 4d2de5
	var buf bytes.Buffer
Packit Service 4d2de5
	fdump(&Config, &buf, a...)
Packit Service 4d2de5
	return buf.String()
Packit Service 4d2de5
}
Packit Service 4d2de5
Packit Service 4d2de5
/*
Packit Service 4d2de5
Dump displays the passed parameters to standard out with newlines, customizable
Packit Service 4d2de5
indentation, and additional debug information such as complete types and all
Packit Service 4d2de5
pointer addresses used to indirect to the final value.  It provides the
Packit Service 4d2de5
following features over the built-in printing facilities provided by the fmt
Packit Service 4d2de5
package:
Packit Service 4d2de5
Packit Service 4d2de5
	* Pointers are dereferenced and followed
Packit Service 4d2de5
	* Circular data structures are detected and handled properly
Packit Service 4d2de5
	* Custom Stringer/error interfaces are optionally invoked, including
Packit Service 4d2de5
	  on unexported types
Packit Service 4d2de5
	* Custom types which only implement the Stringer/error interfaces via
Packit Service 4d2de5
	  a pointer receiver are optionally invoked when passing non-pointer
Packit Service 4d2de5
	  variables
Packit Service 4d2de5
	* Byte arrays and slices are dumped like the hexdump -C command which
Packit Service 4d2de5
	  includes offsets, byte values in hex, and ASCII output
Packit Service 4d2de5
Packit Service 4d2de5
The configuration options are controlled by an exported package global,
Packit Service 4d2de5
spew.Config.  See ConfigState for options documentation.
Packit Service 4d2de5
Packit Service 4d2de5
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
Packit Service 4d2de5
get the formatted result as a string.
Packit Service 4d2de5
*/
Packit Service 4d2de5
func Dump(a ...interface{}) {
Packit Service 4d2de5
	fdump(&Config, os.Stdout, a...)
Packit Service 4d2de5
}