1
16
17 package spew
18
19 import (
20 "bytes"
21 "fmt"
22 "reflect"
23 "strconv"
24 "strings"
25 )
26
27
28 const supportedFlags = "0-+# "
29
30
31
32
33
34 type formatState struct {
35 value interface{}
36 fs fmt.State
37 depth int
38 pointers map[uintptr]int
39 ignoreNextType bool
40 cs *ConfigState
41 }
42
43
44
45
46
47 func (f *formatState) buildDefaultFormat() (format string) {
48 buf := bytes.NewBuffer(percentBytes)
49
50 for _, flag := range supportedFlags {
51 if f.fs.Flag(int(flag)) {
52 buf.WriteRune(flag)
53 }
54 }
55
56 buf.WriteRune('v')
57
58 format = buf.String()
59 return format
60 }
61
62
63
64
65 func (f *formatState) constructOrigFormat(verb rune) (format string) {
66 buf := bytes.NewBuffer(percentBytes)
67
68 for _, flag := range supportedFlags {
69 if f.fs.Flag(int(flag)) {
70 buf.WriteRune(flag)
71 }
72 }
73
74 if width, ok := f.fs.Width(); ok {
75 buf.WriteString(strconv.Itoa(width))
76 }
77
78 if precision, ok := f.fs.Precision(); ok {
79 buf.Write(precisionBytes)
80 buf.WriteString(strconv.Itoa(precision))
81 }
82
83 buf.WriteRune(verb)
84
85 format = buf.String()
86 return format
87 }
88
89
90
91
92
93
94 func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
95 if v.Kind() == reflect.Interface {
96 f.ignoreNextType = false
97 if !v.IsNil() {
98 v = v.Elem()
99 }
100 }
101 return v
102 }
103
104
105 func (f *formatState) formatPtr(v reflect.Value) {
106
107 showTypes := f.fs.Flag('#')
108 if v.IsNil() && (!showTypes || f.ignoreNextType) {
109 f.fs.Write(nilAngleBytes)
110 return
111 }
112
113
114
115 for k, depth := range f.pointers {
116 if depth >= f.depth {
117 delete(f.pointers, k)
118 }
119 }
120
121
122 pointerChain := make([]uintptr, 0)
123
124
125
126
127 nilFound := false
128 cycleFound := false
129 indirects := 0
130 ve := v
131 for ve.Kind() == reflect.Ptr {
132 if ve.IsNil() {
133 nilFound = true
134 break
135 }
136 indirects++
137 addr := ve.Pointer()
138 pointerChain = append(pointerChain, addr)
139 if pd, ok := f.pointers[addr]; ok && pd < f.depth {
140 cycleFound = true
141 indirects--
142 break
143 }
144 f.pointers[addr] = f.depth
145
146 ve = ve.Elem()
147 if ve.Kind() == reflect.Interface {
148 if ve.IsNil() {
149 nilFound = true
150 break
151 }
152 ve = ve.Elem()
153 }
154 }
155
156
157 if showTypes && !f.ignoreNextType {
158 f.fs.Write(openParenBytes)
159 f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
160 f.fs.Write([]byte(ve.Type().String()))
161 f.fs.Write(closeParenBytes)
162 } else {
163 if nilFound || cycleFound {
164 indirects += strings.Count(ve.Type().String(), "*")
165 }
166 f.fs.Write(openAngleBytes)
167 f.fs.Write([]byte(strings.Repeat("*", indirects)))
168 f.fs.Write(closeAngleBytes)
169 }
170
171
172 if f.fs.Flag('+') && (len(pointerChain) > 0) {
173 f.fs.Write(openParenBytes)
174 for i, addr := range pointerChain {
175 if i > 0 {
176 f.fs.Write(pointerChainBytes)
177 }
178 printHexPtr(f.fs, addr)
179 }
180 f.fs.Write(closeParenBytes)
181 }
182
183
184 switch {
185 case nilFound:
186 f.fs.Write(nilAngleBytes)
187
188 case cycleFound:
189 f.fs.Write(circularShortBytes)
190
191 default:
192 f.ignoreNextType = true
193 f.format(ve)
194 }
195 }
196
197
198
199
200
201 func (f *formatState) format(v reflect.Value) {
202
203 kind := v.Kind()
204 if kind == reflect.Invalid {
205 f.fs.Write(invalidAngleBytes)
206 return
207 }
208
209
210 if kind == reflect.Ptr {
211 f.formatPtr(v)
212 return
213 }
214
215
216 if !f.ignoreNextType && f.fs.Flag('#') {
217 f.fs.Write(openParenBytes)
218 f.fs.Write([]byte(v.Type().String()))
219 f.fs.Write(closeParenBytes)
220 }
221 f.ignoreNextType = false
222
223
224
225 if !f.cs.DisableMethods {
226 if (kind != reflect.Invalid) && (kind != reflect.Interface) {
227 if handled := handleMethods(f.cs, f.fs, v); handled {
228 return
229 }
230 }
231 }
232
233 switch kind {
234 case reflect.Invalid:
235
236
237
238 case reflect.Bool:
239 printBool(f.fs, v.Bool())
240
241 case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
242 printInt(f.fs, v.Int(), 10)
243
244 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
245 printUint(f.fs, v.Uint(), 10)
246
247 case reflect.Float32:
248 printFloat(f.fs, v.Float(), 32)
249
250 case reflect.Float64:
251 printFloat(f.fs, v.Float(), 64)
252
253 case reflect.Complex64:
254 printComplex(f.fs, v.Complex(), 32)
255
256 case reflect.Complex128:
257 printComplex(f.fs, v.Complex(), 64)
258
259 case reflect.Slice:
260 if v.IsNil() {
261 f.fs.Write(nilAngleBytes)
262 break
263 }
264 fallthrough
265
266 case reflect.Array:
267 f.fs.Write(openBracketBytes)
268 f.depth++
269 if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
270 f.fs.Write(maxShortBytes)
271 } else {
272 numEntries := v.Len()
273 for i := 0; i < numEntries; i++ {
274 if i > 0 {
275 f.fs.Write(spaceBytes)
276 }
277 f.ignoreNextType = true
278 f.format(f.unpackValue(v.Index(i)))
279 }
280 }
281 f.depth--
282 f.fs.Write(closeBracketBytes)
283
284 case reflect.String:
285 f.fs.Write([]byte(v.String()))
286
287 case reflect.Interface:
288
289
290 if v.IsNil() {
291 f.fs.Write(nilAngleBytes)
292 }
293
294 case reflect.Ptr:
295
296
297
298 case reflect.Map:
299
300 if v.IsNil() {
301 f.fs.Write(nilAngleBytes)
302 break
303 }
304
305 f.fs.Write(openMapBytes)
306 f.depth++
307 if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
308 f.fs.Write(maxShortBytes)
309 } else {
310 keys := v.MapKeys()
311 if f.cs.SortKeys {
312 sortValues(keys, f.cs)
313 }
314 for i, key := range keys {
315 if i > 0 {
316 f.fs.Write(spaceBytes)
317 }
318 f.ignoreNextType = true
319 f.format(f.unpackValue(key))
320 f.fs.Write(colonBytes)
321 f.ignoreNextType = true
322 f.format(f.unpackValue(v.MapIndex(key)))
323 }
324 }
325 f.depth--
326 f.fs.Write(closeMapBytes)
327
328 case reflect.Struct:
329 numFields := v.NumField()
330 f.fs.Write(openBraceBytes)
331 f.depth++
332 if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
333 f.fs.Write(maxShortBytes)
334 } else {
335 vt := v.Type()
336 for i := 0; i < numFields; i++ {
337 if i > 0 {
338 f.fs.Write(spaceBytes)
339 }
340 vtf := vt.Field(i)
341 if f.fs.Flag('+') || f.fs.Flag('#') {
342 f.fs.Write([]byte(vtf.Name))
343 f.fs.Write(colonBytes)
344 }
345 f.format(f.unpackValue(v.Field(i)))
346 }
347 }
348 f.depth--
349 f.fs.Write(closeBraceBytes)
350
351 case reflect.Uintptr:
352 printHexPtr(f.fs, uintptr(v.Uint()))
353
354 case reflect.UnsafePointer, reflect.Chan, reflect.Func:
355 printHexPtr(f.fs, v.Pointer())
356
357
358
359 default:
360 format := f.buildDefaultFormat()
361 if v.CanInterface() {
362 fmt.Fprintf(f.fs, format, v.Interface())
363 } else {
364 fmt.Fprintf(f.fs, format, v.String())
365 }
366 }
367 }
368
369
370
371 func (f *formatState) Format(fs fmt.State, verb rune) {
372 f.fs = fs
373
374
375 if verb != 'v' {
376 format := f.constructOrigFormat(verb)
377 fmt.Fprintf(fs, format, f.value)
378 return
379 }
380
381 if f.value == nil {
382 if fs.Flag('#') {
383 fs.Write(interfaceBytes)
384 }
385 fs.Write(nilAngleBytes)
386 return
387 }
388
389 f.format(reflect.ValueOf(f.value))
390 }
391
392
393
394 func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
395 fs := &formatState{value: v, cs: cs}
396 fs.pointers = make(map[uintptr]int)
397 return fs
398 }
399
400
417 func NewFormatter(v interface{}) fmt.Formatter {
418 return newFormatter(&Config, v)
419 }
420
View as plain text