OSDN Git Service

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