aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/fmt
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-12-14 15:41:54 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-12-14 15:41:54 +0000
commitd5363590597572228d4e0d0ae13f3469176ceb14 (patch)
treee3de46cbc89d82ca1f49843fe2e1e670db67795e /libgo/go/fmt
parentef0d4c4d9937276c8ff818ecb0b92925d322d3bd (diff)
downloadgcc-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.go16
-rw-r--r--libgo/go/fmt/fmt_test.go64
-rw-r--r--libgo/go/fmt/format.go24
-rw-r--r--libgo/go/fmt/print.go42
-rw-r--r--libgo/go/fmt/scan.go8
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)
}