Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(338)

Delta Between Two Patch Sets: src/pkg/fmt/print.go

Issue 4607052: code review 4607052: os.Error API: don't export os.ErrorString, use os.NewEr... (Closed)
Left Patch Set: diff -r 3a5f42c956e0 https://go.googlecode.com/hg/ Created 13 years, 9 months ago
Right Patch Set: diff -r 6e3e06fb2dc3 https://go.googlecode.com/hg/ Created 13 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/exec/lp_windows.go ('k') | src/pkg/fmt/scan.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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
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
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
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 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b