common.go raw

   1  /*
   2   * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
   3   *
   4   * Permission to use, copy, modify, and distribute this software for any
   5   * purpose with or without fee is hereby granted, provided that the above
   6   * copyright notice and this permission notice appear in all copies.
   7   *
   8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15   */
  16  
  17  package spew
  18  
  19  import (
  20  	"bytes"
  21  	"fmt"
  22  	"io"
  23  	"reflect"
  24  	"sort"
  25  	"strconv"
  26  )
  27  
  28  // Some constants in the form of bytes to avoid string overhead.  This mirrors
  29  // the technique used in the fmt package.
  30  var (
  31  	panicBytes            = []byte("(PANIC=")
  32  	plusBytes             = []byte("+")
  33  	iBytes                = []byte("i")
  34  	trueBytes             = []byte("true")
  35  	falseBytes            = []byte("false")
  36  	interfaceBytes        = []byte("(interface {})")
  37  	commaNewlineBytes     = []byte(",\n")
  38  	newlineBytes          = []byte("\n")
  39  	openBraceBytes        = []byte("{")
  40  	openBraceNewlineBytes = []byte("{\n")
  41  	closeBraceBytes       = []byte("}")
  42  	asteriskBytes         = []byte("*")
  43  	colonBytes            = []byte(":")
  44  	colonSpaceBytes       = []byte(": ")
  45  	openParenBytes        = []byte("(")
  46  	closeParenBytes       = []byte(")")
  47  	spaceBytes            = []byte(" ")
  48  	pointerChainBytes     = []byte("->")
  49  	nilAngleBytes         = []byte("<nil>")
  50  	maxNewlineBytes       = []byte("<max depth reached>\n")
  51  	maxShortBytes         = []byte("<max>")
  52  	circularBytes         = []byte("<already shown>")
  53  	circularShortBytes    = []byte("<shown>")
  54  	invalidAngleBytes     = []byte("<invalid>")
  55  	openBracketBytes      = []byte("[")
  56  	closeBracketBytes     = []byte("]")
  57  	percentBytes          = []byte("%")
  58  	precisionBytes        = []byte(".")
  59  	openAngleBytes        = []byte("<")
  60  	closeAngleBytes       = []byte(">")
  61  	openMapBytes          = []byte("map[")
  62  	closeMapBytes         = []byte("]")
  63  	lenEqualsBytes        = []byte("len=")
  64  	capEqualsBytes        = []byte("cap=")
  65  )
  66  
  67  // hexDigits is used to map a decimal value to a hex digit.
  68  var hexDigits = "0123456789abcdef"
  69  
  70  // catchPanic handles any panics that might occur during the handleMethods
  71  // calls.
  72  func catchPanic(w io.Writer, v reflect.Value) {
  73  	if err := recover(); err != nil {
  74  		w.Write(panicBytes)
  75  		fmt.Fprintf(w, "%v", err)
  76  		w.Write(closeParenBytes)
  77  	}
  78  }
  79  
  80  // handleMethods attempts to call the Error and String methods on the underlying
  81  // type the passed reflect.Value represents and outputes the result to Writer w.
  82  //
  83  // It handles panics in any called methods by catching and displaying the error
  84  // as the formatted value.
  85  func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
  86  	// We need an interface to check if the type implements the error or
  87  	// Stringer interface.  However, the reflect package won't give us an
  88  	// interface on certain things like unexported struct fields in order
  89  	// to enforce visibility rules.  We use unsafe, when it's available,
  90  	// to bypass these restrictions since this package does not mutate the
  91  	// values.
  92  	if !v.CanInterface() {
  93  		if UnsafeDisabled {
  94  			return false
  95  		}
  96  
  97  		v = unsafeReflectValue(v)
  98  	}
  99  
 100  	// Choose whether or not to do error and Stringer interface lookups against
 101  	// the base type or a pointer to the base type depending on settings.
 102  	// Technically calling one of these methods with a pointer receiver can
 103  	// mutate the value, however, types which choose to satisify an error or
 104  	// Stringer interface with a pointer receiver should not be mutating their
 105  	// state inside these interface methods.
 106  	if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
 107  		v = unsafeReflectValue(v)
 108  	}
 109  	if v.CanAddr() {
 110  		v = v.Addr()
 111  	}
 112  
 113  	// Is it an error or Stringer?
 114  	switch iface := v.Interface().(type) {
 115  	case error:
 116  		defer catchPanic(w, v)
 117  		if cs.ContinueOnMethod {
 118  			w.Write(openParenBytes)
 119  			w.Write([]byte(iface.Error()))
 120  			w.Write(closeParenBytes)
 121  			w.Write(spaceBytes)
 122  			return false
 123  		}
 124  
 125  		w.Write([]byte(iface.Error()))
 126  		return true
 127  
 128  	case fmt.Stringer:
 129  		defer catchPanic(w, v)
 130  		if cs.ContinueOnMethod {
 131  			w.Write(openParenBytes)
 132  			w.Write([]byte(iface.String()))
 133  			w.Write(closeParenBytes)
 134  			w.Write(spaceBytes)
 135  			return false
 136  		}
 137  		w.Write([]byte(iface.String()))
 138  		return true
 139  	}
 140  	return false
 141  }
 142  
 143  // printBool outputs a boolean value as true or false to Writer w.
 144  func printBool(w io.Writer, val bool) {
 145  	if val {
 146  		w.Write(trueBytes)
 147  	} else {
 148  		w.Write(falseBytes)
 149  	}
 150  }
 151  
 152  // printInt outputs a signed integer value to Writer w.
 153  func printInt(w io.Writer, val int64, base int) {
 154  	w.Write([]byte(strconv.FormatInt(val, base)))
 155  }
 156  
 157  // printUint outputs an unsigned integer value to Writer w.
 158  func printUint(w io.Writer, val uint64, base int) {
 159  	w.Write([]byte(strconv.FormatUint(val, base)))
 160  }
 161  
 162  // printFloat outputs a floating point value using the specified precision,
 163  // which is expected to be 32 or 64bit, to Writer w.
 164  func printFloat(w io.Writer, val float64, precision int) {
 165  	w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
 166  }
 167  
 168  // printComplex outputs a complex value using the specified float precision
 169  // for the real and imaginary parts to Writer w.
 170  func printComplex(w io.Writer, c complex128, floatPrecision int) {
 171  	r := real(c)
 172  	w.Write(openParenBytes)
 173  	w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
 174  	i := imag(c)
 175  	if i >= 0 {
 176  		w.Write(plusBytes)
 177  	}
 178  	w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
 179  	w.Write(iBytes)
 180  	w.Write(closeParenBytes)
 181  }
 182  
 183  // printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
 184  // prefix to Writer w.
 185  func printHexPtr(w io.Writer, p uintptr) {
 186  	// Null pointer.
 187  	num := uint64(p)
 188  	if num == 0 {
 189  		w.Write(nilAngleBytes)
 190  		return
 191  	}
 192  
 193  	// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
 194  	buf := make([]byte, 18)
 195  
 196  	// It's simpler to construct the hex string right to left.
 197  	base := uint64(16)
 198  	i := len(buf) - 1
 199  	for num >= base {
 200  		buf[i] = hexDigits[num%base]
 201  		num /= base
 202  		i--
 203  	}
 204  	buf[i] = hexDigits[num]
 205  
 206  	// Add '0x' prefix.
 207  	i--
 208  	buf[i] = 'x'
 209  	i--
 210  	buf[i] = '0'
 211  
 212  	// Strip unused leading bytes.
 213  	buf = buf[i:]
 214  	w.Write(buf)
 215  }
 216  
 217  // valuesSorter implements sort.Interface to allow a slice of reflect.Value
 218  // elements to be sorted.
 219  type valuesSorter struct {
 220  	values  []reflect.Value
 221  	strings []string // either nil or same len and values
 222  	cs      *ConfigState
 223  }
 224  
 225  // newValuesSorter initializes a valuesSorter instance, which holds a set of
 226  // surrogate keys on which the data should be sorted.  It uses flags in
 227  // ConfigState to decide if and how to populate those surrogate keys.
 228  func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
 229  	vs := &valuesSorter{values: values, cs: cs}
 230  	if canSortSimply(vs.values[0].Kind()) {
 231  		return vs
 232  	}
 233  	if !cs.DisableMethods {
 234  		vs.strings = make([]string, len(values))
 235  		for i := range vs.values {
 236  			b := bytes.Buffer{}
 237  			if !handleMethods(cs, &b, vs.values[i]) {
 238  				vs.strings = nil
 239  				break
 240  			}
 241  			vs.strings[i] = b.String()
 242  		}
 243  	}
 244  	if vs.strings == nil && cs.SpewKeys {
 245  		vs.strings = make([]string, len(values))
 246  		for i := range vs.values {
 247  			vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
 248  		}
 249  	}
 250  	return vs
 251  }
 252  
 253  // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
 254  // directly, or whether it should be considered for sorting by surrogate keys
 255  // (if the ConfigState allows it).
 256  func canSortSimply(kind reflect.Kind) bool {
 257  	// This switch parallels valueSortLess, except for the default case.
 258  	switch kind {
 259  	case reflect.Bool:
 260  		return true
 261  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
 262  		return true
 263  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
 264  		return true
 265  	case reflect.Float32, reflect.Float64:
 266  		return true
 267  	case reflect.String:
 268  		return true
 269  	case reflect.Uintptr:
 270  		return true
 271  	case reflect.Array:
 272  		return true
 273  	}
 274  	return false
 275  }
 276  
 277  // Len returns the number of values in the slice.  It is part of the
 278  // sort.Interface implementation.
 279  func (s *valuesSorter) Len() int {
 280  	return len(s.values)
 281  }
 282  
 283  // Swap swaps the values at the passed indices.  It is part of the
 284  // sort.Interface implementation.
 285  func (s *valuesSorter) Swap(i, j int) {
 286  	s.values[i], s.values[j] = s.values[j], s.values[i]
 287  	if s.strings != nil {
 288  		s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
 289  	}
 290  }
 291  
 292  // valueSortLess returns whether the first value should sort before the second
 293  // value.  It is used by valueSorter.Less as part of the sort.Interface
 294  // implementation.
 295  func valueSortLess(a, b reflect.Value) bool {
 296  	switch a.Kind() {
 297  	case reflect.Bool:
 298  		return !a.Bool() && b.Bool()
 299  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
 300  		return a.Int() < b.Int()
 301  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
 302  		return a.Uint() < b.Uint()
 303  	case reflect.Float32, reflect.Float64:
 304  		return a.Float() < b.Float()
 305  	case reflect.String:
 306  		return a.String() < b.String()
 307  	case reflect.Uintptr:
 308  		return a.Uint() < b.Uint()
 309  	case reflect.Array:
 310  		// Compare the contents of both arrays.
 311  		l := a.Len()
 312  		for i := 0; i < l; i++ {
 313  			av := a.Index(i)
 314  			bv := b.Index(i)
 315  			if av.Interface() == bv.Interface() {
 316  				continue
 317  			}
 318  			return valueSortLess(av, bv)
 319  		}
 320  	}
 321  	return a.String() < b.String()
 322  }
 323  
 324  // Less returns whether the value at index i should sort before the
 325  // value at index j.  It is part of the sort.Interface implementation.
 326  func (s *valuesSorter) Less(i, j int) bool {
 327  	if s.strings == nil {
 328  		return valueSortLess(s.values[i], s.values[j])
 329  	}
 330  	return s.strings[i] < s.strings[j]
 331  }
 332  
 333  // sortValues is a sort function that handles both native types and any type that
 334  // can be converted to error or Stringer.  Other inputs are sorted according to
 335  // their Value.String() value to ensure display stability.
 336  func sortValues(values []reflect.Value, cs *ConfigState) {
 337  	if len(values) == 0 {
 338  		return
 339  	}
 340  	sort.Sort(newValuesSorter(values, cs))
 341  }
 342