LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package fmt | 5 package fmt |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "io" | 9 "io" |
10 "os" | 10 "os" |
11 "reflect" | 11 "reflect" |
12 "unicode" | 12 "unicode" |
13 "utf8" | 13 "utf8" |
14 ) | 14 ) |
15 | 15 |
16 // Some constants in the form of bytes, to avoid string overhead. | 16 // Some constants in the form of bytes, to avoid string overhead. |
17 // Needlessly fastidious, I suppose. | 17 // Needlessly fastidious, I suppose. |
18 var ( | 18 var ( |
19 commaSpaceBytes = []byte(", ") | 19 commaSpaceBytes = []byte(", ") |
20 nilAngleBytes = []byte("<nil>") | 20 nilAngleBytes = []byte("<nil>") |
21 nilParenBytes = []byte("(nil)") | 21 nilParenBytes = []byte("(nil)") |
22 nilBytes = []byte("nil") | 22 nilBytes = []byte("nil") |
23 mapBytes = []byte("map[") | 23 mapBytes = []byte("map[") |
24 missingBytes = []byte("(MISSING)") | 24 missingBytes = []byte("(MISSING)") |
| 25 panicBytes = []byte("(PANIC=") |
25 extraBytes = []byte("%!(EXTRA ") | 26 extraBytes = []byte("%!(EXTRA ") |
26 irparenBytes = []byte("i)") | 27 irparenBytes = []byte("i)") |
27 bytesBytes = []byte("[]byte{") | 28 bytesBytes = []byte("[]byte{") |
28 widthBytes = []byte("%!(BADWIDTH)") | 29 widthBytes = []byte("%!(BADWIDTH)") |
29 precBytes = []byte("%!(BADPREC)") | 30 precBytes = []byte("%!(BADPREC)") |
30 noVerbBytes = []byte("%!(NOVERB)") | 31 noVerbBytes = []byte("%!(NOVERB)") |
31 ) | 32 ) |
32 | 33 |
33 // State represents the printer state passed to custom formatters. | 34 // State represents the printer state passed to custom formatters. |
34 // It provides access to the io.Writer interface plus information about | 35 // It provides access to the io.Writer interface plus information about |
(...skipping 27 matching lines...) Expand all Loading... |
62 | 63 |
63 // GoStringer is implemented by any value that has a GoString() method, | 64 // GoStringer is implemented by any value that has a GoString() method, |
64 // which defines the Go syntax for that value. | 65 // which defines the Go syntax for that value. |
65 // The GoString method is used to print values passed as an operand | 66 // The GoString method is used to print values passed as an operand |
66 // to a %#v format. | 67 // to a %#v format. |
67 type GoStringer interface { | 68 type GoStringer interface { |
68 GoString() string | 69 GoString() string |
69 } | 70 } |
70 | 71 |
71 type pp struct { | 72 type pp struct { |
72 » n int | 73 » n int |
73 » buf bytes.Buffer | 74 » panicking bool |
74 » runeBuf [utf8.UTFMax]byte | 75 » buf bytes.Buffer |
75 » fmt fmt | 76 » runeBuf [utf8.UTFMax]byte |
| 77 » fmt fmt |
76 } | 78 } |
77 | 79 |
78 // A cache holds a set of reusable objects. | 80 // A cache holds a set of reusable objects. |
79 // The buffered channel holds the currently available objects. | 81 // The buffered channel holds the currently available objects. |
80 // If more are needed, the cache creates them by calling new. | 82 // If more are needed, the cache creates them by calling new. |
81 type cache struct { | 83 type cache struct { |
82 saved chan interface{} | 84 saved chan interface{} |
83 new func() interface{} | 85 new func() interface{} |
84 } | 86 } |
85 | 87 |
(...skipping 18 matching lines...) Expand all Loading... |
104 | 106 |
105 func newCache(f func() interface{}) *cache { | 107 func newCache(f func() interface{}) *cache { |
106 return &cache{make(chan interface{}, 100), f} | 108 return &cache{make(chan interface{}, 100), f} |
107 } | 109 } |
108 | 110 |
109 var ppFree = newCache(func() interface{} { return new(pp) }) | 111 var ppFree = newCache(func() interface{} { return new(pp) }) |
110 | 112 |
111 // Allocate a new pp struct or grab a cached one. | 113 // Allocate a new pp struct or grab a cached one. |
112 func newPrinter() *pp { | 114 func newPrinter() *pp { |
113 p := ppFree.get().(*pp) | 115 p := ppFree.get().(*pp) |
| 116 p.panicking = false |
114 p.fmt.init(&p.buf) | 117 p.fmt.init(&p.buf) |
115 return p | 118 return p |
116 } | 119 } |
117 | 120 |
118 // Save used pp structs in ppFree; avoids an allocation per invocation. | 121 // Save used pp structs in ppFree; avoids an allocation per invocation. |
119 func (p *pp) free() { | 122 func (p *pp) free() { |
120 // Don't hold on to pp structs with large buffers. | 123 // Don't hold on to pp structs with large buffers. |
121 if cap(p.buf.Bytes()) > 1024 { | 124 if cap(p.buf.Bytes()) > 1024 { |
122 return | 125 return |
123 } | 126 } |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 } | 562 } |
560 } | 563 } |
561 | 564 |
562 var ( | 565 var ( |
563 intBits = reflect.TypeOf(0).Bits() | 566 intBits = reflect.TypeOf(0).Bits() |
564 floatBits = reflect.TypeOf(0.0).Bits() | 567 floatBits = reflect.TypeOf(0.0).Bits() |
565 complexBits = reflect.TypeOf(1i).Bits() | 568 complexBits = reflect.TypeOf(1i).Bits() |
566 uintptrBits = reflect.TypeOf(uintptr(0)).Bits() | 569 uintptrBits = reflect.TypeOf(uintptr(0)).Bits() |
567 ) | 570 ) |
568 | 571 |
| 572 func (p *pp) catchPanic(val interface{}, verb int) { |
| 573 if err := recover(); err != nil { |
| 574 // If it's a nil pointer, just say "<nil>". The likeliest causes
are a |
| 575 // Stringer that fails to guard against nil or a nil pointer for
a |
| 576 // value receiver, and in either case, "<nil>" is a nice result. |
| 577 if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr && v.IsNil
() { |
| 578 p.buf.Write(nilAngleBytes) |
| 579 return |
| 580 } |
| 581 // Otherwise print a concise panic message. Most of the time the
panic |
| 582 // value will print itself nicely. |
| 583 if p.panicking { |
| 584 // Nested panics; the recursion in printField cannot suc
ceed. |
| 585 panic(err) |
| 586 } |
| 587 p.buf.WriteByte('%') |
| 588 p.add(verb) |
| 589 p.buf.Write(panicBytes) |
| 590 p.panicking = true |
| 591 p.printField(err, 'v', false, false, 0) |
| 592 p.panicking = false |
| 593 p.buf.WriteByte(')') |
| 594 } |
| 595 } |
| 596 |
569 func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
int) (wasString bool) { | 597 func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
int) (wasString bool) { |
570 if field == nil { | 598 if field == nil { |
571 if verb == 'T' || verb == 'v' { | 599 if verb == 'T' || verb == 'v' { |
572 p.buf.Write(nilAngleBytes) | 600 p.buf.Write(nilAngleBytes) |
573 } else { | 601 } else { |
574 p.badVerb(verb, field) | 602 p.badVerb(verb, field) |
575 } | 603 } |
576 return false | 604 return false |
577 } | 605 } |
578 | 606 |
579 // Special processing considerations. | 607 // Special processing considerations. |
580 // %T (the value's type) and %p (its address) are special; we always do
them first. | 608 // %T (the value's type) and %p (its address) are special; we always do
them first. |
581 switch verb { | 609 switch verb { |
582 case 'T': | 610 case 'T': |
583 p.printField(reflect.TypeOf(field).String(), 's', false, false,
0) | 611 p.printField(reflect.TypeOf(field).String(), 's', false, false,
0) |
584 return false | 612 return false |
585 case 'p': | 613 case 'p': |
586 p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax) | 614 p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax) |
587 return false | 615 return false |
588 } | 616 } |
589 // Is it a Formatter? | 617 // Is it a Formatter? |
590 if formatter, ok := field.(Formatter); ok { | 618 if formatter, ok := field.(Formatter); ok { |
| 619 defer p.catchPanic(field, verb) |
591 formatter.Format(p, verb) | 620 formatter.Format(p, verb) |
592 return false // this value is not a string | 621 return false // this value is not a string |
593 | 622 |
594 } | 623 } |
595 // Must not touch flags before Formatter looks at them. | 624 // Must not touch flags before Formatter looks at them. |
596 if plus { | 625 if plus { |
597 p.fmt.plus = false | 626 p.fmt.plus = false |
598 } | 627 } |
599 // If we're doing Go syntax and the field knows how to supply it, take c
are of it now. | 628 // If we're doing Go syntax and the field knows how to supply it, take c
are of it now. |
600 if goSyntax { | 629 if goSyntax { |
601 p.fmt.sharp = false | 630 p.fmt.sharp = false |
602 if stringer, ok := field.(GoStringer); ok { | 631 if stringer, ok := field.(GoStringer); ok { |
| 632 defer p.catchPanic(field, verb) |
603 // Print the result of GoString unadorned. | 633 // Print the result of GoString unadorned. |
604 p.fmtString(stringer.GoString(), 's', false, field) | 634 p.fmtString(stringer.GoString(), 's', false, field) |
605 return false // this value is not a string | 635 return false // this value is not a string |
606 } | 636 } |
607 } else { | 637 } else { |
608 // Is it a Stringer? | 638 // Is it a Stringer? |
609 if stringer, ok := field.(Stringer); ok { | 639 if stringer, ok := field.(Stringer); ok { |
| 640 defer p.catchPanic(field, verb) |
610 p.printField(stringer.String(), verb, plus, false, depth
) | 641 p.printField(stringer.String(), verb, plus, false, depth
) |
611 return false // this value is not a string | 642 return false // this value is not a string |
612 } | 643 } |
613 } | 644 } |
614 | 645 |
615 // Some types can be done without reflection. | 646 // Some types can be done without reflection. |
616 switch f := field.(type) { | 647 switch f := field.(type) { |
617 case bool: | 648 case bool: |
618 p.fmtBool(f, verb, field) | 649 p.fmtBool(f, verb, field) |
619 return false | 650 return false |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 if addspace || !isString && !prevString { | 987 if addspace || !isString && !prevString { |
957 p.buf.WriteByte(' ') | 988 p.buf.WriteByte(' ') |
958 } | 989 } |
959 } | 990 } |
960 prevString = p.printField(field, 'v', false, false, 0) | 991 prevString = p.printField(field, 'v', false, false, 0) |
961 } | 992 } |
962 if addnewline { | 993 if addnewline { |
963 p.buf.WriteByte('\n') | 994 p.buf.WriteByte('\n') |
964 } | 995 } |
965 } | 996 } |
LEFT | RIGHT |