common.go

  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
 17package spew
 18
 19import (
 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.
 30var (
 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.
 68var hexDigits = "0123456789abcdef"
 69
 70// catchPanic handles any panics that might occur during the handleMethods
 71// calls.
 72func 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.
 85func 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.
144func 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.
153func 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.
158func 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.
164func 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.
170func 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.
185func 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.
219type 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.
228func 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).
256func 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.
279func (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.
285func (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.
295func 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.
326func (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.
336func sortValues(values []reflect.Value, cs *ConfigState) {
337	if len(values) == 0 {
338		return
339	}
340	sort.Sort(newValuesSorter(values, cs))
341}