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 }