diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-12-14 15:41:54 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-12-14 15:41:54 +0000 |
commit | d5363590597572228d4e0d0ae13f3469176ceb14 (patch) | |
tree | e3de46cbc89d82ca1f49843fe2e1e670db67795e /libgo/go/fmt | |
parent | ef0d4c4d9937276c8ff818ecb0b92925d322d3bd (diff) | |
download | gcc-d5363590597572228d4e0d0ae13f3469176ceb14.zip gcc-d5363590597572228d4e0d0ae13f3469176ceb14.tar.gz gcc-d5363590597572228d4e0d0ae13f3469176ceb14.tar.bz2 |
libgo: Update to weekly.2011-12-06.
From-SVN: r182338
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r-- | libgo/go/fmt/doc.go | 16 | ||||
-rw-r--r-- | libgo/go/fmt/fmt_test.go | 64 | ||||
-rw-r--r-- | libgo/go/fmt/format.go | 24 | ||||
-rw-r--r-- | libgo/go/fmt/print.go | 42 | ||||
-rw-r--r-- | libgo/go/fmt/scan.go | 8 |
5 files changed, 92 insertions, 62 deletions
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index 6713f0a1..11e9f19 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -89,18 +89,22 @@ If an operand implements interface Formatter, that interface can be used for fine control of formatting. - Next, if an operand implements the error interface, the Error method + If the format (which is implicitly %v for Println etc.) is valid + for a string (%s %q %v %x %X), the following two rules also apply: + + 1. If an operand implements the error interface, the Error method will be used to convert the object to a string, which will then be formatted as required by the verb (if any). - Finally, if an operand implements method String() string that method + 2. If an operand implements method String() string, that method will be used to convert the object to a string, which will then be formatted as required by the verb (if any). + To avoid recursion in cases such as - type X int - func (x X) String() string { return Sprintf("%d", x) } - cast the value before recurring: - func (x X) String() string { return Sprintf("%d", int(x)) } + type X string + func (x X) String() string { return Sprintf("<%s>", x) } + convert the value before recurring: + func (x X) String() string { return Sprintf("<%s>", string(x)) } Format errors: diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index 00aac79..63c3338 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -12,6 +12,7 @@ import ( "runtime" // for the malloc count test only "strings" "testing" + "time" ) type ( @@ -352,7 +353,7 @@ var fmttests = []struct { {"%s", I(23), `<23>`}, {"%q", I(23), `"<23>"`}, {"%x", I(23), `3c32333e`}, - {"%d", I(23), `%!d(string=<23>)`}, + {"%d", I(23), `23`}, // Stringer applies only to string formats. // go syntax {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, @@ -361,8 +362,8 @@ var fmttests = []struct { {"%#v", make(chan int), "(chan int)(0xPTR)"}, {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, {"%#v", 1000000000, "1000000000"}, - {"%#v", map[string]int{"a": 1}, `map[string] int{"a":1}`}, - {"%#v", map[string]B{"a": {1, 2}}, `map[string] fmt_test.B{"a":fmt_test.B{I:1, j:2}}`}, + {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`}, + {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`}, {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`}, {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`}, {"%#v", []int(nil), `[]int(nil)`}, @@ -371,8 +372,8 @@ var fmttests = []struct { {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`}, {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, {"%#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", map[int]byte(nil), `map[int]uint8(nil)`}, + {"%#v", map[int]byte{}, `map[int]uint8{}`}, // slices with other formats {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, @@ -430,6 +431,10 @@ var fmttests = []struct { {"%p", make([]int, 1), "0xPTR"}, {"%p", 27, "%!p(int=27)"}, // not a pointer at all + // %d on Stringer should give integer if possible + {"%s", time.Time{}.Month(), "January"}, + {"%d", time.Time{}.Month(), "1"}, + // erroneous things {"%s %", "hello", "hello %!(NOVERB)"}, {"%s %.2", "hello", "hello %!(NOVERB)"}, @@ -495,69 +500,84 @@ func BenchmarkSprintfPrefixedInt(b *testing.B) { } } +func BenchmarkSprintfFloat(b *testing.B) { + for i := 0; i < b.N; i++ { + Sprintf("%g", 5.23184) + } +} + func TestCountMallocs(t *testing.T) { if testing.Short() { return } + const N = 100 runtime.UpdateMemStats() mallocs := 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { Sprintf("") } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100) + Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/N) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { Sprintf("xxx") } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100) + Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/N) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { Sprintf("%x", i) } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100) + Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/N) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { Sprintf("%s", "hello") } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100) + Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/N) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { Sprintf("%x %x", i, i) } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100) + Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/N) + runtime.UpdateMemStats() + mallocs = 0 - runtime.MemStats.Mallocs + for i := 0; i < N; i++ { + Sprintf("%g", 3.14159) + } + runtime.UpdateMemStats() + mallocs += runtime.MemStats.Mallocs + Printf("mallocs per Sprintf(\"%%g\"): %d\n", mallocs/N) buf := new(bytes.Buffer) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { buf.Reset() Fprintf(buf, "%x %x %x", i, i, i) } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100) + Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/N) runtime.UpdateMemStats() mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { + for i := 0; i < N; i++ { buf.Reset() Fprintf(buf, "%s", "hello") } runtime.UpdateMemStats() mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100) + Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/N) } type flagPrinter struct{} @@ -772,9 +792,9 @@ var panictests = []struct { out string }{ // String - {"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"}, - {"%d", Panic{3}, "%d(PANIC=3)"}, + {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case + {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"}, + {"%s", Panic{3}, "%s(PANIC=3)"}, // GoString {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"}, diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index 3957a5a..fbafa9d 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -360,44 +360,44 @@ func (f *fmt) plusSpace(s string) { } // fmt_e64 formats a float64 in the form -1.23e+12. -func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) } +func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'e', doPrec(f, 6), 64)) } // fmt_E64 formats a float64 in the form -1.23E+12. -func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) } +func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'E', doPrec(f, 6), 64)) } // fmt_f64 formats a float64 in the form -1.23. -func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) } +func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'f', doPrec(f, 6), 64)) } // fmt_g64 formats a float64 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) } +func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'g', doPrec(f, -1), 64)) } // fmt_g64 formats a float64 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) } +func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'G', doPrec(f, -1), 64)) } // fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) } +func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.FormatFloat(v, 'b', 0, 64)) } // float32 // cannot defer to float64 versions // because it will get rounding wrong in corner cases. // fmt_e32 formats a float32 in the form -1.23e+12. -func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) } +func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'e', doPrec(f, 6), 32)) } // fmt_E32 formats a float32 in the form -1.23E+12. -func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) } +func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'E', doPrec(f, 6), 32)) } // fmt_f32 formats a float32 in the form -1.23. -func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) } +func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'f', doPrec(f, 6), 32)) } // fmt_g32 formats a float32 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) } +func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'g', doPrec(f, -1), 32)) } // fmt_G32 formats a float32 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) } +func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.FormatFloat(float64(v), 'G', doPrec(f, -1), 32)) } // fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) } +func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.FormatFloat(float64(v), 'b', 0, 32)) } // fmt_c64 formats a complex64 according to the verb. func (f *fmt) fmt_c64(v complex64, verb rune) { diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index e5ca117..8b15a82 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -631,24 +631,30 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString return } } else { - // Is it an error or Stringer? - // The duplication in the bodies is necessary: - // setting wasString and handled and deferring catchPanic - // must happen before calling the method. - switch v := p.field.(type) { - case error: - wasString = false - handled = true - defer p.catchPanic(p.field, verb) - p.printField(v.Error(), verb, plus, false, depth) - return - - case Stringer: - wasString = false - handled = true - defer p.catchPanic(p.field, verb) - p.printField(v.String(), verb, plus, false, depth) - return + // If a string is acceptable according to the format, see if + // the value satisfies one of the string-valued interfaces. + // Println etc. set verb to %v, which is "stringable". + switch verb { + case 'v', 's', 'x', 'X', 'q': + // Is it an error or Stringer? + // The duplication in the bodies is necessary: + // setting wasString and handled, and deferring catchPanic, + // must happen before calling the method. + switch v := p.field.(type) { + case error: + wasString = false + handled = true + defer p.catchPanic(p.field, verb) + p.printField(v.Error(), verb, plus, false, depth) + return + + case Stringer: + wasString = false + handled = true + defer p.catchPanic(p.field, verb) + p.printField(v.String(), verb, plus, false, depth) + return + } } } handled = false diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index 85571e8..2815251 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -613,7 +613,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 { } } tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoi64(tok, base) + i, err := strconv.ParseInt(tok, base, 64) if err != nil { s.error(err) } @@ -643,7 +643,7 @@ func (s *ss) scanUint(verb rune, bitSize int) uint64 { base, digits, haveDigits = s.scanBasePrefix() } tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoui64(tok, base) + i, err := strconv.ParseUint(tok, base, 64) if err != nil { s.error(err) } @@ -719,7 +719,7 @@ func (s *ss) convertFloat(str string, n int) float64 { if p := strings.Index(str, "p"); p >= 0 { // Atof doesn't handle power-of-2 exponents, // but they're easy to evaluate. - f, err := strconv.AtofN(str[:p], n) + f, err := strconv.ParseFloat(str[:p], n) if err != nil { // Put full string into error. if e, ok := err.(*strconv.NumError); ok { @@ -737,7 +737,7 @@ func (s *ss) convertFloat(str string, n int) float64 { } return math.Ldexp(f, n) } - f, err := strconv.AtofN(str, n) + f, err := strconv.ParseFloat(str, n) if err != nil { s.error(err) } |