forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/davecgh/go-spew/spew/common.go

613 lines
10 KiB
Go
Raw Normal View History

2024-04-26 19:30:35 +00:00
/*
2024-04-26 19:30:35 +00:00
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
2024-04-26 19:30:35 +00:00
*
2024-04-26 19:30:35 +00:00
* Permission to use, copy, modify, and distribute this software for any
2024-04-26 19:30:35 +00:00
* purpose with or without fee is hereby granted, provided that the above
2024-04-26 19:30:35 +00:00
* copyright notice and this permission notice appear in all copies.
2024-04-26 19:30:35 +00:00
*
2024-04-26 19:30:35 +00:00
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
2024-04-26 19:30:35 +00:00
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
2024-04-26 19:30:35 +00:00
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2024-04-26 19:30:35 +00:00
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2024-04-26 19:30:35 +00:00
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2024-04-26 19:30:35 +00:00
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2024-04-26 19:30:35 +00:00
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2024-04-26 19:30:35 +00:00
*/
package spew
import (
"bytes"
"fmt"
"io"
"reflect"
"sort"
"strconv"
)
// Some constants in the form of bytes to avoid string overhead. This mirrors
2024-04-26 19:30:35 +00:00
// the technique used in the fmt package.
2024-04-26 19:30:35 +00:00
var (
panicBytes = []byte("(PANIC=")
plusBytes = []byte("+")
iBytes = []byte("i")
trueBytes = []byte("true")
falseBytes = []byte("false")
interfaceBytes = []byte("(interface {})")
commaNewlineBytes = []byte(",\n")
newlineBytes = []byte("\n")
openBraceBytes = []byte("{")
2024-04-26 19:30:35 +00:00
openBraceNewlineBytes = []byte("{\n")
closeBraceBytes = []byte("}")
asteriskBytes = []byte("*")
colonBytes = []byte(":")
colonSpaceBytes = []byte(": ")
openParenBytes = []byte("(")
closeParenBytes = []byte(")")
spaceBytes = []byte(" ")
pointerChainBytes = []byte("->")
nilAngleBytes = []byte("<nil>")
maxNewlineBytes = []byte("<max depth reached>\n")
maxShortBytes = []byte("<max>")
circularBytes = []byte("<already shown>")
circularShortBytes = []byte("<shown>")
invalidAngleBytes = []byte("<invalid>")
openBracketBytes = []byte("[")
closeBracketBytes = []byte("]")
percentBytes = []byte("%")
precisionBytes = []byte(".")
openAngleBytes = []byte("<")
closeAngleBytes = []byte(">")
openMapBytes = []byte("map[")
closeMapBytes = []byte("]")
lenEqualsBytes = []byte("len=")
capEqualsBytes = []byte("cap=")
2024-04-26 19:30:35 +00:00
)
// hexDigits is used to map a decimal value to a hex digit.
2024-04-26 19:30:35 +00:00
var hexDigits = "0123456789abcdef"
// catchPanic handles any panics that might occur during the handleMethods
2024-04-26 19:30:35 +00:00
// calls.
2024-04-26 19:30:35 +00:00
func catchPanic(w io.Writer, v reflect.Value) {
2024-04-26 19:30:35 +00:00
if err := recover(); err != nil {
2024-04-26 19:30:35 +00:00
w.Write(panicBytes)
2024-04-26 19:30:35 +00:00
fmt.Fprintf(w, "%v", err)
2024-04-26 19:30:35 +00:00
w.Write(closeParenBytes)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// handleMethods attempts to call the Error and String methods on the underlying
2024-04-26 19:30:35 +00:00
// type the passed reflect.Value represents and outputes the result to Writer w.
2024-04-26 19:30:35 +00:00
//
2024-04-26 19:30:35 +00:00
// It handles panics in any called methods by catching and displaying the error
2024-04-26 19:30:35 +00:00
// as the formatted value.
2024-04-26 19:30:35 +00:00
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
2024-04-26 19:30:35 +00:00
// We need an interface to check if the type implements the error or
2024-04-26 19:30:35 +00:00
// Stringer interface. However, the reflect package won't give us an
2024-04-26 19:30:35 +00:00
// interface on certain things like unexported struct fields in order
2024-04-26 19:30:35 +00:00
// to enforce visibility rules. We use unsafe, when it's available,
2024-04-26 19:30:35 +00:00
// to bypass these restrictions since this package does not mutate the
2024-04-26 19:30:35 +00:00
// values.
2024-04-26 19:30:35 +00:00
if !v.CanInterface() {
2024-04-26 19:30:35 +00:00
if UnsafeDisabled {
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
v = unsafeReflectValue(v)
2024-04-26 19:30:35 +00:00
}
// Choose whether or not to do error and Stringer interface lookups against
2024-04-26 19:30:35 +00:00
// the base type or a pointer to the base type depending on settings.
2024-04-26 19:30:35 +00:00
// Technically calling one of these methods with a pointer receiver can
2024-04-26 19:30:35 +00:00
// mutate the value, however, types which choose to satisify an error or
2024-04-26 19:30:35 +00:00
// Stringer interface with a pointer receiver should not be mutating their
2024-04-26 19:30:35 +00:00
// state inside these interface methods.
2024-04-26 19:30:35 +00:00
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
2024-04-26 19:30:35 +00:00
v = unsafeReflectValue(v)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if v.CanAddr() {
2024-04-26 19:30:35 +00:00
v = v.Addr()
2024-04-26 19:30:35 +00:00
}
// Is it an error or Stringer?
2024-04-26 19:30:35 +00:00
switch iface := v.Interface().(type) {
2024-04-26 19:30:35 +00:00
case error:
2024-04-26 19:30:35 +00:00
defer catchPanic(w, v)
2024-04-26 19:30:35 +00:00
if cs.ContinueOnMethod {
2024-04-26 19:30:35 +00:00
w.Write(openParenBytes)
2024-04-26 19:30:35 +00:00
w.Write([]byte(iface.Error()))
2024-04-26 19:30:35 +00:00
w.Write(closeParenBytes)
2024-04-26 19:30:35 +00:00
w.Write(spaceBytes)
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
w.Write([]byte(iface.Error()))
2024-04-26 19:30:35 +00:00
return true
case fmt.Stringer:
2024-04-26 19:30:35 +00:00
defer catchPanic(w, v)
2024-04-26 19:30:35 +00:00
if cs.ContinueOnMethod {
2024-04-26 19:30:35 +00:00
w.Write(openParenBytes)
2024-04-26 19:30:35 +00:00
w.Write([]byte(iface.String()))
2024-04-26 19:30:35 +00:00
w.Write(closeParenBytes)
2024-04-26 19:30:35 +00:00
w.Write(spaceBytes)
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
w.Write([]byte(iface.String()))
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
// printBool outputs a boolean value as true or false to Writer w.
2024-04-26 19:30:35 +00:00
func printBool(w io.Writer, val bool) {
2024-04-26 19:30:35 +00:00
if val {
2024-04-26 19:30:35 +00:00
w.Write(trueBytes)
2024-04-26 19:30:35 +00:00
} else {
2024-04-26 19:30:35 +00:00
w.Write(falseBytes)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// printInt outputs a signed integer value to Writer w.
2024-04-26 19:30:35 +00:00
func printInt(w io.Writer, val int64, base int) {
2024-04-26 19:30:35 +00:00
w.Write([]byte(strconv.FormatInt(val, base)))
2024-04-26 19:30:35 +00:00
}
// printUint outputs an unsigned integer value to Writer w.
2024-04-26 19:30:35 +00:00
func printUint(w io.Writer, val uint64, base int) {
2024-04-26 19:30:35 +00:00
w.Write([]byte(strconv.FormatUint(val, base)))
2024-04-26 19:30:35 +00:00
}
// printFloat outputs a floating point value using the specified precision,
2024-04-26 19:30:35 +00:00
// which is expected to be 32 or 64bit, to Writer w.
2024-04-26 19:30:35 +00:00
func printFloat(w io.Writer, val float64, precision int) {
2024-04-26 19:30:35 +00:00
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
2024-04-26 19:30:35 +00:00
}
// printComplex outputs a complex value using the specified float precision
2024-04-26 19:30:35 +00:00
// for the real and imaginary parts to Writer w.
2024-04-26 19:30:35 +00:00
func printComplex(w io.Writer, c complex128, floatPrecision int) {
2024-04-26 19:30:35 +00:00
r := real(c)
2024-04-26 19:30:35 +00:00
w.Write(openParenBytes)
2024-04-26 19:30:35 +00:00
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
2024-04-26 19:30:35 +00:00
i := imag(c)
2024-04-26 19:30:35 +00:00
if i >= 0 {
2024-04-26 19:30:35 +00:00
w.Write(plusBytes)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
2024-04-26 19:30:35 +00:00
w.Write(iBytes)
2024-04-26 19:30:35 +00:00
w.Write(closeParenBytes)
2024-04-26 19:30:35 +00:00
}
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
2024-04-26 19:30:35 +00:00
// prefix to Writer w.
2024-04-26 19:30:35 +00:00
func printHexPtr(w io.Writer, p uintptr) {
2024-04-26 19:30:35 +00:00
// Null pointer.
2024-04-26 19:30:35 +00:00
num := uint64(p)
2024-04-26 19:30:35 +00:00
if num == 0 {
2024-04-26 19:30:35 +00:00
w.Write(nilAngleBytes)
2024-04-26 19:30:35 +00:00
return
2024-04-26 19:30:35 +00:00
}
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
2024-04-26 19:30:35 +00:00
buf := make([]byte, 18)
// It's simpler to construct the hex string right to left.
2024-04-26 19:30:35 +00:00
base := uint64(16)
2024-04-26 19:30:35 +00:00
i := len(buf) - 1
2024-04-26 19:30:35 +00:00
for num >= base {
2024-04-26 19:30:35 +00:00
buf[i] = hexDigits[num%base]
2024-04-26 19:30:35 +00:00
num /= base
2024-04-26 19:30:35 +00:00
i--
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
buf[i] = hexDigits[num]
// Add '0x' prefix.
2024-04-26 19:30:35 +00:00
i--
2024-04-26 19:30:35 +00:00
buf[i] = 'x'
2024-04-26 19:30:35 +00:00
i--
2024-04-26 19:30:35 +00:00
buf[i] = '0'
// Strip unused leading bytes.
2024-04-26 19:30:35 +00:00
buf = buf[i:]
2024-04-26 19:30:35 +00:00
w.Write(buf)
2024-04-26 19:30:35 +00:00
}
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
2024-04-26 19:30:35 +00:00
// elements to be sorted.
2024-04-26 19:30:35 +00:00
type valuesSorter struct {
values []reflect.Value
2024-04-26 19:30:35 +00:00
strings []string // either nil or same len and values
cs *ConfigState
2024-04-26 19:30:35 +00:00
}
// newValuesSorter initializes a valuesSorter instance, which holds a set of
2024-04-26 19:30:35 +00:00
// surrogate keys on which the data should be sorted. It uses flags in
2024-04-26 19:30:35 +00:00
// ConfigState to decide if and how to populate those surrogate keys.
2024-04-26 19:30:35 +00:00
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
2024-04-26 19:30:35 +00:00
vs := &valuesSorter{values: values, cs: cs}
2024-04-26 19:30:35 +00:00
if canSortSimply(vs.values[0].Kind()) {
2024-04-26 19:30:35 +00:00
return vs
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if !cs.DisableMethods {
2024-04-26 19:30:35 +00:00
vs.strings = make([]string, len(values))
2024-04-26 19:30:35 +00:00
for i := range vs.values {
2024-04-26 19:30:35 +00:00
b := bytes.Buffer{}
2024-04-26 19:30:35 +00:00
if !handleMethods(cs, &b, vs.values[i]) {
2024-04-26 19:30:35 +00:00
vs.strings = nil
2024-04-26 19:30:35 +00:00
break
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
vs.strings[i] = b.String()
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
if vs.strings == nil && cs.SpewKeys {
2024-04-26 19:30:35 +00:00
vs.strings = make([]string, len(values))
2024-04-26 19:30:35 +00:00
for i := range vs.values {
2024-04-26 19:30:35 +00:00
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return vs
2024-04-26 19:30:35 +00:00
}
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
2024-04-26 19:30:35 +00:00
// directly, or whether it should be considered for sorting by surrogate keys
2024-04-26 19:30:35 +00:00
// (if the ConfigState allows it).
2024-04-26 19:30:35 +00:00
func canSortSimply(kind reflect.Kind) bool {
2024-04-26 19:30:35 +00:00
// This switch parallels valueSortLess, except for the default case.
2024-04-26 19:30:35 +00:00
switch kind {
2024-04-26 19:30:35 +00:00
case reflect.Bool:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.Float32, reflect.Float64:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.String:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.Uintptr:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
case reflect.Array:
2024-04-26 19:30:35 +00:00
return true
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return false
2024-04-26 19:30:35 +00:00
}
// Len returns the number of values in the slice. It is part of the
2024-04-26 19:30:35 +00:00
// sort.Interface implementation.
2024-04-26 19:30:35 +00:00
func (s *valuesSorter) Len() int {
2024-04-26 19:30:35 +00:00
return len(s.values)
2024-04-26 19:30:35 +00:00
}
// Swap swaps the values at the passed indices. It is part of the
2024-04-26 19:30:35 +00:00
// sort.Interface implementation.
2024-04-26 19:30:35 +00:00
func (s *valuesSorter) Swap(i, j int) {
2024-04-26 19:30:35 +00:00
s.values[i], s.values[j] = s.values[j], s.values[i]
2024-04-26 19:30:35 +00:00
if s.strings != nil {
2024-04-26 19:30:35 +00:00
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
// valueSortLess returns whether the first value should sort before the second
2024-04-26 19:30:35 +00:00
// value. It is used by valueSorter.Less as part of the sort.Interface
2024-04-26 19:30:35 +00:00
// implementation.
2024-04-26 19:30:35 +00:00
func valueSortLess(a, b reflect.Value) bool {
2024-04-26 19:30:35 +00:00
switch a.Kind() {
2024-04-26 19:30:35 +00:00
case reflect.Bool:
2024-04-26 19:30:35 +00:00
return !a.Bool() && b.Bool()
2024-04-26 19:30:35 +00:00
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
2024-04-26 19:30:35 +00:00
return a.Int() < b.Int()
2024-04-26 19:30:35 +00:00
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
2024-04-26 19:30:35 +00:00
return a.Uint() < b.Uint()
2024-04-26 19:30:35 +00:00
case reflect.Float32, reflect.Float64:
2024-04-26 19:30:35 +00:00
return a.Float() < b.Float()
2024-04-26 19:30:35 +00:00
case reflect.String:
2024-04-26 19:30:35 +00:00
return a.String() < b.String()
2024-04-26 19:30:35 +00:00
case reflect.Uintptr:
2024-04-26 19:30:35 +00:00
return a.Uint() < b.Uint()
2024-04-26 19:30:35 +00:00
case reflect.Array:
2024-04-26 19:30:35 +00:00
// Compare the contents of both arrays.
2024-04-26 19:30:35 +00:00
l := a.Len()
2024-04-26 19:30:35 +00:00
for i := 0; i < l; i++ {
2024-04-26 19:30:35 +00:00
av := a.Index(i)
2024-04-26 19:30:35 +00:00
bv := b.Index(i)
2024-04-26 19:30:35 +00:00
if av.Interface() == bv.Interface() {
2024-04-26 19:30:35 +00:00
continue
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return valueSortLess(av, bv)
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return a.String() < b.String()
2024-04-26 19:30:35 +00:00
}
// Less returns whether the value at index i should sort before the
2024-04-26 19:30:35 +00:00
// value at index j. It is part of the sort.Interface implementation.
2024-04-26 19:30:35 +00:00
func (s *valuesSorter) Less(i, j int) bool {
2024-04-26 19:30:35 +00:00
if s.strings == nil {
2024-04-26 19:30:35 +00:00
return valueSortLess(s.values[i], s.values[j])
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
return s.strings[i] < s.strings[j]
2024-04-26 19:30:35 +00:00
}
// sortValues is a sort function that handles both native types and any type that
2024-04-26 19:30:35 +00:00
// can be converted to error or Stringer. Other inputs are sorted according to
2024-04-26 19:30:35 +00:00
// their Value.String() value to ensure display stability.
2024-04-26 19:30:35 +00:00
func sortValues(values []reflect.Value, cs *ConfigState) {
2024-04-26 19:30:35 +00:00
if len(values) == 0 {
2024-04-26 19:30:35 +00:00
return
2024-04-26 19:30:35 +00:00
}
2024-04-26 19:30:35 +00:00
sort.Sort(newValuesSorter(values, cs))
2024-04-26 19:30:35 +00:00
}