summaryrefslogtreecommitdiff
path: root/src/pkg/fmt
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/fmt')
-rw-r--r--src/pkg/fmt/doc.go26
-rw-r--r--src/pkg/fmt/fmt_test.go68
-rw-r--r--src/pkg/fmt/format.go33
-rw-r--r--src/pkg/fmt/print.go57
-rw-r--r--src/pkg/fmt/scan.go21
-rw-r--r--src/pkg/fmt/scan_test.go24
-rw-r--r--src/pkg/fmt/stringer_test.go4
7 files changed, 99 insertions, 134 deletions
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go
index f3067eac9..02c29389d 100644
--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -26,7 +26,7 @@
%o base 8
%x base 16, with lower-case letters for a-f
%X base 16, with upper-case letters for A-F
- %U unicode format: U+1234; same as "U+%x" with 4 digits default
+ %U Unicode format: U+1234; same as "U+%x" with 4 digits default
Floating-point and complex constituents:
%e scientific notation, e.g. -1234.456e+78
%E scientific notation, e.g. -1234.456E+78
@@ -36,21 +36,27 @@
String and slice of bytes:
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Go syntax
- %x base 16 notation with two characters per byte
+ %x base 16, lower-case, two characters per byte
+ %X base 16, upper-case, two characters per byte
Pointer:
%p base 16 notation, with leading 0x
There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
Similarly, there is no need to specify the size of the operand (int8, int64).
- For numeric values, the width and precision flags control
- formatting; width sets the width of the field, precision the
- number of places after the decimal, if appropriate. The
- format %6.2f prints 123.45. The width of a field is the number
- of Unicode code points in the string. This differs from C's printf where
- the field width is the number of bytes. Either or both of the
- flags may be replaced with the character '*', causing their values
- to be obtained from the next operand, which must be of type int.
+ The width and precision control formatting and are in units of Unicode
+ code points. (This differs from C's printf where the units are numbers
+ of bytes.) Either or both of the flags may be replaced with the
+ character '*', causing their values to be obtained from the next
+ operand, which must be of type int.
+
+ For numeric values, width sets the width of the field and precision
+ sets the number of places after the decimal, if appropriate. For
+ example, the format %6.2f prints 123.45.
+
+ For strings, width is the minimum number of characters to output,
+ padding with spaces if necessary, and precision is the maximum
+ number of characters to output, truncating if necessary.
Other flags:
+ always print a sign for numeric values
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go
index 0aafe6d99..3f085b722 100644
--- a/src/pkg/fmt/fmt_test.go
+++ b/src/pkg/fmt/fmt_test.go
@@ -28,10 +28,8 @@ type (
renamedUintptr uintptr
renamedString string
renamedBytes []byte
- renamedFloat float
renamedFloat32 float32
renamedFloat64 float64
- renamedComplex complex
renamedComplex64 complex64
renamedComplex128 complex128
)
@@ -224,31 +222,31 @@ var fmttests = []struct {
{"%b", 7, "111"},
{"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"},
{"%b", -6, "-110"},
- {"%e", float64(1), "1.000000e+00"},
- {"%e", float64(1234.5678e3), "1.234568e+06"},
- {"%e", float64(1234.5678e-8), "1.234568e-05"},
- {"%e", float64(-7), "-7.000000e+00"},
- {"%e", float64(-1e-9), "-1.000000e-09"},
- {"%f", float64(1234.5678e3), "1234567.800000"},
- {"%f", float64(1234.5678e-8), "0.000012"},
- {"%f", float64(-7), "-7.000000"},
- {"%f", float64(-1e-9), "-0.000000"},
- {"%g", float64(1234.5678e3), "1.2345678e+06"},
+ {"%e", 1.0, "1.000000e+00"},
+ {"%e", 1234.5678e3, "1.234568e+06"},
+ {"%e", 1234.5678e-8, "1.234568e-05"},
+ {"%e", -7.0, "-7.000000e+00"},
+ {"%e", -1e-9, "-1.000000e-09"},
+ {"%f", 1234.5678e3, "1234567.800000"},
+ {"%f", 1234.5678e-8, "0.000012"},
+ {"%f", -7.0, "-7.000000"},
+ {"%f", -1e-9, "-0.000000"},
+ {"%g", 1234.5678e3, "1.2345678e+06"},
{"%g", float32(1234.5678e3), "1.2345678e+06"},
- {"%g", float64(1234.5678e-8), "1.2345678e-05"},
- {"%g", float64(-7), "-7"},
- {"%g", float64(-1e-9), "-1e-09"},
+ {"%g", 1234.5678e-8, "1.2345678e-05"},
+ {"%g", -7.0, "-7"},
+ {"%g", -1e-9, "-1e-09"},
{"%g", float32(-1e-9), "-1e-09"},
- {"%E", float64(1), "1.000000E+00"},
- {"%E", float64(1234.5678e3), "1.234568E+06"},
- {"%E", float64(1234.5678e-8), "1.234568E-05"},
- {"%E", float64(-7), "-7.000000E+00"},
- {"%E", float64(-1e-9), "-1.000000E-09"},
- {"%G", float64(1234.5678e3), "1.2345678E+06"},
+ {"%E", 1.0, "1.000000E+00"},
+ {"%E", 1234.5678e3, "1.234568E+06"},
+ {"%E", 1234.5678e-8, "1.234568E-05"},
+ {"%E", -7.0, "-7.000000E+00"},
+ {"%E", -1e-9, "-1.000000E-09"},
+ {"%G", 1234.5678e3, "1.2345678E+06"},
{"%G", float32(1234.5678e3), "1.2345678E+06"},
- {"%G", float64(1234.5678e-8), "1.2345678E-05"},
- {"%G", float64(-7), "-7"},
- {"%G", float64(-1e-9), "-1E-09"},
+ {"%G", 1234.5678e-8, "1.2345678E-05"},
+ {"%G", -7.0, "-7"},
+ {"%G", -1e-9, "-1E-09"},
{"%G", float32(-1e-9), "-1E-09"},
{"%c", 'x', "x"},
{"%c", 0xe4, "รค"},
@@ -273,15 +271,15 @@ var fmttests = []struct {
{"%20e", 1.2345e3, " 1.234500e+03"},
{"%20e", 1.2345e-3, " 1.234500e-03"},
{"%20.8e", 1.2345e3, " 1.23450000e+03"},
- {"%20f", float64(1.23456789e3), " 1234.567890"},
- {"%20f", float64(1.23456789e-3), " 0.001235"},
- {"%20f", float64(12345678901.23456789), " 12345678901.234568"},
- {"%-20f", float64(1.23456789e3), "1234.567890 "},
- {"%20.8f", float64(1.23456789e3), " 1234.56789000"},
- {"%20.8f", float64(1.23456789e-3), " 0.00123457"},
- {"%g", float64(1.23456789e3), "1234.56789"},
- {"%g", float64(1.23456789e-3), "0.00123456789"},
- {"%g", float64(1.23456789e20), "1.23456789e+20"},
+ {"%20f", 1.23456789e3, " 1234.567890"},
+ {"%20f", 1.23456789e-3, " 0.001235"},
+ {"%20f", 12345678901.23456789, " 12345678901.234568"},
+ {"%-20f", 1.23456789e3, "1234.567890 "},
+ {"%20.8f", 1.23456789e3, " 1234.56789000"},
+ {"%20.8f", 1.23456789e-3, " 0.00123457"},
+ {"%g", 1.23456789e3, "1234.56789"},
+ {"%g", 1.23456789e-3, "0.00123456789"},
+ {"%g", 1.23456789e20, "1.23456789e+20"},
{"%20e", math.Inf(1), " +Inf"},
{"%-20f", math.Inf(-1), "-Inf "},
{"%20g", math.NaN(), " NaN"},
@@ -346,10 +344,8 @@ var fmttests = []struct {
{"%x", renamedString("thing"), "7468696e67"},
{"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
{"%q", renamedBytes([]byte("hello")), `"hello"`},
- {"%v", renamedFloat(11), "11"},
{"%v", renamedFloat32(22), "22"},
{"%v", renamedFloat64(33), "33"},
- {"%v", renamedComplex(7 + .2i), "(7+0.2i)"},
{"%v", renamedComplex64(3 + 4i), "(3+4i)"},
{"%v", renamedComplex128(4 - 3i), "(4-3i)"},
@@ -363,7 +359,7 @@ var fmttests = []struct {
{"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"},
// %T
- {"%T", (4 - 3i), "complex"},
+ {"%T", (4 - 3i), "complex128"},
{"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
{"%T", intVal, "int"},
{"%6T", &intVal, " *int"},
diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go
index 0121dda31..86057bf69 100644
--- a/src/pkg/fmt/format.go
+++ b/src/pkg/fmt/format.go
@@ -396,36 +396,3 @@ func (f *fmt) fmt_c128(v complex128, verb int) {
}
f.buf.Write(irparenBytes)
}
-
-// float
-func (x *fmt) f(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_f32(float32(a))
- } else {
- x.fmt_f64(float64(a))
- }
-}
-
-func (x *fmt) e(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_e32(float32(a))
- } else {
- x.fmt_e64(float64(a))
- }
-}
-
-func (x *fmt) g(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_g32(float32(a))
- } else {
- x.fmt_g64(float64(a))
- }
-}
-
-func (x *fmt) fb(a float) {
- if strconv.FloatSize == 32 {
- x.fmt_fb32(float32(a))
- } else {
- x.fmt_fb64(float64(a))
- }
-}
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index 412260441..d6dc8eb3d 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -74,15 +74,42 @@ type pp struct {
fmt fmt
}
-// A leaky bucket of reusable pp structures.
-var ppFree = make(chan *pp, 100)
+// A cache holds a set of reusable objects.
+// The buffered channel holds the currently available objects.
+// If more are needed, the cache creates them by calling new.
+type cache struct {
+ saved chan interface{}
+ new func() interface{}
+}
+
+func (c *cache) put(x interface{}) {
+ select {
+ case c.saved <- x:
+ // saved in cache
+ default:
+ // discard
+ }
+}
-// Allocate a new pp struct. Probably can grab the previous one from ppFree.
-func newPrinter() *pp {
- p, ok := <-ppFree
- if !ok {
- p = new(pp)
+func (c *cache) get() interface{} {
+ select {
+ case x := <-c.saved:
+ return x // reused from cache
+ default:
+ return c.new()
}
+ panic("not reached")
+}
+
+func newCache(f func() interface{}) *cache {
+ return &cache{make(chan interface{}, 100), f}
+}
+
+var ppFree = newCache(func() interface{} { return new(pp) })
+
+// Allocate a new pp struct or grab a cached one.
+func newPrinter() *pp {
+ p := ppFree.get().(*pp)
p.fmt.init(&p.buf)
return p
}
@@ -94,7 +121,7 @@ func (p *pp) free() {
return
}
p.buf.Reset()
- _ = ppFree <- p
+ ppFree.put(p)
}
func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent }
@@ -573,26 +600,12 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
case bool:
p.fmtBool(f, verb, field)
return false
- case float:
- if floatBits == 32 {
- p.fmtFloat32(float32(f), verb, field)
- } else {
- p.fmtFloat64(float64(f), verb, field)
- }
- return false
case float32:
p.fmtFloat32(f, verb, field)
return false
case float64:
p.fmtFloat64(f, verb, field)
return false
- case complex:
- if complexBits == 64 {
- p.fmtComplex64(complex64(f), verb, field)
- } else {
- p.fmtComplex128(complex128(f), verb, field)
- }
- return false
case complex64:
p.fmtComplex64(complex64(f), verb, field)
return false
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index dcc42bc92..a408c42aa 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -303,15 +303,11 @@ func (r *readRune) ReadRune() (rune int, size int, err os.Error) {
}
-// A leaky bucket of reusable ss structures.
-var ssFree = make(chan *ss, 100)
+var ssFree = newCache(func() interface{} { return new(ss) })
-// Allocate a new ss struct. Probably can grab the previous one from ssFree.
+// Allocate a new ss struct or grab a cached one.
func newScanState(r io.Reader, nlIsSpace bool) *ss {
- s, ok := <-ssFree
- if !ok {
- s = new(ss)
- }
+ s := ssFree.get().(*ss)
if rr, ok := r.(readRuner); ok {
s.rr = rr
} else {
@@ -333,7 +329,7 @@ func (s *ss) free() {
}
s.buf.Reset()
s.rr = nil
- _ = ssFree <- s
+ ssFree.put(s)
}
// skipSpace skips spaces and maybe newlines.
@@ -640,7 +636,7 @@ func (s *ss) scanComplex(verb int, n int) complex128 {
sreal, simag := s.complexTokens()
real := s.convertFloat(sreal, n/2)
imag := s.convertFloat(simag, n/2)
- return cmplx(real, imag)
+ return complex(real, imag)
}
// convertString returns the string represented by the next input characters.
@@ -772,8 +768,6 @@ func (s *ss) scanOne(verb int, field interface{}) {
switch v := field.(type) {
case *bool:
*v = s.scanBool(verb)
- case *complex:
- *v = complex(s.scanComplex(verb, int(complexBits)))
case *complex64:
*v = complex64(s.scanComplex(verb, 64))
case *complex128:
@@ -802,11 +796,6 @@ func (s *ss) scanOne(verb int, field interface{}) {
*v = uintptr(s.scanUint(verb, uintptrBits))
// Floats are tricky because you want to scan in the precision of the result, not
// scan in high precision and convert, in order to preserve the correct error condition.
- case *float:
- if s.okVerb(verb, floatVerbs, "float") {
- s.skipSpace(false)
- *v = float(s.convertFloat(s.floatToken(), int(floatBits)))
- }
case *float32:
if s.okVerb(verb, floatVerbs, "float32") {
s.skipSpace(false)
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index fe5ee1d61..78b9fbb4a 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -50,13 +50,11 @@ var (
uint16Val uint16
uint32Val uint32
uint64Val uint64
- floatVal float
float32Val float32
float64Val float64
stringVal string
stringVal1 string
bytesVal []byte
- complexVal complex
complex64Val complex64
complex128Val complex128
renamedBoolVal renamedBool
@@ -73,10 +71,8 @@ var (
renamedUintptrVal renamedUintptr
renamedStringVal renamedString
renamedBytesVal renamedBytes
- renamedFloatVal renamedFloat
renamedFloat32Val renamedFloat32
renamedFloat64Val renamedFloat64
- renamedComplexVal renamedComplex
renamedComplex64Val renamedComplex64
renamedComplex128Val renamedComplex128
)
@@ -161,12 +157,12 @@ var scanTests = []ScanTest{
{"30\n", &uint64Val, uint64(30)},
{"255\n", &uint8Val, uint8(255)},
{"32767\n", &int16Val, int16(32767)},
- {"2.3\n", &floatVal, 2.3},
+ {"2.3\n", &float64Val, 2.3},
{"2.3e1\n", &float32Val, float32(2.3e1)},
- {"2.3e2\n", &float64Val, float64(2.3e2)},
+ {"2.3e2\n", &float64Val, 2.3e2},
{"2.35\n", &stringVal, "2.35"},
{"2345678\n", &bytesVal, []byte("2345678")},
- {"(3.4e1-2i)\n", &complexVal, 3.4e1 - 2i},
+ {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i},
{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
{"hello\n", &stringVal, "hello"},
@@ -256,10 +252,8 @@ var scanfTests = []ScanfTest{
{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
{"%s", "114\n", &renamedStringVal, renamedString("114")},
{"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
- {"%g", "115.1\n", &renamedFloatVal, renamedFloat(115.1)},
{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
- {"%g", "11+5.1i\n", &renamedComplexVal, renamedComplex(11 + 5.1i)},
{"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)},
{"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)},
@@ -288,15 +282,15 @@ var overflowTests = []ScanTest{
{"65536", &uint16Val, 0},
{"1e100", &float32Val, 0},
{"1e500", &float64Val, 0},
- {"(1e100+0i)", &complexVal, 0},
+ {"(1e100+0i)", &complex64Val, 0},
{"(1+1e100i)", &complex64Val, 0},
{"(1-1e500i)", &complex128Val, 0},
}
var i, j, k int
-var f float
+var f float64
var s, t string
-var c complex
+var c complex128
var x, y Xs
var multiTests = []ScanfMultiTest{
@@ -307,7 +301,7 @@ var multiTests = []ScanfMultiTest{
{"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""},
{"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""},
{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
- {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), float(2.5)), ""},
+ {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
{"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""},
@@ -409,7 +403,7 @@ func TestScanOverflow(t *testing.T) {
}
func verifyNaN(str string, t *testing.T) {
- var f float
+ var f float64
var f32 float32
var f64 float64
text := str + " " + str + " " + str
@@ -432,7 +426,7 @@ func TestNaN(t *testing.T) {
}
func verifyInf(str string, t *testing.T) {
- var f float
+ var f float64
var f32 float32
var f64 float64
text := str + " " + str + " " + str
diff --git a/src/pkg/fmt/stringer_test.go b/src/pkg/fmt/stringer_test.go
index 815147e1a..0ca3f522d 100644
--- a/src/pkg/fmt/stringer_test.go
+++ b/src/pkg/fmt/stringer_test.go
@@ -20,7 +20,7 @@ type TU16 uint16
type TU32 uint32
type TU64 uint64
type TUI uintptr
-type TF float
+type TF float64
type TF32 float32
type TF64 float64
type TB bool
@@ -37,7 +37,7 @@ func (v TU16) String() string { return Sprintf("U16: %d", uint16(v)) }
func (v TU32) String() string { return Sprintf("U32: %d", uint32(v)) }
func (v TU64) String() string { return Sprintf("U64: %d", uint64(v)) }
func (v TUI) String() string { return Sprintf("UI: %d", uintptr(v)) }
-func (v TF) String() string { return Sprintf("F: %f", float(v)) }
+func (v TF) String() string { return Sprintf("F: %f", float64(v)) }
func (v TF32) String() string { return Sprintf("F32: %f", float32(v)) }
func (v TF64) String() string { return Sprintf("F64: %f", float64(v)) }
func (v TB) String() string { return Sprintf("B: %t", bool(v)) }