github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/test/go-spew/spew/common.go (about)

     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 hexidecimal 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  }