gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

common.go (10364B)


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