1
2
3
4
5 package message
6
7 import (
8 "bytes"
9 "fmt"
10 "math"
11 "reflect"
12 "sync"
13 "unicode/utf8"
14
15 "golang.org/x/text/internal/format"
16 "golang.org/x/text/internal/number"
17 "golang.org/x/text/language"
18 "golang.org/x/text/message/catalog"
19 )
20
21
22
23 const (
24 commaSpaceString = ", "
25 nilAngleString = "<nil>"
26 nilParenString = "(nil)"
27 nilString = "nil"
28 mapString = "map["
29 percentBangString = "%!"
30 missingString = "(MISSING)"
31 badIndexString = "(BADINDEX)"
32 panicString = "(PANIC="
33 extraString = "%!(EXTRA "
34 badWidthString = "%!(BADWIDTH)"
35 badPrecString = "%!(BADPREC)"
36 noVerbString = "%!(NOVERB)"
37
38 invReflectString = "<invalid reflect.Value>"
39 )
40
41 var printerPool = sync.Pool{
42 New: func() interface{} { return new(printer) },
43 }
44
45
46 func newPrinter(pp *Printer) *printer {
47 p := printerPool.Get().(*printer)
48 p.Printer = *pp
49
50 p.catContext = pp.cat.Context(pp.tag, p)
51
52 p.panicking = false
53 p.erroring = false
54 p.fmt.init(&p.Buffer)
55 return p
56 }
57
58
59 func (p *printer) free() {
60 p.Buffer.Reset()
61 p.arg = nil
62 p.value = reflect.Value{}
63 printerPool.Put(p)
64 }
65
66
67
68 type printer struct {
69 Printer
70
71
72 catContext *catalog.Context
73
74
75 bytes.Buffer
76
77
78 arg interface{}
79
80 value reflect.Value
81
82
83 fmt formatInfo
84
85
86 panicking bool
87
88 erroring bool
89 }
90
91
92 func (p *printer) Language() language.Tag { return p.tag }
93
94 func (p *printer) Width() (wid int, ok bool) { return p.fmt.Width, p.fmt.WidthPresent }
95
96 func (p *printer) Precision() (prec int, ok bool) { return p.fmt.Prec, p.fmt.PrecPresent }
97
98 func (p *printer) Flag(b int) bool {
99 switch b {
100 case '-':
101 return p.fmt.Minus
102 case '+':
103 return p.fmt.Plus || p.fmt.PlusV
104 case '#':
105 return p.fmt.Sharp || p.fmt.SharpV
106 case ' ':
107 return p.fmt.Space
108 case '0':
109 return p.fmt.Zero
110 }
111 return false
112 }
113
114
115
116
117 func getField(v reflect.Value, i int) reflect.Value {
118 val := v.Field(i)
119 if val.Kind() == reflect.Interface && !val.IsNil() {
120 val = val.Elem()
121 }
122 return val
123 }
124
125 func (p *printer) unknownType(v reflect.Value) {
126 if !v.IsValid() {
127 p.WriteString(nilAngleString)
128 return
129 }
130 p.WriteByte('?')
131 p.WriteString(v.Type().String())
132 p.WriteByte('?')
133 }
134
135 func (p *printer) badVerb(verb rune) {
136 p.erroring = true
137 p.WriteString(percentBangString)
138 p.WriteRune(verb)
139 p.WriteByte('(')
140 switch {
141 case p.arg != nil:
142 p.WriteString(reflect.TypeOf(p.arg).String())
143 p.WriteByte('=')
144 p.printArg(p.arg, 'v')
145 case p.value.IsValid():
146 p.WriteString(p.value.Type().String())
147 p.WriteByte('=')
148 p.printValue(p.value, 'v', 0)
149 default:
150 p.WriteString(nilAngleString)
151 }
152 p.WriteByte(')')
153 p.erroring = false
154 }
155
156 func (p *printer) fmtBool(v bool, verb rune) {
157 switch verb {
158 case 't', 'v':
159 p.fmt.fmt_boolean(v)
160 default:
161 p.badVerb(verb)
162 }
163 }
164
165
166
167 func (p *printer) fmt0x64(v uint64, leading0x bool) {
168 sharp := p.fmt.Sharp
169 p.fmt.Sharp = leading0x
170 p.fmt.fmt_integer(v, 16, unsigned, ldigits)
171 p.fmt.Sharp = sharp
172 }
173
174
175 func (p *printer) fmtInteger(v uint64, isSigned bool, verb rune) {
176 switch verb {
177 case 'v':
178 if p.fmt.SharpV && !isSigned {
179 p.fmt0x64(v, true)
180 return
181 }
182 fallthrough
183 case 'd':
184 if p.fmt.Sharp || p.fmt.SharpV {
185 p.fmt.fmt_integer(v, 10, isSigned, ldigits)
186 } else {
187 p.fmtDecimalInt(v, isSigned)
188 }
189 case 'b':
190 p.fmt.fmt_integer(v, 2, isSigned, ldigits)
191 case 'o':
192 p.fmt.fmt_integer(v, 8, isSigned, ldigits)
193 case 'x':
194 p.fmt.fmt_integer(v, 16, isSigned, ldigits)
195 case 'X':
196 p.fmt.fmt_integer(v, 16, isSigned, udigits)
197 case 'c':
198 p.fmt.fmt_c(v)
199 case 'q':
200 if v <= utf8.MaxRune {
201 p.fmt.fmt_qc(v)
202 } else {
203 p.badVerb(verb)
204 }
205 case 'U':
206 p.fmt.fmt_unicode(v)
207 default:
208 p.badVerb(verb)
209 }
210 }
211
212
213
214 func (p *printer) fmtFloat(v float64, size int, verb rune) {
215 switch verb {
216 case 'b':
217 p.fmt.fmt_float(v, size, verb, -1)
218 case 'v':
219 verb = 'g'
220 fallthrough
221 case 'g', 'G':
222 if p.fmt.Sharp || p.fmt.SharpV {
223 p.fmt.fmt_float(v, size, verb, -1)
224 } else {
225 p.fmtVariableFloat(v, size)
226 }
227 case 'e', 'E':
228 if p.fmt.Sharp || p.fmt.SharpV {
229 p.fmt.fmt_float(v, size, verb, 6)
230 } else {
231 p.fmtScientific(v, size, 6)
232 }
233 case 'f', 'F':
234 if p.fmt.Sharp || p.fmt.SharpV {
235 p.fmt.fmt_float(v, size, verb, 6)
236 } else {
237 p.fmtDecimalFloat(v, size, 6)
238 }
239 default:
240 p.badVerb(verb)
241 }
242 }
243
244 func (p *printer) setFlags(f *number.Formatter) {
245 f.Flags &^= number.ElideSign
246 if p.fmt.Plus || p.fmt.Space {
247 f.Flags |= number.AlwaysSign
248 if !p.fmt.Plus {
249 f.Flags |= number.ElideSign
250 }
251 } else {
252 f.Flags &^= number.AlwaysSign
253 }
254 }
255
256 func (p *printer) updatePadding(f *number.Formatter) {
257 f.Flags &^= number.PadMask
258 if p.fmt.Minus {
259 f.Flags |= number.PadAfterSuffix
260 } else {
261 f.Flags |= number.PadBeforePrefix
262 }
263 f.PadRune = ' '
264 f.FormatWidth = uint16(p.fmt.Width)
265 }
266
267 func (p *printer) initDecimal(minFrac, maxFrac int) {
268 f := &p.toDecimal
269 f.MinIntegerDigits = 1
270 f.MaxIntegerDigits = 0
271 f.MinFractionDigits = uint8(minFrac)
272 f.MaxFractionDigits = int16(maxFrac)
273 p.setFlags(f)
274 f.PadRune = 0
275 if p.fmt.WidthPresent {
276 if p.fmt.Zero {
277 wid := p.fmt.Width
278
279
280 if f.MinFractionDigits > 0 {
281 wid -= 1 + int(f.MinFractionDigits)
282 }
283 if p.fmt.Plus || p.fmt.Space {
284 wid--
285 }
286 if wid > 0 && wid > int(f.MinIntegerDigits) {
287 f.MinIntegerDigits = uint8(wid)
288 }
289 }
290 p.updatePadding(f)
291 }
292 }
293
294 func (p *printer) initScientific(minFrac, maxFrac int) {
295 f := &p.toScientific
296 if maxFrac < 0 {
297 f.SetPrecision(maxFrac)
298 } else {
299 f.SetPrecision(maxFrac + 1)
300 f.MinFractionDigits = uint8(minFrac)
301 f.MaxFractionDigits = int16(maxFrac)
302 }
303 f.MinExponentDigits = 2
304 p.setFlags(f)
305 f.PadRune = 0
306 if p.fmt.WidthPresent {
307 f.Flags &^= number.PadMask
308 if p.fmt.Zero {
309 f.PadRune = f.Digit(0)
310 f.Flags |= number.PadAfterPrefix
311 } else {
312 f.PadRune = ' '
313 f.Flags |= number.PadBeforePrefix
314 }
315 p.updatePadding(f)
316 }
317 }
318
319 func (p *printer) fmtDecimalInt(v uint64, isSigned bool) {
320 var d number.Decimal
321
322 f := &p.toDecimal
323 if p.fmt.PrecPresent {
324 p.setFlags(f)
325 f.MinIntegerDigits = uint8(p.fmt.Prec)
326 f.MaxIntegerDigits = 0
327 f.MinFractionDigits = 0
328 f.MaxFractionDigits = 0
329 if p.fmt.WidthPresent {
330 p.updatePadding(f)
331 }
332 } else {
333 p.initDecimal(0, 0)
334 }
335 d.ConvertInt(p.toDecimal.RoundingContext, isSigned, v)
336
337 out := p.toDecimal.Format([]byte(nil), &d)
338 p.Buffer.Write(out)
339 }
340
341 func (p *printer) fmtDecimalFloat(v float64, size, prec int) {
342 var d number.Decimal
343 if p.fmt.PrecPresent {
344 prec = p.fmt.Prec
345 }
346 p.initDecimal(prec, prec)
347 d.ConvertFloat(p.toDecimal.RoundingContext, v, size)
348
349 out := p.toDecimal.Format([]byte(nil), &d)
350 p.Buffer.Write(out)
351 }
352
353 func (p *printer) fmtVariableFloat(v float64, size int) {
354 prec := -1
355 if p.fmt.PrecPresent {
356 prec = p.fmt.Prec
357 }
358 var d number.Decimal
359 p.initScientific(0, prec)
360 d.ConvertFloat(p.toScientific.RoundingContext, v, size)
361
362
363
364 shortest := prec < 0
365 ePrec := prec
366 if shortest {
367 prec = len(d.Digits)
368 ePrec = 6
369 } else if prec == 0 {
370 prec = 1
371 ePrec = 1
372 }
373 exp := int(d.Exp) - 1
374 if exp < -4 || exp >= ePrec {
375 p.initScientific(0, prec)
376
377 out := p.toScientific.Format([]byte(nil), &d)
378 p.Buffer.Write(out)
379 } else {
380 if prec > int(d.Exp) {
381 prec = len(d.Digits)
382 }
383 if prec -= int(d.Exp); prec < 0 {
384 prec = 0
385 }
386 p.initDecimal(0, prec)
387
388 out := p.toDecimal.Format([]byte(nil), &d)
389 p.Buffer.Write(out)
390 }
391 }
392
393 func (p *printer) fmtScientific(v float64, size, prec int) {
394 var d number.Decimal
395 if p.fmt.PrecPresent {
396 prec = p.fmt.Prec
397 }
398 p.initScientific(prec, prec)
399 rc := p.toScientific.RoundingContext
400 d.ConvertFloat(rc, v, size)
401
402 out := p.toScientific.Format([]byte(nil), &d)
403 p.Buffer.Write(out)
404
405 }
406
407
408
409
410 func (p *printer) fmtComplex(v complex128, size int, verb rune) {
411
412
413 switch verb {
414 case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
415 p.WriteByte('(')
416 p.fmtFloat(real(v), size/2, verb)
417
418 if math.IsNaN(imag(v)) {
419
420
421
422 f := &p.toScientific
423 p.setFlags(f)
424 p.updatePadding(f)
425 p.setFlags(f)
426 nan := f.Symbol(number.SymNan)
427 extra := 0
428 if w, ok := p.Width(); ok {
429 extra = w - utf8.RuneCountInString(nan) - 1
430 }
431 if f.Flags&number.PadAfterNumber == 0 {
432 for ; extra > 0; extra-- {
433 p.WriteRune(f.PadRune)
434 }
435 }
436 p.WriteString(f.Symbol(number.SymPlusSign))
437 p.WriteString(nan)
438 for ; extra > 0; extra-- {
439 p.WriteRune(f.PadRune)
440 }
441 p.WriteString("i)")
442 return
443 }
444 oldPlus := p.fmt.Plus
445 p.fmt.Plus = true
446 p.fmtFloat(imag(v), size/2, verb)
447 p.WriteString("i)")
448 p.fmt.Plus = oldPlus
449 default:
450 p.badVerb(verb)
451 }
452 }
453
454 func (p *printer) fmtString(v string, verb rune) {
455 switch verb {
456 case 'v':
457 if p.fmt.SharpV {
458 p.fmt.fmt_q(v)
459 } else {
460 p.fmt.fmt_s(v)
461 }
462 case 's':
463 p.fmt.fmt_s(v)
464 case 'x':
465 p.fmt.fmt_sx(v, ldigits)
466 case 'X':
467 p.fmt.fmt_sx(v, udigits)
468 case 'q':
469 p.fmt.fmt_q(v)
470 case 'm':
471 ctx := p.cat.Context(p.tag, rawPrinter{p})
472 if ctx.Execute(v) == catalog.ErrNotFound {
473 p.WriteString(v)
474 }
475 default:
476 p.badVerb(verb)
477 }
478 }
479
480 func (p *printer) fmtBytes(v []byte, verb rune, typeString string) {
481 switch verb {
482 case 'v', 'd':
483 if p.fmt.SharpV {
484 p.WriteString(typeString)
485 if v == nil {
486 p.WriteString(nilParenString)
487 return
488 }
489 p.WriteByte('{')
490 for i, c := range v {
491 if i > 0 {
492 p.WriteString(commaSpaceString)
493 }
494 p.fmt0x64(uint64(c), true)
495 }
496 p.WriteByte('}')
497 } else {
498 p.WriteByte('[')
499 for i, c := range v {
500 if i > 0 {
501 p.WriteByte(' ')
502 }
503 p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits)
504 }
505 p.WriteByte(']')
506 }
507 case 's':
508 p.fmt.fmt_s(string(v))
509 case 'x':
510 p.fmt.fmt_bx(v, ldigits)
511 case 'X':
512 p.fmt.fmt_bx(v, udigits)
513 case 'q':
514 p.fmt.fmt_q(string(v))
515 default:
516 p.printValue(reflect.ValueOf(v), verb, 0)
517 }
518 }
519
520 func (p *printer) fmtPointer(value reflect.Value, verb rune) {
521 var u uintptr
522 switch value.Kind() {
523 case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
524 u = value.Pointer()
525 default:
526 p.badVerb(verb)
527 return
528 }
529
530 switch verb {
531 case 'v':
532 if p.fmt.SharpV {
533 p.WriteByte('(')
534 p.WriteString(value.Type().String())
535 p.WriteString(")(")
536 if u == 0 {
537 p.WriteString(nilString)
538 } else {
539 p.fmt0x64(uint64(u), true)
540 }
541 p.WriteByte(')')
542 } else {
543 if u == 0 {
544 p.fmt.padString(nilAngleString)
545 } else {
546 p.fmt0x64(uint64(u), !p.fmt.Sharp)
547 }
548 }
549 case 'p':
550 p.fmt0x64(uint64(u), !p.fmt.Sharp)
551 case 'b', 'o', 'd', 'x', 'X':
552 if verb == 'd' {
553 p.fmt.Sharp = true
554 }
555 p.fmtInteger(uint64(u), unsigned, verb)
556 default:
557 p.badVerb(verb)
558 }
559 }
560
561 func (p *printer) catchPanic(arg interface{}, verb rune) {
562 if err := recover(); err != nil {
563
564
565
566 if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() {
567 p.WriteString(nilAngleString)
568 return
569 }
570
571
572 if p.panicking {
573
574 panic(err)
575 }
576
577 oldFlags := p.fmt.Parser
578
579 p.fmt.ClearFlags()
580
581 p.WriteString(percentBangString)
582 p.WriteRune(verb)
583 p.WriteString(panicString)
584 p.panicking = true
585 p.printArg(err, 'v')
586 p.panicking = false
587 p.WriteByte(')')
588
589 p.fmt.Parser = oldFlags
590 }
591 }
592
593 func (p *printer) handleMethods(verb rune) (handled bool) {
594 if p.erroring {
595 return
596 }
597
598 if formatter, ok := p.arg.(format.Formatter); ok {
599 handled = true
600 defer p.catchPanic(p.arg, verb)
601 formatter.Format(p, verb)
602 return
603 }
604 if formatter, ok := p.arg.(fmt.Formatter); ok {
605 handled = true
606 defer p.catchPanic(p.arg, verb)
607 formatter.Format(p, verb)
608 return
609 }
610
611
612 if p.fmt.SharpV {
613 if stringer, ok := p.arg.(fmt.GoStringer); ok {
614 handled = true
615 defer p.catchPanic(p.arg, verb)
616
617 p.fmt.fmt_s(stringer.GoString())
618 return
619 }
620 } else {
621
622
623
624 switch verb {
625 case 'v', 's', 'x', 'X', 'q':
626
627
628
629
630 switch v := p.arg.(type) {
631 case error:
632 handled = true
633 defer p.catchPanic(p.arg, verb)
634 p.fmtString(v.Error(), verb)
635 return
636
637 case fmt.Stringer:
638 handled = true
639 defer p.catchPanic(p.arg, verb)
640 p.fmtString(v.String(), verb)
641 return
642 }
643 }
644 }
645 return false
646 }
647
648 func (p *printer) printArg(arg interface{}, verb rune) {
649 p.arg = arg
650 p.value = reflect.Value{}
651
652 if arg == nil {
653 switch verb {
654 case 'T', 'v':
655 p.fmt.padString(nilAngleString)
656 default:
657 p.badVerb(verb)
658 }
659 return
660 }
661
662
663
664 switch verb {
665 case 'T':
666 p.fmt.fmt_s(reflect.TypeOf(arg).String())
667 return
668 case 'p':
669 p.fmtPointer(reflect.ValueOf(arg), 'p')
670 return
671 }
672
673
674 switch f := arg.(type) {
675 case bool:
676 p.fmtBool(f, verb)
677 case float32:
678 p.fmtFloat(float64(f), 32, verb)
679 case float64:
680 p.fmtFloat(f, 64, verb)
681 case complex64:
682 p.fmtComplex(complex128(f), 64, verb)
683 case complex128:
684 p.fmtComplex(f, 128, verb)
685 case int:
686 p.fmtInteger(uint64(f), signed, verb)
687 case int8:
688 p.fmtInteger(uint64(f), signed, verb)
689 case int16:
690 p.fmtInteger(uint64(f), signed, verb)
691 case int32:
692 p.fmtInteger(uint64(f), signed, verb)
693 case int64:
694 p.fmtInteger(uint64(f), signed, verb)
695 case uint:
696 p.fmtInteger(uint64(f), unsigned, verb)
697 case uint8:
698 p.fmtInteger(uint64(f), unsigned, verb)
699 case uint16:
700 p.fmtInteger(uint64(f), unsigned, verb)
701 case uint32:
702 p.fmtInteger(uint64(f), unsigned, verb)
703 case uint64:
704 p.fmtInteger(f, unsigned, verb)
705 case uintptr:
706 p.fmtInteger(uint64(f), unsigned, verb)
707 case string:
708 p.fmtString(f, verb)
709 case []byte:
710 p.fmtBytes(f, verb, "[]byte")
711 case reflect.Value:
712
713
714 if f.IsValid() && f.CanInterface() {
715 p.arg = f.Interface()
716 if p.handleMethods(verb) {
717 return
718 }
719 }
720 p.printValue(f, verb, 0)
721 default:
722
723 if !p.handleMethods(verb) {
724
725
726 p.printValue(reflect.ValueOf(f), verb, 0)
727 }
728 }
729 }
730
731
732
733 func (p *printer) printValue(value reflect.Value, verb rune, depth int) {
734
735 if depth > 0 && value.IsValid() && value.CanInterface() {
736 p.arg = value.Interface()
737 if p.handleMethods(verb) {
738 return
739 }
740 }
741 p.arg = nil
742 p.value = value
743
744 switch f := value; value.Kind() {
745 case reflect.Invalid:
746 if depth == 0 {
747 p.WriteString(invReflectString)
748 } else {
749 switch verb {
750 case 'v':
751 p.WriteString(nilAngleString)
752 default:
753 p.badVerb(verb)
754 }
755 }
756 case reflect.Bool:
757 p.fmtBool(f.Bool(), verb)
758 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
759 p.fmtInteger(uint64(f.Int()), signed, verb)
760 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
761 p.fmtInteger(f.Uint(), unsigned, verb)
762 case reflect.Float32:
763 p.fmtFloat(f.Float(), 32, verb)
764 case reflect.Float64:
765 p.fmtFloat(f.Float(), 64, verb)
766 case reflect.Complex64:
767 p.fmtComplex(f.Complex(), 64, verb)
768 case reflect.Complex128:
769 p.fmtComplex(f.Complex(), 128, verb)
770 case reflect.String:
771 p.fmtString(f.String(), verb)
772 case reflect.Map:
773 if p.fmt.SharpV {
774 p.WriteString(f.Type().String())
775 if f.IsNil() {
776 p.WriteString(nilParenString)
777 return
778 }
779 p.WriteByte('{')
780 } else {
781 p.WriteString(mapString)
782 }
783 keys := f.MapKeys()
784 for i, key := range keys {
785 if i > 0 {
786 if p.fmt.SharpV {
787 p.WriteString(commaSpaceString)
788 } else {
789 p.WriteByte(' ')
790 }
791 }
792 p.printValue(key, verb, depth+1)
793 p.WriteByte(':')
794 p.printValue(f.MapIndex(key), verb, depth+1)
795 }
796 if p.fmt.SharpV {
797 p.WriteByte('}')
798 } else {
799 p.WriteByte(']')
800 }
801 case reflect.Struct:
802 if p.fmt.SharpV {
803 p.WriteString(f.Type().String())
804 }
805 p.WriteByte('{')
806 for i := 0; i < f.NumField(); i++ {
807 if i > 0 {
808 if p.fmt.SharpV {
809 p.WriteString(commaSpaceString)
810 } else {
811 p.WriteByte(' ')
812 }
813 }
814 if p.fmt.PlusV || p.fmt.SharpV {
815 if name := f.Type().Field(i).Name; name != "" {
816 p.WriteString(name)
817 p.WriteByte(':')
818 }
819 }
820 p.printValue(getField(f, i), verb, depth+1)
821 }
822 p.WriteByte('}')
823 case reflect.Interface:
824 value := f.Elem()
825 if !value.IsValid() {
826 if p.fmt.SharpV {
827 p.WriteString(f.Type().String())
828 p.WriteString(nilParenString)
829 } else {
830 p.WriteString(nilAngleString)
831 }
832 } else {
833 p.printValue(value, verb, depth+1)
834 }
835 case reflect.Array, reflect.Slice:
836 switch verb {
837 case 's', 'q', 'x', 'X':
838
839 t := f.Type()
840 if t.Elem().Kind() == reflect.Uint8 {
841 var bytes []byte
842 if f.Kind() == reflect.Slice {
843 bytes = f.Bytes()
844 } else if f.CanAddr() {
845 bytes = f.Slice(0, f.Len()).Bytes()
846 } else {
847
848
849
850 bytes = make([]byte, f.Len())
851 for i := range bytes {
852 bytes[i] = byte(f.Index(i).Uint())
853 }
854 }
855 p.fmtBytes(bytes, verb, t.String())
856 return
857 }
858 }
859 if p.fmt.SharpV {
860 p.WriteString(f.Type().String())
861 if f.Kind() == reflect.Slice && f.IsNil() {
862 p.WriteString(nilParenString)
863 return
864 }
865 p.WriteByte('{')
866 for i := 0; i < f.Len(); i++ {
867 if i > 0 {
868 p.WriteString(commaSpaceString)
869 }
870 p.printValue(f.Index(i), verb, depth+1)
871 }
872 p.WriteByte('}')
873 } else {
874 p.WriteByte('[')
875 for i := 0; i < f.Len(); i++ {
876 if i > 0 {
877 p.WriteByte(' ')
878 }
879 p.printValue(f.Index(i), verb, depth+1)
880 }
881 p.WriteByte(']')
882 }
883 case reflect.Ptr:
884
885
886 if depth == 0 && f.Pointer() != 0 {
887 switch a := f.Elem(); a.Kind() {
888 case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map:
889 p.WriteByte('&')
890 p.printValue(a, verb, depth+1)
891 return
892 }
893 }
894 fallthrough
895 case reflect.Chan, reflect.Func, reflect.UnsafePointer:
896 p.fmtPointer(f, verb)
897 default:
898 p.unknownType(f)
899 }
900 }
901
902 func (p *printer) badArgNum(verb rune) {
903 p.WriteString(percentBangString)
904 p.WriteRune(verb)
905 p.WriteString(badIndexString)
906 }
907
908 func (p *printer) missingArg(verb rune) {
909 p.WriteString(percentBangString)
910 p.WriteRune(verb)
911 p.WriteString(missingString)
912 }
913
914 func (p *printer) doPrintf(fmt string) {
915 for p.fmt.Parser.SetFormat(fmt); p.fmt.Scan(); {
916 switch p.fmt.Status {
917 case format.StatusText:
918 p.WriteString(p.fmt.Text())
919 case format.StatusSubstitution:
920 p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
921 case format.StatusBadWidthSubstitution:
922 p.WriteString(badWidthString)
923 p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
924 case format.StatusBadPrecSubstitution:
925 p.WriteString(badPrecString)
926 p.printArg(p.Arg(p.fmt.ArgNum), p.fmt.Verb)
927 case format.StatusNoVerb:
928 p.WriteString(noVerbString)
929 case format.StatusBadArgNum:
930 p.badArgNum(p.fmt.Verb)
931 case format.StatusMissingArg:
932 p.missingArg(p.fmt.Verb)
933 default:
934 panic("unreachable")
935 }
936 }
937
938
939
940
941
942 if !p.fmt.Reordered && p.fmt.ArgNum < len(p.fmt.Args) && p.fmt.ArgNum != 0 {
943 p.fmt.ClearFlags()
944 p.WriteString(extraString)
945 for i, arg := range p.fmt.Args[p.fmt.ArgNum:] {
946 if i > 0 {
947 p.WriteString(commaSpaceString)
948 }
949 if arg == nil {
950 p.WriteString(nilAngleString)
951 } else {
952 p.WriteString(reflect.TypeOf(arg).String())
953 p.WriteString("=")
954 p.printArg(arg, 'v')
955 }
956 }
957 p.WriteByte(')')
958 }
959 }
960
961 func (p *printer) doPrint(a []interface{}) {
962 prevString := false
963 for argNum, arg := range a {
964 isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String
965
966 if argNum > 0 && !isString && !prevString {
967 p.WriteByte(' ')
968 }
969 p.printArg(arg, 'v')
970 prevString = isString
971 }
972 }
973
974
975
976 func (p *printer) doPrintln(a []interface{}) {
977 for argNum, arg := range a {
978 if argNum > 0 {
979 p.WriteByte(' ')
980 }
981 p.printArg(arg, 'v')
982 }
983 p.WriteByte('\n')
984 }
985
View as plain text