diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-10-23 04:31:11 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-10-23 04:31:11 +0000 |
commit | 4ccad563d2a3559f0557bfb177bcf45144219bdf (patch) | |
tree | 46bb86f514fbf6bad82da48e69a18fb09d878834 /libgo/go/fmt | |
parent | 0b7463235f0e23c624d1911c9b15f531108cc5a6 (diff) | |
download | gcc-4ccad563d2a3559f0557bfb177bcf45144219bdf.zip gcc-4ccad563d2a3559f0557bfb177bcf45144219bdf.tar.gz gcc-4ccad563d2a3559f0557bfb177bcf45144219bdf.tar.bz2 |
libgo: Update to current sources.
From-SVN: r192704
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r-- | libgo/go/fmt/fmt_test.go | 38 | ||||
-rw-r--r-- | libgo/go/fmt/format.go | 55 | ||||
-rw-r--r-- | libgo/go/fmt/print.go | 41 | ||||
-rw-r--r-- | libgo/go/fmt/scan.go | 3 | ||||
-rw-r--r-- | libgo/go/fmt/scan_test.go | 27 |
5 files changed, 135 insertions, 29 deletions
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index 98ebfb7..f704b7d 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -127,6 +127,10 @@ var fmttests = []struct { {"%s", []byte("abc"), "abc"}, {"%x", []byte("abc"), "616263"}, {"% x", []byte("abc\xff"), "61 62 63 ff"}, + {"%#x", []byte("abc\xff"), "0x610x620x630xff"}, + {"%#X", []byte("abc\xff"), "0X610X620X630XFF"}, + {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"}, + {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"}, {"% X", []byte("abc\xff"), "61 62 63 FF"}, {"%x", []byte("xyz"), "78797a"}, {"%X", []byte("xyz"), "78797A"}, @@ -350,10 +354,12 @@ var fmttests = []struct { {"%+v", B{1, 2}, `{I:<1> j:2}`}, {"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`}, - // q on Stringable items + // other formats on Stringable items {"%s", I(23), `<23>`}, {"%q", I(23), `"<23>"`}, {"%x", I(23), `3c32333e`}, + {"%#x", I(23), `0x3c0x320x330x3e`}, + {"%# x", I(23), `0x3c 0x32 0x33 0x3e`}, {"%d", I(23), `23`}, // Stringer applies only to string formats. // go syntax @@ -375,6 +381,7 @@ var fmttests = []struct { {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, {"%#v", map[int]byte(nil), `map[int]uint8(nil)`}, {"%#v", map[int]byte{}, `map[int]uint8{}`}, + {"%#v", "foo", `"foo"`}, // slices with other formats {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, @@ -441,6 +448,11 @@ var fmttests = []struct { {"%v", (*int)(nil), "<nil>"}, {"%v", new(int), "0xPTR"}, + // %d etc. pointers use specified base. + {"%d", new(int), "PTR_d"}, + {"%o", new(int), "PTR_o"}, + {"%x", new(int), "PTR_x"}, + // %d on Stringer should give integer if possible {"%s", time.Time{}.Month(), "January"}, {"%d", time.Time{}.Month(), "1"}, @@ -470,14 +482,26 @@ func TestSprintf(t *testing.T) { for _, tt := range fmttests { s := Sprintf(tt.fmt, tt.val) if i := strings.Index(tt.out, "PTR"); i >= 0 { + pattern := "PTR" + chars := "0123456789abcdefABCDEF" + switch { + case strings.HasPrefix(tt.out[i:], "PTR_d"): + pattern = "PTR_d" + chars = chars[:10] + case strings.HasPrefix(tt.out[i:], "PTR_o"): + pattern = "PTR_o" + chars = chars[:8] + case strings.HasPrefix(tt.out[i:], "PTR_x"): + pattern = "PTR_x" + } j := i for ; j < len(s); j++ { c := s[j] - if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') { + if !strings.ContainsRune(chars, rune(c)) { break } } - s = s[0:i] + "PTR" + s[j:] + s = s[0:i] + pattern + s[j:] } if s != tt.out { if _, ok := tt.val.(string); ok { @@ -527,6 +551,14 @@ func BenchmarkSprintfFloat(b *testing.B) { } } +func BenchmarkManyArgs(b *testing.B) { + var buf bytes.Buffer + for i := 0; i < b.N; i++ { + buf.Reset() + Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world") + } +} + var mallocBuf bytes.Buffer // gccgo numbers are different because gccgo does not have escape diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index caf900d..ce80116 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -110,11 +110,11 @@ func (f *fmt) writePadding(n int, padding []byte) { // Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus) // clear flags afterwards. func (f *fmt) pad(b []byte) { - var padding []byte - var left, right int - if f.widPresent && f.wid != 0 { - padding, left, right = f.computePadding(len(b)) + if !f.widPresent || f.wid == 0 { + f.buf.Write(b) + return } + padding, left, right := f.computePadding(len(b)) if left > 0 { f.writePadding(left, padding) } @@ -127,11 +127,11 @@ func (f *fmt) pad(b []byte) { // append s to buf, padded on left (w > 0) or right (w < 0 or f.minus). // clear flags afterwards. func (f *fmt) padString(s string) { - var padding []byte - var left, right int - if f.widPresent && f.wid != 0 { - padding, left, right = f.computePadding(utf8.RuneCountInString(s)) + if !f.widPresent || f.wid == 0 { + f.buf.WriteString(s) + return } + padding, left, right := f.computePadding(utf8.RuneCountInString(s)) if left > 0 { f.writePadding(left, padding) } @@ -285,18 +285,41 @@ func (f *fmt) fmt_s(s string) { f.padString(s) } -// fmt_sx formats a string as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sx(s, digits string) { +// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes. +func (f *fmt) fmt_sbx(s string, b []byte, digits string) { + n := len(b) + if b == nil { + n = len(s) + } + x := digits[10] - 'a' + 'x' // TODO: Avoid buffer by pre-padding. - var b []byte - for i := 0; i < len(s); i++ { + var buf []byte + for i := 0; i < n; i++ { if i > 0 && f.space { - b = append(b, ' ') + buf = append(buf, ' ') + } + if f.sharp { + buf = append(buf, '0', x) + } + var c byte + if b == nil { + c = s[i] + } else { + c = b[i] } - v := s[i] - b = append(b, digits[v>>4], digits[v&0xF]) + buf = append(buf, digits[c>>4], digits[c&0xF]) } - f.pad(b) + f.pad(buf) +} + +// fmt_sx formats a string as a hexadecimal encoding of its bytes. +func (f *fmt) fmt_sx(s, digits string) { + f.fmt_sbx(s, nil, digits) +} + +// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes. +func (f *fmt) fmt_bx(b []byte, digits string) { + f.fmt_sbx("", b, digits) } // fmt_q formats a string as a double-quoted, escaped Go string constant. diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index f29e8c8..13e5873 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -569,24 +569,27 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, depth int) { } return } - s := string(v) switch verb { case 's': - p.fmt.fmt_s(s) + p.fmt.fmt_s(string(v)) case 'x': - p.fmt.fmt_sx(s, ldigits) + p.fmt.fmt_bx(v, ldigits) case 'X': - p.fmt.fmt_sx(s, udigits) + p.fmt.fmt_bx(v, udigits) case 'q': - p.fmt.fmt_q(s) + p.fmt.fmt_q(string(v)) default: p.badVerb(verb) } } func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { + use0x64 := true switch verb { - case 'p', 'v', 'b', 'd', 'o', 'x', 'X': + case 'p', 'v': + // ok + case 'b', 'd', 'o', 'x', 'X': + use0x64 = false // ok default: p.badVerb(verb) @@ -616,7 +619,11 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { } else if verb == 'v' && u == 0 { p.buf.Write(nilAngleBytes) } else { - p.fmt0x64(uint64(u), !p.fmt.sharp) + if use0x64 { + p.fmt0x64(uint64(u), !p.fmt.sharp) + } else { + p.fmtUint64(uint64(u), verb, false) + } } } @@ -735,8 +742,17 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth return false } - if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return wasString + // Clear flags for base formatters. + // handleMethods needs them, so we must restore them later. + // We could call handleMethods here and avoid this work, but + // handleMethods is expensive enough to be worth delaying. + oldPlus := p.fmt.plus + oldSharp := p.fmt.sharp + if plus { + p.fmt.plus = false + } + if goSyntax { + p.fmt.sharp = false } // Some types can be done without reflection. @@ -780,6 +796,13 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth p.fmtBytes(f, verb, goSyntax, depth) wasString = verb == 's' default: + // Restore flags in case handleMethods finds a Formatter. + p.fmt.plus = oldPlus + p.fmt.sharp = oldSharp + // If the type is not simple, it might have methods. + if wasString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { + return wasString + } // Need to use reflection return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth) } diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index 0b3e040..d69911c 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -1090,7 +1090,8 @@ func (s *ss) advance(format string) (i int) { // There was space in the format, so there should be space (EOF) // in the input. inputc := s.getRune() - if inputc == eof { + if inputc == eof || inputc == '\n' { + // If we've reached a newline, stop now; don't read ahead. return } if !isSpace(inputc) { diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go index 320857b..cc09e91 100644 --- a/libgo/go/fmt/scan_test.go +++ b/libgo/go/fmt/scan_test.go @@ -810,6 +810,33 @@ func TestMultiLine(t *testing.T) { } } +// simpleReader is a strings.Reader that implements only Read, not ReadRune. +// Good for testing readahead. +type simpleReader struct { + sr *strings.Reader +} + +func (s *simpleReader) Read(b []byte) (n int, err error) { + return s.sr.Read(b) +} + +// Test that Fscanf does not read past newline. Issue 3481. +func TestLineByLineFscanf(t *testing.T) { + r := &simpleReader{strings.NewReader("1\n2\n")} + var i, j int + n, err := Fscanf(r, "%v\n", &i) + if n != 1 || err != nil { + t.Fatalf("first read: %d %q", n, err) + } + n, err = Fscanf(r, "%v\n", &j) + if n != 1 || err != nil { + t.Fatalf("second read: %d %q", n, err) + } + if i != 1 || j != 2 { + t.Errorf("wrong values; wanted 1 2 got %d %d", i, j) + } +} + // RecursiveInt accepts a string matching %d.%d.%d.... // and parses it into a linked list. // It allows us to benchmark recursive descent style scanners. |