2 * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
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.
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.
28 // Some constants in the form of bytes to avoid string overhead. This mirrors
29 // the technique used in the fmt package.
31 panicBytes = []byte("(PANIC=")
32 plusBytes = []byte("+")
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=")
67 // hexDigits is used to map a decimal value to a hex digit.
68 var hexDigits = "0123456789abcdef"
70 // catchPanic handles any panics that might occur during the handleMethods
72 func catchPanic(w io.Writer, v reflect.Value) {
73 if err := recover(); err != nil {
75 fmt.Fprintf(w, "%v", err)
76 w.Write(closeParenBytes)
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.
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
92 if !v.CanInterface() {
97 v = unsafeReflectValue(v)
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)
113 // Is it an error or Stringer?
114 switch iface := v.Interface().(type) {
116 defer catchPanic(w, v)
117 if cs.ContinueOnMethod {
118 w.Write(openParenBytes)
119 w.Write([]byte(iface.Error()))
120 w.Write(closeParenBytes)
125 w.Write([]byte(iface.Error()))
129 defer catchPanic(w, v)
130 if cs.ContinueOnMethod {
131 w.Write(openParenBytes)
132 w.Write([]byte(iface.String()))
133 w.Write(closeParenBytes)
137 w.Write([]byte(iface.String()))
143 // printBool outputs a boolean value as true or false to Writer w.
144 func printBool(w io.Writer, val bool) {
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)))
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)))
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)))
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) {
172 w.Write(openParenBytes)
173 w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
178 w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
180 w.Write(closeParenBytes)
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) {
189 w.Write(nilAngleBytes)
193 // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
194 buf := make([]byte, 18)
196 // It's simpler to construct the hex string right to left.
200 buf[i] = hexDigits[num%base]
204 buf[i] = hexDigits[num]
212 // Strip unused leading bytes.
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
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()) {
233 if !cs.DisableMethods {
234 vs.strings = make([]string, len(values))
235 for i := range vs.values {
237 if !handleMethods(cs, &b, vs.values[i]) {
241 vs.strings[i] = b.String()
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())
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.
261 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
263 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
265 case reflect.Float32, reflect.Float64:
269 case reflect.Uintptr:
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 {
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]
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
295 func valueSortLess(a, b reflect.Value) 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()
306 return a.String() < b.String()
307 case reflect.Uintptr:
308 return a.Uint() < b.Uint()
310 // Compare the contents of both arrays.
312 for i := 0; i < l; i++ {
315 if av.Interface() == bv.Interface() {
318 return valueSortLess(av, bv)
321 return a.String() < b.String()
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])
330 return s.strings[i] < s.strings[j]
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 {
340 sort.Sort(newValuesSorter(values, cs))