本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
10KB

  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. package spew
  17. import (
  18. "bytes"
  19. "fmt"
  20. "io"
  21. "reflect"
  22. "sort"
  23. "strconv"
  24. )
  25. // Some constants in the form of bytes to avoid string overhead. This mirrors
  26. // the technique used in the fmt package.
  27. var (
  28. panicBytes = []byte("(PANIC=")
  29. plusBytes = []byte("+")
  30. iBytes = []byte("i")
  31. trueBytes = []byte("true")
  32. falseBytes = []byte("false")
  33. interfaceBytes = []byte("(interface {})")
  34. commaNewlineBytes = []byte(",\n")
  35. newlineBytes = []byte("\n")
  36. openBraceBytes = []byte("{")
  37. openBraceNewlineBytes = []byte("{\n")
  38. closeBraceBytes = []byte("}")
  39. asteriskBytes = []byte("*")
  40. colonBytes = []byte(":")
  41. colonSpaceBytes = []byte(": ")
  42. openParenBytes = []byte("(")
  43. closeParenBytes = []byte(")")
  44. spaceBytes = []byte(" ")
  45. pointerChainBytes = []byte("->")
  46. nilAngleBytes = []byte("<nil>")
  47. maxNewlineBytes = []byte("<max depth reached>\n")
  48. maxShortBytes = []byte("<max>")
  49. circularBytes = []byte("<already shown>")
  50. circularShortBytes = []byte("<shown>")
  51. invalidAngleBytes = []byte("<invalid>")
  52. openBracketBytes = []byte("[")
  53. closeBracketBytes = []byte("]")
  54. percentBytes = []byte("%")
  55. precisionBytes = []byte(".")
  56. openAngleBytes = []byte("<")
  57. closeAngleBytes = []byte(">")
  58. openMapBytes = []byte("map[")
  59. closeMapBytes = []byte("]")
  60. lenEqualsBytes = []byte("len=")
  61. capEqualsBytes = []byte("cap=")
  62. )
  63. // hexDigits is used to map a decimal value to a hex digit.
  64. var hexDigits = "0123456789abcdef"
  65. // catchPanic handles any panics that might occur during the handleMethods
  66. // calls.
  67. func catchPanic(w io.Writer, v reflect.Value) {
  68. if err := recover(); err != nil {
  69. w.Write(panicBytes)
  70. fmt.Fprintf(w, "%v", err)
  71. w.Write(closeParenBytes)
  72. }
  73. }
  74. // handleMethods attempts to call the Error and String methods on the underlying
  75. // type the passed reflect.Value represents and outputes the result to Writer w.
  76. //
  77. // It handles panics in any called methods by catching and displaying the error
  78. // as the formatted value.
  79. func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
  80. // We need an interface to check if the type implements the error or
  81. // Stringer interface. However, the reflect package won't give us an
  82. // interface on certain things like unexported struct fields in order
  83. // to enforce visibility rules. We use unsafe, when it's available,
  84. // to bypass these restrictions since this package does not mutate the
  85. // values.
  86. if !v.CanInterface() {
  87. if UnsafeDisabled {
  88. return false
  89. }
  90. v = unsafeReflectValue(v)
  91. }
  92. // Choose whether or not to do error and Stringer interface lookups against
  93. // the base type or a pointer to the base type depending on settings.
  94. // Technically calling one of these methods with a pointer receiver can
  95. // mutate the value, however, types which choose to satisify an error or
  96. // Stringer interface with a pointer receiver should not be mutating their
  97. // state inside these interface methods.
  98. if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
  99. v = unsafeReflectValue(v)
  100. }
  101. if v.CanAddr() {
  102. v = v.Addr()
  103. }
  104. // Is it an error or Stringer?
  105. switch iface := v.Interface().(type) {
  106. case error:
  107. defer catchPanic(w, v)
  108. if cs.ContinueOnMethod {
  109. w.Write(openParenBytes)
  110. w.Write([]byte(iface.Error()))
  111. w.Write(closeParenBytes)
  112. w.Write(spaceBytes)
  113. return false
  114. }
  115. w.Write([]byte(iface.Error()))
  116. return true
  117. case fmt.Stringer:
  118. defer catchPanic(w, v)
  119. if cs.ContinueOnMethod {
  120. w.Write(openParenBytes)
  121. w.Write([]byte(iface.String()))
  122. w.Write(closeParenBytes)
  123. w.Write(spaceBytes)
  124. return false
  125. }
  126. w.Write([]byte(iface.String()))
  127. return true
  128. }
  129. return false
  130. }
  131. // printBool outputs a boolean value as true or false to Writer w.
  132. func printBool(w io.Writer, val bool) {
  133. if val {
  134. w.Write(trueBytes)
  135. } else {
  136. w.Write(falseBytes)
  137. }
  138. }
  139. // printInt outputs a signed integer value to Writer w.
  140. func printInt(w io.Writer, val int64, base int) {
  141. w.Write([]byte(strconv.FormatInt(val, base)))
  142. }
  143. // printUint outputs an unsigned integer value to Writer w.
  144. func printUint(w io.Writer, val uint64, base int) {
  145. w.Write([]byte(strconv.FormatUint(val, base)))
  146. }
  147. // printFloat outputs a floating point value using the specified precision,
  148. // which is expected to be 32 or 64bit, to Writer w.
  149. func printFloat(w io.Writer, val float64, precision int) {
  150. w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
  151. }
  152. // printComplex outputs a complex value using the specified float precision
  153. // for the real and imaginary parts to Writer w.
  154. func printComplex(w io.Writer, c complex128, floatPrecision int) {
  155. r := real(c)
  156. w.Write(openParenBytes)
  157. w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
  158. i := imag(c)
  159. if i >= 0 {
  160. w.Write(plusBytes)
  161. }
  162. w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
  163. w.Write(iBytes)
  164. w.Write(closeParenBytes)
  165. }
  166. // printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
  167. // prefix to Writer w.
  168. func printHexPtr(w io.Writer, p uintptr) {
  169. // Null pointer.
  170. num := uint64(p)
  171. if num == 0 {
  172. w.Write(nilAngleBytes)
  173. return
  174. }
  175. // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
  176. buf := make([]byte, 18)
  177. // It's simpler to construct the hex string right to left.
  178. base := uint64(16)
  179. i := len(buf) - 1
  180. for num >= base {
  181. buf[i] = hexDigits[num%base]
  182. num /= base
  183. i--
  184. }
  185. buf[i] = hexDigits[num]
  186. // Add '0x' prefix.
  187. i--
  188. buf[i] = 'x'
  189. i--
  190. buf[i] = '0'
  191. // Strip unused leading bytes.
  192. buf = buf[i:]
  193. w.Write(buf)
  194. }
  195. // valuesSorter implements sort.Interface to allow a slice of reflect.Value
  196. // elements to be sorted.
  197. type valuesSorter struct {
  198. values []reflect.Value
  199. strings []string // either nil or same len and values
  200. cs *ConfigState
  201. }
  202. // newValuesSorter initializes a valuesSorter instance, which holds a set of
  203. // surrogate keys on which the data should be sorted. It uses flags in
  204. // ConfigState to decide if and how to populate those surrogate keys.
  205. func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
  206. vs := &valuesSorter{values: values, cs: cs}
  207. if canSortSimply(vs.values[0].Kind()) {
  208. return vs
  209. }
  210. if !cs.DisableMethods {
  211. vs.strings = make([]string, len(values))
  212. for i := range vs.values {
  213. b := bytes.Buffer{}
  214. if !handleMethods(cs, &b, vs.values[i]) {
  215. vs.strings = nil
  216. break
  217. }
  218. vs.strings[i] = b.String()
  219. }
  220. }
  221. if vs.strings == nil && cs.SpewKeys {
  222. vs.strings = make([]string, len(values))
  223. for i := range vs.values {
  224. vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
  225. }
  226. }
  227. return vs
  228. }
  229. // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
  230. // directly, or whether it should be considered for sorting by surrogate keys
  231. // (if the ConfigState allows it).
  232. func canSortSimply(kind reflect.Kind) bool {
  233. // This switch parallels valueSortLess, except for the default case.
  234. switch kind {
  235. case reflect.Bool:
  236. return true
  237. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
  238. return true
  239. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  240. return true
  241. case reflect.Float32, reflect.Float64:
  242. return true
  243. case reflect.String:
  244. return true
  245. case reflect.Uintptr:
  246. return true
  247. case reflect.Array:
  248. return true
  249. }
  250. return false
  251. }
  252. // Len returns the number of values in the slice. It is part of the
  253. // sort.Interface implementation.
  254. func (s *valuesSorter) Len() int {
  255. return len(s.values)
  256. }
  257. // Swap swaps the values at the passed indices. It is part of the
  258. // sort.Interface implementation.
  259. func (s *valuesSorter) Swap(i, j int) {
  260. s.values[i], s.values[j] = s.values[j], s.values[i]
  261. if s.strings != nil {
  262. s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
  263. }
  264. }
  265. // valueSortLess returns whether the first value should sort before the second
  266. // value. It is used by valueSorter.Less as part of the sort.Interface
  267. // implementation.
  268. func valueSortLess(a, b reflect.Value) bool {
  269. switch a.Kind() {
  270. case reflect.Bool:
  271. return !a.Bool() && b.Bool()
  272. case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
  273. return a.Int() < b.Int()
  274. case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
  275. return a.Uint() < b.Uint()
  276. case reflect.Float32, reflect.Float64:
  277. return a.Float() < b.Float()
  278. case reflect.String:
  279. return a.String() < b.String()
  280. case reflect.Uintptr:
  281. return a.Uint() < b.Uint()
  282. case reflect.Array:
  283. // Compare the contents of both arrays.
  284. l := a.Len()
  285. for i := 0; i < l; i++ {
  286. av := a.Index(i)
  287. bv := b.Index(i)
  288. if av.Interface() == bv.Interface() {
  289. continue
  290. }
  291. return valueSortLess(av, bv)
  292. }
  293. }
  294. return a.String() < b.String()
  295. }
  296. // Less returns whether the value at index i should sort before the
  297. // value at index j. It is part of the sort.Interface implementation.
  298. func (s *valuesSorter) Less(i, j int) bool {
  299. if s.strings == nil {
  300. return valueSortLess(s.values[i], s.values[j])
  301. }
  302. return s.strings[i] < s.strings[j]
  303. }
  304. // sortValues is a sort function that handles both native types and any type that
  305. // can be converted to error or Stringer. Other inputs are sorted according to
  306. // their Value.String() value to ensure display stability.
  307. func sortValues(values []reflect.Value, cs *ConfigState) {
  308. if len(values) == 0 {
  309. return
  310. }
  311. sort.Sort(newValuesSorter(values, cs))
  312. }
上海开阖软件有限公司 沪ICP备12045867号-1