1
16
17 package spew
18
19 import (
20 "bytes"
21 "fmt"
22 "io"
23 "reflect"
24 "sort"
25 "strconv"
26 )
27
28
29
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
68 var hexDigits = "0123456789abcdef"
69
70
71
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
81
82
83
84
85 func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
86
87
88
89
90
91
92 if !v.CanInterface() {
93 if UnsafeDisabled {
94 return false
95 }
96
97 v = unsafeReflectValue(v)
98 }
99
100
101
102
103
104
105
106 if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
107 v = unsafeReflectValue(v)
108 }
109 if v.CanAddr() {
110 v = v.Addr()
111 }
112
113
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
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
153 func printInt(w io.Writer, val int64, base int) {
154 w.Write([]byte(strconv.FormatInt(val, base)))
155 }
156
157
158 func printUint(w io.Writer, val uint64, base int) {
159 w.Write([]byte(strconv.FormatUint(val, base)))
160 }
161
162
163
164 func printFloat(w io.Writer, val float64, precision int) {
165 w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
166 }
167
168
169
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
184
185 func printHexPtr(w io.Writer, p uintptr) {
186
187 num := uint64(p)
188 if num == 0 {
189 w.Write(nilAngleBytes)
190 return
191 }
192
193
194 buf := make([]byte, 18)
195
196
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
207 i--
208 buf[i] = 'x'
209 i--
210 buf[i] = '0'
211
212
213 buf = buf[i:]
214 w.Write(buf)
215 }
216
217
218
219 type valuesSorter struct {
220 values []reflect.Value
221 strings []string
222 cs *ConfigState
223 }
224
225
226
227
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
254
255
256 func canSortSimply(kind reflect.Kind) bool {
257
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
278
279 func (s *valuesSorter) Len() int {
280 return len(s.values)
281 }
282
283
284
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
293
294
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
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
325
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
334
335
336 func sortValues(values []reflect.Value, cs *ConfigState) {
337 if len(values) == 0 {
338 return
339 }
340 sort.Sort(newValuesSorter(values, cs))
341 }
342
View as plain text