diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-07-22 18:15:38 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-07-22 18:15:38 +0000 |
commit | be239ed2ba619747b64629895116f209b58baee8 (patch) | |
tree | abdbd898676e1f853fca2d7e031d105d7ebcf676 /libgo/go/fmt | |
parent | 8f60bf3b0c426d469b5e65e1ad943e21ad42d957 (diff) | |
download | gcc-be239ed2ba619747b64629895116f209b58baee8.tar.gz |
libgo: update to go1.7rc3
Reviewed-on: https://go-review.googlesource.com/25150
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@238662 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r-- | libgo/go/fmt/doc.go | 12 | ||||
-rw-r--r-- | libgo/go/fmt/export_test.go | 2 | ||||
-rw-r--r-- | libgo/go/fmt/fmt_test.go | 781 | ||||
-rw-r--r-- | libgo/go/fmt/format.go | 593 | ||||
-rw-r--r-- | libgo/go/fmt/print.go | 852 | ||||
-rw-r--r-- | libgo/go/fmt/scan.go | 152 | ||||
-rw-r--r-- | libgo/go/fmt/scan_test.go | 127 |
7 files changed, 1330 insertions, 1189 deletions
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index 4eea48eb6b0..c312914b44a 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -62,7 +62,7 @@ For compound objects, the elements are printed using these rules, recursively, laid out like this: struct: {field0 field1 ...} - array, slice: [elem0 elem1 ...] + array, slice: [elem0 elem1 ...] maps: map[key1:value1 key2:value2] pointer to above: &{}, &[], &map[] @@ -95,10 +95,10 @@ For floating-point values, width sets the minimum width of the field and precision sets the number of places after the decimal, if appropriate, - except that for %g/%G it sets the total number of digits. For example, - given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5. - The default precision for %e and %f is 6; for %g it is the smallest - number of digits necessary to identify the value uniquely. + except that for %g/%G precision sets the total number of significant + digits. For example, given 12.345 the format %6.3f prints 12.345 while + %.3g prints 12.3. The default precision for %e and %f is 6; for %g it + is the smallest number of digits necessary to identify the value uniquely. For complex numbers, the width and precision apply to the two components independently and the result is parenthesized, so %f applied @@ -210,7 +210,7 @@ Too many arguments: %!(EXTRA type=value) Printf("hi", "guys"): hi%!(EXTRA string=guys) Too few arguments: %!verb(MISSING) - Printf("hi%d"): hi %!d(MISSING) + Printf("hi%d"): hi%!d(MISSING) Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC) Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi diff --git a/libgo/go/fmt/export_test.go b/libgo/go/fmt/export_test.go index 89d57ee6ce3..12d5a1130a4 100644 --- a/libgo/go/fmt/export_test.go +++ b/libgo/go/fmt/export_test.go @@ -1,4 +1,4 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index ea6392feb6b..b6582367673 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -48,13 +48,18 @@ func TestFmtInterface(t *testing.T) { } } -const b32 uint32 = 1<<32 - 1 -const b64 uint64 = 1<<64 - 1 +var ( + NaN = math.NaN() + posInf = math.Inf(1) + negInf = math.Inf(-1) -var array = [5]int{1, 2, 3, 4, 5} -var iarray = [4]interface{}{1, "hello", 2.5, nil} -var slice = array[:] -var islice = iarray[:] + intVar = 0 + + array = [5]int{1, 2, 3, 4, 5} + iarray = [4]interface{}{1, "hello", 2.5, nil} + slice = array[:] + islice = iarray[:] +) type A struct { i int @@ -112,9 +117,11 @@ var bslice = barray[:] type byteStringer byte -func (byteStringer) String() string { return "X" } +func (byteStringer) String() string { + return "X" +} -var byteStringerSlice = []byteStringer{97, 98, 99, 100} +var byteStringerSlice = []byteStringer{'h', 'e', 'l', 'l', 'o'} type byteFormatter byte @@ -122,9 +129,7 @@ func (byteFormatter) Format(f State, _ rune) { Fprint(f, "X") } -var byteFormatterSlice = []byteFormatter{97, 98, 99, 100} - -var b byte +var byteFormatterSlice = []byteFormatter{'h', 'e', 'l', 'l', 'o'} var fmtTests = []struct { fmt string @@ -141,6 +146,10 @@ var fmtTests = []struct { {"%x", "abc", "616263"}, {"%x", "\xff\xf0\x0f\xff", "fff00fff"}, {"%X", "\xff\xf0\x0f\xff", "FFF00FFF"}, + {"%x", "", ""}, + {"% x", "", ""}, + {"%#x", "", ""}, + {"%# x", "", ""}, {"%x", "xyz", "78797a"}, {"%X", "xyz", "78797A"}, {"% x", "xyz", "78 79 7a"}, @@ -152,10 +161,16 @@ var fmtTests = []struct { // basic bytes {"%s", []byte("abc"), "abc"}, + {"%s", [3]byte{'a', 'b', 'c'}, "abc"}, + {"%s", &[3]byte{'a', 'b', 'c'}, "&abc"}, {"%q", []byte("abc"), `"abc"`}, {"%x", []byte("abc"), "616263"}, {"%x", []byte("\xff\xf0\x0f\xff"), "fff00fff"}, {"%X", []byte("\xff\xf0\x0f\xff"), "FFF00FFF"}, + {"%x", []byte(""), ""}, + {"% x", []byte(""), ""}, + {"%#x", []byte(""), ""}, + {"%# x", []byte(""), ""}, {"%x", []byte("xyz"), "78797a"}, {"%X", []byte("xyz"), "78797A"}, {"% x", []byte("xyz"), "78 79 7a"}, @@ -166,29 +181,112 @@ var fmtTests = []struct { {"%# X", []byte("xyz"), "0X78 0X79 0X7A"}, // escaped strings - {"%#q", `abc`, "`abc`"}, - {"%#q", `"`, "`\"`"}, - {"1 %#q", `\n`, "1 `\\n`"}, - {"2 %#q", "\n", `2 "\n"`}, - {"%q", `"`, `"\""`}, - {"%q", "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`}, + {"%q", "", `""`}, + {"%#q", "", "``"}, + {"%q", "\"", `"\""`}, + {"%#q", "\"", "`\"`"}, + {"%q", "`", `"` + "`" + `"`}, + {"%#q", "`", `"` + "`" + `"`}, + {"%q", "\n", `"\n"`}, + {"%#q", "\n", `"\n"`}, + {"%q", `\n`, `"\\n"`}, + {"%#q", `\n`, "`\\n`"}, + {"%q", "abc", `"abc"`}, + {"%#q", "abc", "`abc`"}, + {"%q", "日本語", `"日本語"`}, + {"%+q", "日本語", `"\u65e5\u672c\u8a9e"`}, + {"%#q", "日本語", "`日本語`"}, + {"%#+q", "日本語", "`日本語`"}, + {"%q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`}, + {"%+q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`}, + {"%#q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`}, + {"%#+q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`}, + {"%q", "☺", `"☺"`}, + {"% q", "☺", `"☺"`}, // The space modifier should have no effect. + {"%+q", "☺", `"\u263a"`}, + {"%#q", "☺", "`☺`"}, + {"%#+q", "☺", "`☺`"}, + {"%10q", "⌘", ` "⌘"`}, + {"%+10q", "⌘", ` "\u2318"`}, + {"%-10q", "⌘", `"⌘" `}, + {"%+-10q", "⌘", `"\u2318" `}, + {"%010q", "⌘", `0000000"⌘"`}, + {"%+010q", "⌘", `00"\u2318"`}, + {"%-010q", "⌘", `"⌘" `}, // 0 has no effect when - is present. + {"%+-010q", "⌘", `"\u2318" `}, + {"%#8q", "\n", ` "\n"`}, + {"%#+8q", "\r", ` "\r"`}, + {"%#-8q", "\t", "` ` "}, + {"%#+-8q", "\b", `"\b" `}, {"%q", "abc\xffdef", `"abc\xffdef"`}, - {"%q", "\u263a", `"☺"`}, - {"%+q", "\u263a", `"\u263a"`}, + {"%+q", "abc\xffdef", `"abc\xffdef"`}, + {"%#q", "abc\xffdef", `"abc\xffdef"`}, + {"%#+q", "abc\xffdef", `"abc\xffdef"`}, + // Runes that are not printable. {"%q", "\U0010ffff", `"\U0010ffff"`}, + {"%+q", "\U0010ffff", `"\U0010ffff"`}, + {"%#q", "\U0010ffff", "``"}, + {"%#+q", "\U0010ffff", "``"}, + // Runes that are not valid. + {"%q", string(0x110000), `"�"`}, + {"%+q", string(0x110000), `"\ufffd"`}, + {"%#q", string(0x110000), "`�`"}, + {"%#+q", string(0x110000), "`�`"}, + + // characters + {"%c", uint('x'), "x"}, + {"%c", 0xe4, "ä"}, + {"%c", 0x672c, "本"}, + {"%c", '日', "日"}, + {"%.0c", '⌘', "⌘"}, // Specifying precision should have no effect. + {"%3c", '⌘', " ⌘"}, + {"%-3c", '⌘', "⌘ "}, + // Runes that are not printable. + {"%c", '\U00000e00', "\u0e00"}, + {"%c", '\U0010ffff', "\U0010ffff"}, + // Runes that are not valid. + {"%c", -1, "�"}, + {"%c", 0xDC80, "�"}, + {"%c", rune(0x110000), "�"}, + {"%c", int64(0xFFFFFFFFF), "�"}, + {"%c", uint64(0xFFFFFFFFF), "�"}, // escaped characters - {"%q", 'x', `'x'`}, - {"%q", 0, `'\x00'`}, - {"%q", '\n', `'\n'`}, - {"%q", '\u0e00', `'\u0e00'`}, // not a printable rune. - {"%q", '\U000c2345', `'\U000c2345'`}, // not a printable rune. - {"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`}, - {"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`}, + {"%q", uint(0), `'\x00'`}, + {"%+q", uint(0), `'\x00'`}, {"%q", '"', `'"'`}, + {"%+q", '"', `'"'`}, {"%q", '\'', `'\''`}, - {"%q", "\u263a", `"☺"`}, - {"%+q", "\u263a", `"\u263a"`}, + {"%+q", '\'', `'\''`}, + {"%q", '`', "'`'"}, + {"%+q", '`', "'`'"}, + {"%q", 'x', `'x'`}, + {"%+q", 'x', `'x'`}, + {"%q", 'ÿ', `'ÿ'`}, + {"%+q", 'ÿ', `'\u00ff'`}, + {"%q", '\n', `'\n'`}, + {"%+q", '\n', `'\n'`}, + {"%q", '☺', `'☺'`}, + {"%+q", '☺', `'\u263a'`}, + {"% q", '☺', `'☺'`}, // The space modifier should have no effect. + {"%.0q", '☺', `'☺'`}, // Specifying precision should have no effect. + {"%10q", '⌘', ` '⌘'`}, + {"%+10q", '⌘', ` '\u2318'`}, + {"%-10q", '⌘', `'⌘' `}, + {"%+-10q", '⌘', `'\u2318' `}, + {"%010q", '⌘', `0000000'⌘'`}, + {"%+010q", '⌘', `00'\u2318'`}, + {"%-010q", '⌘', `'⌘' `}, // 0 has no effect when - is present. + {"%+-010q", '⌘', `'\u2318' `}, + // Runes that are not printable. + {"%q", '\U00000e00', `'\u0e00'`}, + {"%q", '\U0010ffff', `'\U0010ffff'`}, + // Runes that are not valid. + {"%q", int32(-1), "%!q(int32=-1)"}, + {"%q", 0xDC80, `'�'`}, + {"%q", rune(0x110000), "%!q(int32=1114112)"}, + {"%q", int64(0xFFFFFFFFF), "%!q(int64=68719476735)"}, + {"%q", uint64(0xFFFFFFFFF), "%!q(uint64=68719476735)"}, // width {"%5s", "abc", " abc"}, @@ -199,57 +297,99 @@ var fmtTests = []struct { {"%08q", "abc", `000"abc"`}, {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}, {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"}, + {"%.0s", "日本語日本語", ""}, {"%.5s", "日本語日本語", "日本語日本"}, + {"%.10s", "日本語日本語", "日本語日本語"}, {"%.5s", []byte("日本語日本語"), "日本語日本"}, {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`}, - {"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`}, + {"%.5x", "abcdefghijklmnopqrstuvwxyz", "6162636465"}, {"%.5q", []byte("abcdefghijklmnopqrstuvwxyz"), `"abcde"`}, - {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), `6162636465`}, + {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), "6162636465"}, {"%.3q", "日本語日本語", `"日本語"`}, {"%.3q", []byte("日本語日本語"), `"日本語"`}, {"%.1q", "日本語", `"日"`}, {"%.1q", []byte("日本語"), `"日"`}, - {"%.1x", "日本語", `e6`}, - {"%.1X", []byte("日本語"), `E6`}, + {"%.1x", "日本語", "e6"}, + {"%.1X", []byte("日本語"), "E6"}, {"%10.1q", "日本語日本語", ` "日"`}, - {"%3c", '⌘', " ⌘"}, - {"%5q", '\u2026', ` '…'`}, {"%10v", nil, " <nil>"}, {"%-10v", nil, "<nil> "}, // integers - {"%d", 12345, "12345"}, - {"%d", -12345, "-12345"}, + {"%d", uint(12345), "12345"}, + {"%d", int(-12345), "-12345"}, + {"%d", ^uint8(0), "255"}, + {"%d", ^uint16(0), "65535"}, + {"%d", ^uint32(0), "4294967295"}, + {"%d", ^uint64(0), "18446744073709551615"}, + {"%d", int8(-1 << 7), "-128"}, + {"%d", int16(-1 << 15), "-32768"}, + {"%d", int32(-1 << 31), "-2147483648"}, + {"%d", int64(-1 << 63), "-9223372036854775808"}, + {"%.d", 0, ""}, + {"%.0d", 0, ""}, + {"%6.0d", 0, " "}, + {"%06.0d", 0, " "}, + {"% d", 12345, " 12345"}, + {"%+d", 12345, "+12345"}, + {"%+d", -12345, "-12345"}, + {"%b", 7, "111"}, + {"%b", -6, "-110"}, + {"%b", ^uint32(0), "11111111111111111111111111111111"}, + {"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"}, + {"%b", int64(-1 << 63), zeroFill("-1", 63, "")}, + {"%o", 01234, "1234"}, + {"%#o", 01234, "01234"}, + {"%o", ^uint32(0), "37777777777"}, + {"%o", ^uint64(0), "1777777777777777777777"}, + {"%#X", 0, "0X0"}, + {"%x", 0x12abcdef, "12abcdef"}, + {"%X", 0x12abcdef, "12ABCDEF"}, + {"%x", ^uint32(0), "ffffffff"}, + {"%X", ^uint64(0), "FFFFFFFFFFFFFFFF"}, + {"%.20b", 7, "00000000000000000111"}, {"%10d", 12345, " 12345"}, {"%10d", -12345, " -12345"}, {"%+10d", 12345, " +12345"}, {"%010d", 12345, "0000012345"}, {"%010d", -12345, "-000012345"}, - {"%-10d", 12345, "12345 "}, - {"%010.3d", 1, " 001"}, - {"%010.3d", -1, " -001"}, - {"%+d", 12345, "+12345"}, - {"%+d", -12345, "-12345"}, - {"%+d", 0, "+0"}, - {"% d", 0, " 0"}, - {"% d", 12345, " 12345"}, - {"%.0d", 0, ""}, - {"%.d", 0, ""}, + {"%20.8d", 1234, " 00001234"}, + {"%20.8d", -1234, " -00001234"}, + {"%020.8d", 1234, " 00001234"}, + {"%020.8d", -1234, " -00001234"}, + {"%-20.8d", 1234, "00001234 "}, + {"%-20.8d", -1234, "-00001234 "}, + {"%-#20.8x", 0x1234abc, "0x01234abc "}, + {"%-#20.8X", 0x1234abc, "0X01234ABC "}, + {"%-#20.8o", 01234, "00001234 "}, + + // Test correct f.intbuf overflow checks. + {"%068d", 1, zeroFill("", 68, "1")}, + {"%068d", -1, zeroFill("-", 67, "1")}, + {"%#.68x", 42, zeroFill("0x", 68, "2a")}, + {"%.68d", -42, zeroFill("-", 68, "42")}, + {"%+.68d", 42, zeroFill("+", 68, "42")}, + {"% .68d", 42, zeroFill(" ", 68, "42")}, + {"% +.68d", 42, zeroFill("+", 68, "42")}, // unicode format - {"%U", 0x1, "U+0001"}, - {"%U", uint(0x1), "U+0001"}, - {"%.8U", 0x2, "U+00000002"}, - {"%U", 0x1234, "U+1234"}, - {"%U", 0x12345, "U+12345"}, - {"%10.6U", 0xABC, " U+000ABC"}, - {"%-10.6U", 0xABC, "U+000ABC "}, + {"%U", 0, "U+0000"}, + {"%U", -1, "U+FFFFFFFFFFFFFFFF"}, {"%U", '\n', `U+000A`}, {"%#U", '\n', `U+000A`}, - {"%U", 'x', `U+0078`}, - {"%#U", 'x', `U+0078 'x'`}, + {"%+U", 'x', `U+0078`}, // Plus flag should have no effect. + {"%# U", 'x', `U+0078 'x'`}, // Space flag should have no effect. + {"%#.2U", 'x', `U+0078 'x'`}, // Precisions below 4 should print 4 digits. {"%U", '\u263a', `U+263A`}, {"%#U", '\u263a', `U+263A '☺'`}, + {"%U", '\U0001D6C2', `U+1D6C2`}, + {"%#U", '\U0001D6C2', `U+1D6C2 '𝛂'`}, + {"%#14.6U", '⌘', " U+002318 '⌘'"}, + {"%#-14.6U", '⌘', "U+002318 '⌘' "}, + {"%#014.6U", '⌘', " U+002318 '⌘'"}, + {"%#-014.6U", '⌘', "U+002318 '⌘' "}, + {"%.68U", uint(42), zeroFill("U+", 68, "2A")}, + {"%#.68U", '日', zeroFill("U+", 68, "65E5") + " '日'"}, // floats {"%+.3e", 0.0, "+0.000e+00"}, @@ -259,6 +399,12 @@ var fmtTests = []struct { {"%+.3F", float32(-1.0), "-1.000"}, {"%+07.2f", 1.0, "+001.00"}, {"%+07.2f", -1.0, "-001.00"}, + {"%-07.2f", 1.0, "1.00 "}, + {"%-07.2f", -1.0, "-1.00 "}, + {"%+-07.2f", 1.0, "+1.00 "}, + {"%+-07.2f", -1.0, "-1.00 "}, + {"%-+07.2f", 1.0, "+1.00 "}, + {"%-+07.2f", -1.0, "-1.00 "}, {"%+10.2f", +1.0, " +1.00"}, {"%+10.2f", -1.0, " -1.00"}, {"% .3E", -1.0, "-1.000E+00"}, @@ -270,8 +416,36 @@ var fmtTests = []struct { {"% .3g", 1.0, " 1"}, {"%b", float32(1.0), "8388608p-23"}, {"%b", 1.0, "4503599627370496p-52"}, + // Precision has no effect for binary float format. + {"%.4b", float32(1.0), "8388608p-23"}, + {"%.4b", -1.0, "-4503599627370496p-52"}, + // Test correct f.intbuf boundary checks. + {"%.68f", 1.0, zeroFill("1.", 68, "")}, + {"%.68f", -1.0, zeroFill("-1.", 68, "")}, + // float infinites and NaNs + {"%f", posInf, "+Inf"}, + {"%.1f", negInf, "-Inf"}, + {"% f", NaN, " NaN"}, + {"%20f", posInf, " +Inf"}, + {"% 20F", posInf, " Inf"}, + {"% 20e", negInf, " -Inf"}, + {"%+20E", negInf, " -Inf"}, + {"% +20g", negInf, " -Inf"}, + {"%+-20G", posInf, "+Inf "}, + {"%20e", NaN, " NaN"}, + {"% +20E", NaN, " +NaN"}, + {"% -20g", NaN, " NaN "}, + {"%+-20G", NaN, "+NaN "}, + // Zero padding does not apply to infinities and NaN. + {"%+020e", posInf, " +Inf"}, + {"%-020f", negInf, "-Inf "}, + {"%-020E", NaN, "NaN "}, // complex values + {"%.f", 0i, "(0+0i)"}, + {"% .f", 0i, "( 0+0i)"}, + {"%+.f", 0i, "(+0+0i)"}, + {"% +.f", 0i, "(+0+0i)"}, {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"}, {"%+.3f", 0i, "(+0.000+0.000i)"}, {"%+.3g", 0i, "(+0+0i)"}, @@ -290,35 +464,33 @@ var fmtTests = []struct { {"%.3f", -1 - 2i, "(-1.000-2.000i)"}, {"%.3g", -1 - 2i, "(-1-2i)"}, {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"}, + {"%+.3g", 1 + 2i, "(+1+2i)"}, {"%+.3g", complex64(1 + 2i), "(+1+2i)"}, - {"%+.3g", complex128(1 + 2i), "(+1+2i)"}, - {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"}, {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"}, - - // erroneous formats - {"", 2, "%!(EXTRA int=2)"}, - {"%d", "hello", "%!d(string=hello)"}, + {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"}, + // Precision has no effect for binary complex format. + {"%.4b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"}, + {"%.4b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"}, + // complex infinites and NaNs + {"%f", complex(posInf, posInf), "(+Inf+Infi)"}, + {"%f", complex(negInf, negInf), "(-Inf-Infi)"}, + {"%f", complex(NaN, NaN), "(NaN+NaNi)"}, + {"%.1f", complex(posInf, posInf), "(+Inf+Infi)"}, + {"% f", complex(posInf, posInf), "( Inf+Infi)"}, + {"% f", complex(negInf, negInf), "(-Inf-Infi)"}, + {"% f", complex(NaN, NaN), "( NaN+NaNi)"}, + {"%8e", complex(posInf, posInf), "( +Inf +Infi)"}, + {"% 8E", complex(posInf, posInf), "( Inf +Infi)"}, + {"%+8f", complex(negInf, negInf), "( -Inf -Infi)"}, + {"% +8g", complex(negInf, negInf), "( -Inf -Infi)"}, + {"% -8G", complex(NaN, NaN), "( NaN +NaN i)"}, + {"%+-8b", complex(NaN, NaN), "(+NaN +NaN i)"}, + // Zero padding does not apply to infinities and NaN. + {"%08f", complex(posInf, posInf), "( +Inf +Infi)"}, + {"%-08g", complex(negInf, negInf), "(-Inf -Inf i)"}, + {"%-08G", complex(NaN, NaN), "(NaN +NaN i)"}, // old test/fmt_test.go - {"%d", 1234, "1234"}, - {"%d", -1234, "-1234"}, - {"%d", uint(1234), "1234"}, - {"%d", uint32(b32), "4294967295"}, - {"%d", uint64(b64), "18446744073709551615"}, - {"%o", 01234, "1234"}, - {"%#o", 01234, "01234"}, - {"%o", uint32(b32), "37777777777"}, - {"%o", uint64(b64), "1777777777777777777777"}, - {"%x", 0x1234abcd, "1234abcd"}, - {"%#x", 0x1234abcd, "0x1234abcd"}, - {"%x", b32 - 0x1234567, "fedcba98"}, - {"%X", 0x1234abcd, "1234ABCD"}, - {"%X", b32 - 0x1234567, "FEDCBA98"}, - {"%#X", 0, "0X0"}, - {"%x", b64, "ffffffffffffffff"}, - {"%b", 7, "111"}, - {"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"}, - {"%b", -6, "-110"}, {"%e", 1.0, "1.000000e+00"}, {"%e", 1234.5678e3, "1.234568e+06"}, {"%e", 1234.5678e-8, "1.234568e-05"}, @@ -345,19 +517,6 @@ var fmtTests = []struct { {"%G", -7.0, "-7"}, {"%G", -1e-9, "-1E-09"}, {"%G", float32(-1e-9), "-1E-09"}, - {"%c", 'x', "x"}, - {"%c", 0xe4, "ä"}, - {"%c", 0x672c, "本"}, - {"%c", '日', "日"}, - {"%20.8d", 1234, " 00001234"}, - {"%20.8d", -1234, " -00001234"}, - {"%20d", 1234, " 1234"}, - {"%-20.8d", 1234, "00001234 "}, - {"%-20.8d", -1234, "-00001234 "}, - {"%-#20.8x", 0x1234abc, "0x01234abc "}, - {"%-#20.8X", 0x1234abc, "0X01234ABC "}, - {"%-#20.8o", 01234, "00001234 "}, - {"%.20b", 7, "00000000000000000111"}, {"%20.5s", "qwertyuiop", " qwert"}, {"%.5s", "qwertyuiop", "qwert"}, {"%-20.5s", "qwertyuiop", "qwert "}, @@ -377,9 +536,6 @@ var fmtTests = []struct { {"%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"}, // arrays {"%v", array, "[1 2 3 4 5]"}, @@ -396,13 +552,44 @@ var fmtTests = []struct { {"%v", &slice, "&[1 2 3 4 5]"}, {"%v", &islice, "&[1 hello 2.5 <nil>]"}, {"%v", &bslice, "&[1 2 3 4 5]"}, - {"%v", []byte{1}, "[1]"}, - {"%v", []byte{}, "[]"}, + + // byte arrays and slices with %b,%c,%d,%o,%U and %v + {"%b", [3]byte{65, 66, 67}, "[1000001 1000010 1000011]"}, + {"%c", [3]byte{65, 66, 67}, "[A B C]"}, + {"%d", [3]byte{65, 66, 67}, "[65 66 67]"}, + {"%o", [3]byte{65, 66, 67}, "[101 102 103]"}, + {"%U", [3]byte{65, 66, 67}, "[U+0041 U+0042 U+0043]"}, + {"%v", [3]byte{65, 66, 67}, "[65 66 67]"}, + {"%v", [1]byte{123}, "[123]"}, + {"%012v", []byte{}, "[]"}, + {"%#012v", []byte{}, "[]byte{}"}, + {"%6v", []byte{1, 11, 111}, "[ 1 11 111]"}, + {"%06v", []byte{1, 11, 111}, "[000001 000011 000111]"}, + {"%-6v", []byte{1, 11, 111}, "[1 11 111 ]"}, + {"%-06v", []byte{1, 11, 111}, "[1 11 111 ]"}, + {"%#v", []byte{1, 11, 111}, "[]byte{0x1, 0xb, 0x6f}"}, + {"%#6v", []byte{1, 11, 111}, "[]byte{ 0x1, 0xb, 0x6f}"}, + {"%#06v", []byte{1, 11, 111}, "[]byte{0x000001, 0x00000b, 0x00006f}"}, + {"%#-6v", []byte{1, 11, 111}, "[]byte{0x1 , 0xb , 0x6f }"}, + {"%#-06v", []byte{1, 11, 111}, "[]byte{0x1 , 0xb , 0x6f }"}, + // f.space should and f.plus should not have an effect with %v. + {"% v", []byte{1, 11, 111}, "[ 1 11 111]"}, + {"%+v", [3]byte{1, 11, 111}, "[1 11 111]"}, + {"%# -6v", []byte{1, 11, 111}, "[]byte{ 0x1 , 0xb , 0x6f }"}, + {"%#+-6v", [3]byte{1, 11, 111}, "[3]uint8{0x1 , 0xb , 0x6f }"}, + // f.space and f.plus should have an effect with %d. + {"% d", []byte{1, 11, 111}, "[ 1 11 111]"}, + {"%+d", [3]byte{1, 11, 111}, "[+1 +11 +111]"}, + {"%# -6d", []byte{1, 11, 111}, "[ 1 11 111 ]"}, + {"%#+-6d", [3]byte{1, 11, 111}, "[+1 +11 +111 ]"}, + + // floates with %v + {"%v", 1.2345678, "1.2345678"}, + {"%v", float32(1.2345678), "1.2345678"}, // complexes with %v {"%v", 1 + 2i, "(1+2i)"}, {"%v", complex64(1 + 2i), "(1+2i)"}, - {"%v", complex128(1 + 2i), "(1+2i)"}, // structs {"%v", A{1, 2, "a", []int{1, 2}}, `{1 2 a [1 2]}`}, @@ -422,7 +609,7 @@ var fmtTests = []struct { // go syntax {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, - {"%#v", &b, "(*uint8)(0xPTR)"}, + {"%#v", new(byte), "(*uint8)(0xPTR)"}, {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, {"%#v", make(chan int), "(chan int)(0xPTR)"}, {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, @@ -442,8 +629,20 @@ var fmtTests = []struct { {"%#v", "foo", `"foo"`}, {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, - {"%#v", []byte(nil), "[]byte(nil)"}, {"%#v", []int32(nil), "[]int32(nil)"}, + {"%#v", 1.2345678, "1.2345678"}, + {"%#v", float32(1.2345678), "1.2345678"}, + // Only print []byte and []uint8 as type []byte if they appear at the top level. + {"%#v", []byte(nil), "[]byte(nil)"}, + {"%#v", []uint8(nil), "[]byte(nil)"}, + {"%#v", []byte{}, "[]byte{}"}, + {"%#v", []uint8{}, "[]byte{}"}, + {"%#v", reflect.ValueOf([]byte{}), "[]uint8{}"}, + {"%#v", reflect.ValueOf([]uint8{}), "[]uint8{}"}, + {"%#v", &[]byte{}, "&[]uint8{}"}, + {"%#v", &[]byte{}, "&[]uint8{}"}, + {"%#v", [3]byte{}, "[3]uint8{0x0, 0x0, 0x0}"}, + {"%#v", [3]uint8{}, "[3]uint8{0x0, 0x0, 0x0}"}, // slices with other formats {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, @@ -453,30 +652,61 @@ var fmtTests = []struct { {"%q", []string{"a", "b"}, `["a" "b"]`}, {"% 02x", []byte{1}, "01"}, {"% 02x", []byte{1, 2, 3}, "01 02 03"}, + // Padding with byte slices. - {"%x", []byte{}, ""}, - {"%02x", []byte{}, "00"}, + {"%2x", []byte{}, " "}, + {"%#2x", []byte{}, " "}, {"% 02x", []byte{}, "00"}, - {"%08x", []byte{0xab}, "000000ab"}, - {"% 08x", []byte{0xab}, "000000ab"}, - {"%08x", []byte{0xab, 0xcd}, "0000abcd"}, - {"% 08x", []byte{0xab, 0xcd}, "000ab cd"}, + {"%# 02x", []byte{}, "00"}, + {"%-2x", []byte{}, " "}, + {"%-02x", []byte{}, " "}, {"%8x", []byte{0xab}, " ab"}, {"% 8x", []byte{0xab}, " ab"}, - {"%8x", []byte{0xab, 0xcd}, " abcd"}, - {"% 8x", []byte{0xab, 0xcd}, " ab cd"}, + {"%#8x", []byte{0xab}, " 0xab"}, + {"%# 8x", []byte{0xab}, " 0xab"}, + {"%08x", []byte{0xab}, "000000ab"}, + {"% 08x", []byte{0xab}, "000000ab"}, + {"%#08x", []byte{0xab}, "00000xab"}, + {"%# 08x", []byte{0xab}, "00000xab"}, + {"%10x", []byte{0xab, 0xcd}, " abcd"}, + {"% 10x", []byte{0xab, 0xcd}, " ab cd"}, + {"%#10x", []byte{0xab, 0xcd}, " 0xabcd"}, + {"%# 10x", []byte{0xab, 0xcd}, " 0xab 0xcd"}, + {"%010x", []byte{0xab, 0xcd}, "000000abcd"}, + {"% 010x", []byte{0xab, 0xcd}, "00000ab cd"}, + {"%#010x", []byte{0xab, 0xcd}, "00000xabcd"}, + {"%# 010x", []byte{0xab, 0xcd}, "00xab 0xcd"}, + {"%-10X", []byte{0xab}, "AB "}, + {"% -010X", []byte{0xab}, "AB "}, + {"%#-10X", []byte{0xab, 0xcd}, "0XABCD "}, + {"%# -010X", []byte{0xab, 0xcd}, "0XAB 0XCD "}, // Same for strings - {"%x", "", ""}, - {"%02x", "", "00"}, + {"%2x", "", " "}, + {"%#2x", "", " "}, {"% 02x", "", "00"}, - {"%08x", "\xab", "000000ab"}, - {"% 08x", "\xab", "000000ab"}, - {"%08x", "\xab\xcd", "0000abcd"}, - {"% 08x", "\xab\xcd", "000ab cd"}, + {"%# 02x", "", "00"}, + {"%-2x", "", " "}, + {"%-02x", "", " "}, {"%8x", "\xab", " ab"}, {"% 8x", "\xab", " ab"}, - {"%8x", "\xab\xcd", " abcd"}, - {"% 8x", "\xab\xcd", " ab cd"}, + {"%#8x", "\xab", " 0xab"}, + {"%# 8x", "\xab", " 0xab"}, + {"%08x", "\xab", "000000ab"}, + {"% 08x", "\xab", "000000ab"}, + {"%#08x", "\xab", "00000xab"}, + {"%# 08x", "\xab", "00000xab"}, + {"%10x", "\xab\xcd", " abcd"}, + {"% 10x", "\xab\xcd", " ab cd"}, + {"%#10x", "\xab\xcd", " 0xabcd"}, + {"%# 10x", "\xab\xcd", " 0xab 0xcd"}, + {"%010x", "\xab\xcd", "000000abcd"}, + {"% 010x", "\xab\xcd", "00000ab cd"}, + {"%#010x", "\xab\xcd", "00000xabcd"}, + {"%# 010x", "\xab\xcd", "00xab 0xcd"}, + {"%-10X", "\xab", "AB "}, + {"% -010X", "\xab", "AB "}, + {"%#-10X", "\xab\xcd", "0XABCD "}, + {"%# -010X", "\xab\xcd", "0XAB 0XCD "}, // renamings {"%v", renamedBool(true), "true"}, @@ -495,7 +725,8 @@ var fmtTests = []struct { {"%x", renamedString("thing"), "7468696e67"}, {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`}, {"%q", renamedBytes([]byte("hello")), `"hello"`}, - {"%x", []renamedUint8{'a', 'b', 'c'}, "616263"}, + {"%x", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "68656c6c6f"}, + {"%X", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "68656C6C6F"}, {"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"}, {"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`}, {"%v", renamedFloat32(22), "22"}, @@ -513,79 +744,72 @@ var fmtTests = []struct { {"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"}, // %T + {"%T", byte(0), "uint8"}, + {"%T", reflect.ValueOf(nil), "reflect.Value"}, {"%T", (4 - 3i), "complex128"}, {"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"}, - {"%T", intVal, "int"}, - {"%6T", &intVal, " *int"}, + {"%T", intVar, "int"}, + {"%6T", &intVar, " *int"}, {"%10T", nil, " <nil>"}, {"%-10T", nil, "<nil> "}, - // %p - {"p0=%p", new(int), "p0=0xPTR"}, - {"p1=%s", &pValue, "p1=String(p)"}, // String method... - {"p2=%p", &pValue, "p2=0xPTR"}, // ... not called with %p - {"p3=%p", (*int)(nil), "p3=0x0"}, - {"p4=%#p", new(int), "p4=PTR"}, - + // %p with pointers + {"%p", (*int)(nil), "0x0"}, + {"%#p", (*int)(nil), "0"}, + {"%p", &intVar, "0xPTR"}, + {"%#p", &intVar, "PTR"}, + {"%p", &array, "0xPTR"}, + {"%p", &slice, "0xPTR"}, + {"%8.2p", (*int)(nil), " 0x00"}, + {"%-20.16p", &intVar, "0xPTR "}, // %p on non-pointers {"%p", make(chan int), "0xPTR"}, {"%p", make(map[int]int), "0xPTR"}, - {"%p", make([]int, 1), "0xPTR"}, - {"%p", 27, "%!p(int=27)"}, // not a pointer at all - - // %q on pointers - {"%q", (*int)(nil), "%!q(*int=<nil>)"}, - {"%q", new(int), "%!q(*int=0xPTR)"}, - - // %v on pointers formats 0 as <nil> + {"%p", func() {}, "0xPTR"}, + {"%p", 27, "%!p(int=27)"}, // not a pointer at all + {"%p", nil, "%!p(<nil>)"}, // nil on its own has no type ... + {"%#p", nil, "%!p(<nil>)"}, // ... and hence is not a pointer type. + // pointers with specified base + {"%b", &intVar, "PTR_b"}, + {"%d", &intVar, "PTR_d"}, + {"%o", &intVar, "PTR_o"}, + {"%x", &intVar, "PTR_x"}, + {"%X", &intVar, "PTR_X"}, + // %v on pointers + {"%v", nil, "<nil>"}, + {"%#v", nil, "<nil>"}, {"%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"}, + {"%#v", (*int)(nil), "(*int)(nil)"}, + {"%v", &intVar, "0xPTR"}, + {"%#v", &intVar, "(*int)(0xPTR)"}, + {"%8.2v", (*int)(nil), " <nil>"}, + {"%-20.16v", &intVar, "0xPTR "}, + // string method on pointer + {"%s", &pValue, "String(p)"}, // String method... + {"%p", &pValue, "0xPTR"}, // ... is not called with %p. // %d on Stringer should give integer if possible {"%s", time.Time{}.Month(), "January"}, {"%d", time.Time{}.Month(), "1"}, // erroneous things + {"", nil, "%!(EXTRA <nil>)"}, + {"", 2, "%!(EXTRA int=2)"}, + {"no args", "hello", "no args%!(EXTRA string=hello)"}, {"%s %", "hello", "hello %!(NOVERB)"}, {"%s %.2", "hello", "hello %!(NOVERB)"}, - {"%d", "hello", "%!d(string=hello)"}, - {"no args", "hello", "no args%!(EXTRA string=hello)"}, - {"%s", nil, "%!s(<nil>)"}, - {"%T", nil, "<nil>"}, - {"%-1", 100, "%!(NOVERB)%!(EXTRA int=100)"}, {"%017091901790959340919092959340919017929593813360", 0, "%!(NOVERB)%!(EXTRA int=0)"}, {"%184467440737095516170v", 0, "%!(NOVERB)%!(EXTRA int=0)"}, + // Extra argument errors should format without flags set. + {"%010.2", "12345", "%!(NOVERB)%!(EXTRA string=12345)"}, // The "<nil>" show up because maps are printed by // first obtaining a list of keys and then looking up - // each key. Since NaNs can be map keys but cannot + // each key. Since NaNs can be map keys but cannot // be fetched directly, the lookup fails and returns a // zero reflect.Value, which formats as <nil>. // This test is just to check that it shows the two NaNs at all. - {"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN:<nil> NaN:<nil>]"}, - - // Used to crash because nByte didn't allow for a sign. - {"%b", int64(-1 << 63), zeroFill("-1", 63, "")}, - - // Used to panic. - {"%0100d", 1, zeroFill("", 100, "1")}, - {"%0100d", -1, zeroFill("-", 99, "1")}, - {"%0.100f", 1.0, zeroFill("1.", 100, "")}, - {"%0.100f", -1.0, zeroFill("-1.", 100, "")}, - - // Used to panic: integer function didn't look at f.prec, f.unicode, f.width or sign. - {"%#.80x", 42, "0x0000000000000000000000000000000000000000000000000000000000000000000000000000002a"}, - {"%.80U", 42, "U+0000000000000000000000000000000000000000000000000000000000000000000000000000002A"}, - {"%#.80U", '日', "U+000000000000000000000000000000000000000000000000000000000000000000000000000065E5 '日'"}, - {"%.65d", -44, "-00000000000000000000000000000000000000000000000000000000000000044"}, - {"%+.65d", 44, "+00000000000000000000000000000000000000000000000000000000000000044"}, - {"% .65d", 44, " 00000000000000000000000000000000000000000000000000000000000000044"}, - {"% +.65d", 44, "+00000000000000000000000000000000000000000000000000000000000000044"}, + {"%v", map[float64]int{NaN: 1, NaN: 2}, "map[NaN:<nil> NaN:<nil>]"}, // Comparison of padding rules with C printf. /* @@ -599,14 +823,16 @@ var fmtTests = []struct { "[%7.2f]", "[% 7.2f]", "[%+7.2f]", + "[% +7.2f]", "[%07.2f]", "[% 07.2f]", "[%+07.2f]", + "[% +07.2f]" }; int main(void) { int i; - for(i = 0; i < 9; i++) { + for(i = 0; i < 11; i++) { printf("%s: ", format[i]); printf(format[i], 1.0); printf(" "); @@ -622,9 +848,12 @@ var fmtTests = []struct { [%7.2f]: [ 1.00] [ -1.00] [% 7.2f]: [ 1.00] [ -1.00] [%+7.2f]: [ +1.00] [ -1.00] + [% +7.2f]: [ +1.00] [ -1.00] [%07.2f]: [0001.00] [-001.00] [% 07.2f]: [ 001.00] [-001.00] [%+07.2f]: [+001.00] [-001.00] + [% +07.2f]: [+001.00] [-001.00] + */ {"%.2f", 1.0, "1.00"}, {"%.2f", -1.0, "-1.00"}, @@ -638,26 +867,35 @@ var fmtTests = []struct { {"% 7.2f", -1.0, " -1.00"}, {"%+7.2f", 1.0, " +1.00"}, {"%+7.2f", -1.0, " -1.00"}, + {"% +7.2f", 1.0, " +1.00"}, + {"% +7.2f", -1.0, " -1.00"}, {"%07.2f", 1.0, "0001.00"}, {"%07.2f", -1.0, "-001.00"}, {"% 07.2f", 1.0, " 001.00"}, {"% 07.2f", -1.0, "-001.00"}, {"%+07.2f", 1.0, "+001.00"}, {"%+07.2f", -1.0, "-001.00"}, + {"% +07.2f", 1.0, "+001.00"}, + {"% +07.2f", -1.0, "-001.00"}, // Complex numbers: exhaustively tested in TestComplexFormatting. {"%7.2f", 1 + 2i, "( 1.00 +2.00i)"}, {"%+07.2f", -1 - 2i, "(-001.00-002.00i)"}, - // Zero padding does not apply to infinities. - {"%020f", math.Inf(-1), " -Inf"}, - {"%020f", math.Inf(+1), " +Inf"}, - {"% 020f", math.Inf(-1), " -Inf"}, - {"% 020f", math.Inf(+1), " Inf"}, - {"%+020f", math.Inf(-1), " -Inf"}, - {"%+020f", math.Inf(+1), " +Inf"}, - {"%20f", -1.0, " -1.000000"}, - // Make sure we can handle very large widths. - {"%0100f", -1.0, zeroFill("-", 99, "1.000000")}, + + // Use spaces instead of zero if padding to the right. + {"%0-5s", "abc", "abc "}, + {"%-05.1f", 1.0, "1.0 "}, + + // float and complex formatting should not change the padding width + // for other elements. See issue 14642. + {"%06v", []interface{}{+10.0, 10}, "[000010 000010]"}, + {"%06v", []interface{}{-10.0, 10}, "[-00010 000010]"}, + {"%06v", []interface{}{+10.0 + 10i, 10}, "[(000010+00010i) 000010]"}, + {"%06v", []interface{}{-10.0 + 10i, 10}, "[(-00010+00010i) 000010]"}, + + // integer formatting should not alter padding for other elements. + {"%03.6v", []interface{}{1, 2.0, "x"}, "[000001 002 00x]"}, + {"%03.0v", []interface{}{0, 2.0, "x"}, "[ 002 000]"}, // Complex fmt used to leave the plus flag set for future entries in the array // causing +2+0i and +3+0i instead of 2+0i and 3+0i. @@ -667,27 +905,6 @@ var fmtTests = []struct { // Incomplete format specification caused crash. {"%.", 3, "%!.(int=3)"}, - // Used to panic with out-of-bounds for very large numeric representations. - // nByte is set to handle one bit per uint64 in %b format, with a negative number. - // See issue 6777. - {"%#064x", 1, zeroFill("0x", 64, "1")}, - {"%#064x", -1, zeroFill("-0x", 63, "1")}, - {"%#064b", 1, zeroFill("", 64, "1")}, - {"%#064b", -1, zeroFill("-", 63, "1")}, - {"%#064o", 1, zeroFill("", 64, "1")}, - {"%#064o", -1, zeroFill("-", 63, "1")}, - {"%#064d", 1, zeroFill("", 64, "1")}, - {"%#064d", -1, zeroFill("-", 63, "1")}, - // Test that we handle the crossover above the size of uint64 - {"%#072x", 1, zeroFill("0x", 72, "1")}, - {"%#072x", -1, zeroFill("-0x", 71, "1")}, - {"%#072b", 1, zeroFill("", 72, "1")}, - {"%#072b", -1, zeroFill("-", 71, "1")}, - {"%#072o", 1, zeroFill("", 72, "1")}, - {"%#072o", -1, zeroFill("-", 71, "1")}, - {"%#072d", 1, zeroFill("", 72, "1")}, - {"%#072d", -1, zeroFill("-", 71, "1")}, - // Padding for complex numbers. Has been bad, then fixed, then bad again. {"%+10.2f", +104.66 + 440.51i, "( +104.66 +440.51i)"}, {"%+10.2f", -104.66 + 440.51i, "( -104.66 +440.51i)"}, @@ -699,19 +916,21 @@ var fmtTests = []struct { {"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"}, // []T where type T is a byte with a Stringer method. - {"%v", byteStringerSlice, "[X X X X]"}, - {"%s", byteStringerSlice, "abcd"}, - {"%q", byteStringerSlice, "\"abcd\""}, - {"%x", byteStringerSlice, "61626364"}, - {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x61, 0x62, 0x63, 0x64}"}, + {"%v", byteStringerSlice, "[X X X X X]"}, + {"%s", byteStringerSlice, "hello"}, + {"%q", byteStringerSlice, "\"hello\""}, + {"%x", byteStringerSlice, "68656c6c6f"}, + {"%X", byteStringerSlice, "68656C6C6F"}, + {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x68, 0x65, 0x6c, 0x6c, 0x6f}"}, // And the same for Formatter. - {"%v", byteFormatterSlice, "[X X X X]"}, - {"%s", byteFormatterSlice, "abcd"}, - {"%q", byteFormatterSlice, "\"abcd\""}, - {"%x", byteFormatterSlice, "61626364"}, + {"%v", byteFormatterSlice, "[X X X X X]"}, + {"%s", byteFormatterSlice, "hello"}, + {"%q", byteFormatterSlice, "\"hello\""}, + {"%x", byteFormatterSlice, "68656c6c6f"}, + {"%X", byteFormatterSlice, "68656C6C6F"}, // This next case seems wrong, but the docs say the Formatter wins here. - {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X}"}, + {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X, X}"}, // reflect.Value handled specially in Go 1.5, making it possible to // see inside non-exported fields (which cannot be accessed with Interface()). @@ -726,6 +945,32 @@ var fmtTests = []struct { // invalid reflect.Value doesn't crash. {"%v", reflect.Value{}, "<invalid reflect.Value>"}, + {"%v", &reflect.Value{}, "<invalid Value>"}, + {"%v", SI{reflect.Value{}}, "{<invalid Value>}"}, + + // Tests to check that not supported verbs generate an error string. + {"%☠", nil, "%!☠(<nil>)"}, + {"%☠", interface{}(nil), "%!☠(<nil>)"}, + {"%☠", int(0), "%!☠(int=0)"}, + {"%☠", uint(0), "%!☠(uint=0)"}, + {"%☠", []byte{0, 1}, "[%!☠(uint8=0) %!☠(uint8=1)]"}, + {"%☠", []uint8{0, 1}, "[%!☠(uint8=0) %!☠(uint8=1)]"}, + {"%☠", [1]byte{0}, "[%!☠(uint8=0)]"}, + {"%☠", [1]uint8{0}, "[%!☠(uint8=0)]"}, + {"%☠", "hello", "%!☠(string=hello)"}, + {"%☠", 1.2345678, "%!☠(float64=1.2345678)"}, + {"%☠", float32(1.2345678), "%!☠(float32=1.2345678)"}, + {"%☠", 1.2345678 + 1.2345678i, "%!☠(complex128=(1.2345678+1.2345678i))"}, + {"%☠", complex64(1.2345678 + 1.2345678i), "%!☠(complex64=(1.2345678+1.2345678i))"}, + {"%☠", &intVar, "%!☠(*int=0xPTR)"}, + {"%☠", make(chan int), "%!☠(chan int=0xPTR)"}, + {"%☠", func() {}, "%!☠(func()=0xPTR)"}, + {"%☠", reflect.ValueOf(renamedInt(0)), "%!☠(fmt_test.renamedInt=0)"}, + {"%☠", SI{renamedInt(0)}, "{%!☠(fmt_test.renamedInt=0)}"}, + {"%☠", &[]interface{}{I(1), G(2)}, "&[%!☠(fmt_test.I=1) %!☠(fmt_test.G=2)]"}, + {"%☠", SI{&[]interface{}{I(1), G(2)}}, "{%!☠(*[]interface {}=&[1 2])}"}, + {"%☠", reflect.Value{}, "<invalid reflect.Value>"}, + {"%☠", map[float64]int{NaN: 1}, "map[%!☠(float64=NaN):%!☠(<nil>)]"}, } // zeroFill generates zero-filled strings of the specified width. The length @@ -737,27 +982,37 @@ func zeroFill(prefix string, width int, suffix string) string { 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" + i := strings.Index(tt.out, "PTR") + if i >= 0 && i < len(s) { + var pattern, chars string switch { - case strings.HasPrefix(tt.out[i:], "PTR_d"): - pattern = "PTR_d" - chars = chars[:10] + case strings.HasPrefix(tt.out[i:], "PTR_b"): + pattern = "PTR_b" + chars = "01" case strings.HasPrefix(tt.out[i:], "PTR_o"): pattern = "PTR_o" - chars = chars[:8] + chars = "01234567" + case strings.HasPrefix(tt.out[i:], "PTR_d"): + pattern = "PTR_d" + chars = "0123456789" case strings.HasPrefix(tt.out[i:], "PTR_x"): pattern = "PTR_x" + chars = "0123456789abcdef" + case strings.HasPrefix(tt.out[i:], "PTR_X"): + pattern = "PTR_X" + chars = "0123456789ABCDEF" + default: + pattern = "PTR" + chars = "0123456789abcdefABCDEF" } - j := i - for ; j < len(s); j++ { - c := s[j] - if !strings.ContainsRune(chars, rune(c)) { + p := s[:i] + pattern + for j := i; j < len(s); j++ { + if !strings.ContainsRune(chars, rune(s[j])) { + p += s[j:] break } } - s = s[0:i] + pattern + s[j:] + s = p } if s != tt.out { if _, ok := tt.val.(string); ok { @@ -775,7 +1030,7 @@ func TestSprintf(t *testing.T) { // thing as if done by hand with two singleton prints. func TestComplexFormatting(t *testing.T) { var yesNo = []bool{true, false} - var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()} + var values = []float64{1, 0, -1, posInf, negInf, NaN} for _, plus := range yesNo { for _, zero := range yesNo { for _, space := range yesNo { @@ -869,6 +1124,14 @@ func TestReorder(t *testing.T) { } } +func BenchmarkSprintfPadding(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%16f", 1.0) + } + }) +} + func BenchmarkSprintfEmpty(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { @@ -885,6 +1148,22 @@ func BenchmarkSprintfString(b *testing.B) { }) } +func BenchmarkSprintfTruncateString(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%.3s", "日本語日本語日本語") + } + }) +} + +func BenchmarkSprintfQuoteString(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%q", "日本語日本語日本語") + } + }) +} + func BenchmarkSprintfInt(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { @@ -917,6 +1196,66 @@ func BenchmarkSprintfFloat(b *testing.B) { }) } +func BenchmarkSprintfComplex(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%f", 5.23184+5.23184i) + } + }) +} + +func BenchmarkSprintfBoolean(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%t", true) + } + }) +} + +func BenchmarkSprintfHexString(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("% #x", "0123456789abcdef") + } + }) +} + +func BenchmarkSprintfHexBytes(b *testing.B) { + data := []byte("0123456789abcdef") + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("% #x", data) + } + }) +} + +func BenchmarkSprintfBytes(b *testing.B) { + data := []byte("0123456789abcdef") + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%v", data) + } + }) +} + +func BenchmarkSprintfStringer(b *testing.B) { + stringer := I(12345) + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%v", stringer) + } + }) +} + +func BenchmarkSprintfStructure(b *testing.B) { + s := &[]interface{}{SI{12345}, map[int]string{0: "hello"}} + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%#v", s) + } + }) +} + func BenchmarkManyArgs(b *testing.B) { b.RunParallel(func(pb *testing.PB) { var buf bytes.Buffer diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index 517b18f7d43..023647501a0 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -5,18 +5,13 @@ package fmt import ( - "math" "strconv" "unicode/utf8" ) const ( - // %b of an int64, plus a sign. - // Hex can add 0x and we handle it specially. - nByte = 65 - - ldigits = "0123456789abcdef" - udigits = "0123456789ABCDEF" + ldigits = "0123456789abcdefx" + udigits = "0123456789ABCDEFX" ) const ( @@ -24,16 +19,6 @@ const ( unsigned = false ) -var padZeroBytes = make([]byte, nByte) -var padSpaceBytes = make([]byte, nByte) - -func init() { - for i := 0; i < nByte; i++ { - padZeroBytes[i] = '0' - padSpaceBytes[i] = ' ' - } -} - // flags placed in a separate struct for easy clearing. type fmtFlags struct { widPresent bool @@ -42,8 +27,6 @@ type fmtFlags struct { plus bool sharp bool space bool - unicode bool - uniQuote bool // Use 'x'= prefix for %U if printable. zero bool // For the formats %+v %#v, we set the plusV/sharpV flags @@ -56,12 +39,16 @@ type fmtFlags struct { // A fmt is the raw formatter used by Printf etc. // It prints into a buffer that must be set up separately. type fmt struct { - intbuf [nByte]byte - buf *buffer - // width, precision - wid int - prec int + buf *buffer + fmtFlags + + wid int // width + prec int // precision + + // intbuf is large enought to store %b of an int64 with a sign and + // avoids padding at the end of the struct on 32 bit architectures. + intbuf [68]byte } func (f *fmt) clearflags() { @@ -73,176 +60,213 @@ func (f *fmt) init(buf *buffer) { f.clearflags() } -// computePadding computes left and right padding widths (only one will be non-zero). -func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) { - left := !f.minus - w := f.wid - if w < 0 { - left = false - w = -w - } - w -= width - if w > 0 { - if left && f.zero { - return padZeroBytes, w, 0 - } - if left { - return padSpaceBytes, w, 0 - } else { - // can't be zero padding on the right - return padSpaceBytes, 0, w - } - } - return -} - // writePadding generates n bytes of padding. -func (f *fmt) writePadding(n int, padding []byte) { - for n > 0 { - m := n - if m > nByte { - m = nByte - } - f.buf.Write(padding[0:m]) - n -= m +func (f *fmt) writePadding(n int) { + if n <= 0 { // No padding bytes needed. + return } + buf := *f.buf + oldLen := len(buf) + newLen := oldLen + n + // Make enough room for padding. + if newLen > cap(buf) { + buf = make(buffer, cap(buf)*2+n) + copy(buf, *f.buf) + } + // Decide which byte the padding should be filled with. + padByte := byte(' ') + if f.zero { + padByte = byte('0') + } + // Fill padding with padByte. + padding := buf[oldLen:newLen] + for i := range padding { + padding[i] = padByte + } + *f.buf = buf[:newLen] } -// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus). +// pad appends b to f.buf, padded on left (!f.minus) or right (f.minus). func (f *fmt) pad(b []byte) { if !f.widPresent || f.wid == 0 { f.buf.Write(b) return } - padding, left, right := f.computePadding(utf8.RuneCount(b)) - if left > 0 { - f.writePadding(left, padding) - } - f.buf.Write(b) - if right > 0 { - f.writePadding(right, padding) + width := f.wid - utf8.RuneCount(b) + if !f.minus { + // left padding + f.writePadding(width) + f.buf.Write(b) + } else { + // right padding + f.buf.Write(b) + f.writePadding(width) } } -// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus). +// padString appends s to f.buf, padded on left (!f.minus) or right (f.minus). func (f *fmt) padString(s string) { 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) - } - f.buf.WriteString(s) - if right > 0 { - f.writePadding(right, padding) + width := f.wid - utf8.RuneCountInString(s) + if !f.minus { + // left padding + f.writePadding(width) + f.buf.WriteString(s) + } else { + // right padding + f.buf.WriteString(s) + f.writePadding(width) } } -var ( - trueBytes = []byte("true") - falseBytes = []byte("false") -) - // fmt_boolean formats a boolean. func (f *fmt) fmt_boolean(v bool) { if v { - f.pad(trueBytes) + f.padString("true") } else { - f.pad(falseBytes) + f.padString("false") } } -// integer; interprets prec but not wid. Once formatted, result is sent to pad() -// and then flags are cleared. -func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { - // precision of 0 and value of 0 means "print nothing" - if f.precPresent && f.prec == 0 && a == 0 { - return +// fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'". +func (f *fmt) fmt_unicode(u uint64) { + buf := f.intbuf[0:] + + // With default precision set the maximum needed buf length is 18 + // for formatting -1 with %#U ("U+FFFFFFFFFFFFFFFF") which fits + // into the already allocated intbuf with a capacity of 68 bytes. + prec := 4 + if f.precPresent && f.prec > 4 { + prec = f.prec + // Compute space needed for "U+" , number, " '", character, "'". + width := 2 + prec + 2 + utf8.UTFMax + 1 + if width > len(buf) { + buf = make([]byte, width) + } } - negative := signedness == signed && a < 0 + // Format into buf, ending at buf[i]. Formatting numbers is easier right-to-left. + i := len(buf) + + // For %#U we want to add a space and a quoted character at the end of the buffer. + if f.sharp && u <= utf8.MaxRune && strconv.IsPrint(rune(u)) { + i-- + buf[i] = '\'' + i -= utf8.RuneLen(rune(u)) + utf8.EncodeRune(buf[i:], rune(u)) + i-- + buf[i] = '\'' + i-- + buf[i] = ' ' + } + // Format the Unicode code point u as a hexadecimal number. + for u >= 16 { + i-- + buf[i] = udigits[u&0xF] + prec-- + u >>= 4 + } + i-- + buf[i] = udigits[u] + prec-- + // Add zeros in front of the number until requested precision is reached. + for prec > 0 { + i-- + buf[i] = '0' + prec-- + } + // Add a leading "U+". + i-- + buf[i] = '+' + i-- + buf[i] = 'U' + + oldZero := f.zero + f.zero = false + f.pad(buf[i:]) + f.zero = oldZero +} + +// fmt_integer formats signed and unsigned integers. +func (f *fmt) fmt_integer(u uint64, base int, isSigned bool, digits string) { + negative := isSigned && int64(u) < 0 if negative { - a = -a + u = -u } - var buf []byte = f.intbuf[0:] - if f.widPresent || f.precPresent || f.plus || f.space { - width := f.wid + f.prec // Only one will be set, both are positive; this provides the maximum. - if base == 16 && f.sharp { - // Also adds "0x". - width += 2 - } - if f.unicode { - // Also adds "U+". - width += 2 - if f.uniQuote { - // Also adds " 'x'". - width += 1 + 1 + utf8.UTFMax + 1 - } - } - if negative || f.plus || f.space { - width++ - } - if width > nByte { + buf := f.intbuf[0:] + // The already allocated f.intbuf with a capacity of 68 bytes + // is large enough for integer formatting when no precision or width is set. + if f.widPresent || f.precPresent { + // Account 3 extra bytes for possible addition of a sign and "0x". + width := 3 + f.wid + f.prec // wid and prec are always positive. + if width > len(buf) { // We're going to need a bigger boat. buf = make([]byte, width) } } - // two ways to ask for extra leading zero digits: %.3d or %03d. - // apparently the first cancels the second. + // Two ways to ask for extra leading zero digits: %.3d or %03d. + // If both are specified the f.zero flag is ignored and + // padding with spaces is used instead. prec := 0 if f.precPresent { prec = f.prec - f.zero = false - } else if f.zero && f.widPresent && !f.minus && f.wid > 0 { + // Precision of 0 and value of 0 means "print nothing" but padding. + if prec == 0 && u == 0 { + oldZero := f.zero + f.zero = false + f.writePadding(f.wid) + f.zero = oldZero + return + } + } else if f.zero && f.widPresent { prec = f.wid if negative || f.plus || f.space { prec-- // leave room for sign } } - // format a into buf, ending at buf[i]. (printing is easier right-to-left.) - // a is made into unsigned ua. we could make things - // marginally faster by splitting the 32-bit case out into a separate - // block but it's not worth the duplication, so ua has 64 bits. + // Because printing is easier right-to-left: format u into buf, ending at buf[i]. + // We could make things marginally faster by splitting the 32-bit case out + // into a separate block but it's not worth the duplication, so u has 64 bits. i := len(buf) - ua := uint64(a) - // use constants for the division and modulo for more efficient code. - // switch cases ordered by popularity. + // Use constants for the division and modulo for more efficient code. + // Switch cases ordered by popularity. switch base { case 10: - for ua >= 10 { + for u >= 10 { i-- - next := ua / 10 - buf[i] = byte('0' + ua - next*10) - ua = next + next := u / 10 + buf[i] = byte('0' + u - next*10) + u = next } case 16: - for ua >= 16 { + for u >= 16 { i-- - buf[i] = digits[ua&0xF] - ua >>= 4 + buf[i] = digits[u&0xF] + u >>= 4 } case 8: - for ua >= 8 { + for u >= 8 { i-- - buf[i] = byte('0' + ua&7) - ua >>= 3 + buf[i] = byte('0' + u&7) + u >>= 3 } case 2: - for ua >= 2 { + for u >= 2 { i-- - buf[i] = byte('0' + ua&1) - ua >>= 1 + buf[i] = byte('0' + u&1) + u >>= 1 } default: panic("fmt: unknown base; can't happen") } i-- - buf[i] = digits[ua] + buf[i] = digits[u] for i > 0 && prec > len(buf)-i { i-- buf[i] = '0' @@ -257,18 +281,13 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { buf[i] = '0' } case 16: + // Add a leading 0x or 0X. i-- - buf[i] = 'x' + digits[10] - 'a' + buf[i] = digits[16] i-- buf[i] = '0' } } - if f.unicode { - i-- - buf[i] = '+' - i-- - buf[i] = 'U' - } if negative { i-- @@ -281,36 +300,23 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { buf[i] = ' ' } - // If we want a quoted char for %#U, move the data up to make room. - if f.unicode && f.uniQuote && a >= 0 && a <= utf8.MaxRune && strconv.IsPrint(rune(a)) { - runeWidth := utf8.RuneLen(rune(a)) - width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote - copy(buf[i-width:], buf[i:]) // guaranteed to have enough room. - i -= width - // Now put " 'x'" at the end. - j := len(buf) - width - buf[j] = ' ' - j++ - buf[j] = '\'' - j++ - utf8.EncodeRune(buf[j:], rune(a)) - j += runeWidth - buf[j] = '\'' - } - + // Left padding with zeros has already been handled like precision earlier + // or the f.zero flag is ignored due to an explicitly set precision. + oldZero := f.zero + f.zero = false f.pad(buf[i:]) + f.zero = oldZero } // truncate truncates the string to the specified precision, if present. func (f *fmt) truncate(s string) string { - if f.precPresent && f.prec < utf8.RuneCountInString(s) { + if f.precPresent { n := f.prec for i := range s { - if n == 0 { - s = s[:i] - break - } n-- + if n < 0 { + return s[:i] + } } } return s @@ -324,212 +330,169 @@ func (f *fmt) fmt_s(s 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) + length := len(b) if b == nil { - n = len(s) + // No byte slice present. Assume string s should be encoded. + length = len(s) + } + // Set length to not process more bytes than the precision demands. + if f.precPresent && f.prec < length { + length = f.prec + } + // Compute width of the encoding taking into account the f.sharp and f.space flag. + width := 2 * length + if width > 0 { + if f.space { + // Each element encoded by two hexadecimals will get a leading 0x or 0X. + if f.sharp { + width *= 2 + } + // Elements will be separated by a space. + width += length - 1 + } else if f.sharp { + // Only a leading 0x or 0X will be added for the whole string. + width += 2 + } + } else { // The byte slice or string that should be encoded is empty. + if f.widPresent { + f.writePadding(f.wid) + } + return + } + // Handle padding to the left. + if f.widPresent && f.wid > width && !f.minus { + f.writePadding(f.wid - width) } - x := digits[10] - 'a' + 'x' - // TODO: Avoid buffer by pre-padding. - var buf []byte - for i := 0; i < n; i++ { - if i > 0 && f.space { + // Write the encoding directly into the output buffer. + buf := *f.buf + if f.sharp { + // Add leading 0x or 0X. + buf = append(buf, '0', digits[16]) + } + var c byte + for i := 0; i < length; i++ { + if f.space && i > 0 { + // Separate elements with a space. buf = append(buf, ' ') + if f.sharp { + // Add leading 0x or 0X for each element. + buf = append(buf, '0', digits[16]) + } } - if f.sharp && (f.space || i == 0) { - buf = append(buf, '0', x) - } - var c byte - if b == nil { - c = s[i] + if b != nil { + c = b[i] // Take a byte from the input byte slice. } else { - c = b[i] + c = s[i] // Take a byte from the input string. } + // Encode each byte as two hexadecimal digits. buf = append(buf, digits[c>>4], digits[c&0xF]) } - f.pad(buf) + *f.buf = buf + // Handle padding to the right. + if f.widPresent && f.wid > width && f.minus { + f.writePadding(f.wid - width) + } } // fmt_sx formats a string as a hexadecimal encoding of its bytes. func (f *fmt) fmt_sx(s, digits string) { - if f.precPresent && f.prec < len(s) { - s = s[:f.prec] - } 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) { - if f.precPresent && f.prec < len(b) { - b = b[:f.prec] - } f.fmt_sbx("", b, digits) } // fmt_q formats a string as a double-quoted, escaped Go string constant. +// If f.sharp is set a raw (backquoted) string may be returned instead +// if the string does not contain any control characters other than tab. func (f *fmt) fmt_q(s string) { s = f.truncate(s) - var quoted string if f.sharp && strconv.CanBackquote(s) { - quoted = "`" + s + "`" + f.padString("`" + s + "`") + return + } + buf := f.intbuf[:0] + if f.plus { + f.pad(strconv.AppendQuoteToASCII(buf, s)) } else { - if f.plus { - quoted = strconv.QuoteToASCII(s) - } else { - quoted = strconv.Quote(s) - } + f.pad(strconv.AppendQuote(buf, s)) } - f.padString(quoted) } -// fmt_qc formats the integer as a single-quoted, escaped Go character constant. +// fmt_c formats an integer as a Unicode character. // If the character is not valid Unicode, it will print '\ufffd'. -func (f *fmt) fmt_qc(c int64) { - var quoted []byte +func (f *fmt) fmt_c(c uint64) { + r := rune(c) + if c > utf8.MaxRune { + r = utf8.RuneError + } + buf := f.intbuf[:0] + w := utf8.EncodeRune(buf[:utf8.UTFMax], r) + f.pad(buf[:w]) +} + +// fmt_qc formats an integer as a single-quoted, escaped Go character constant. +// If the character is not valid Unicode, it will print '\ufffd'. +func (f *fmt) fmt_qc(c uint64) { + r := rune(c) + if c > utf8.MaxRune { + r = utf8.RuneError + } + buf := f.intbuf[:0] if f.plus { - quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c)) + f.pad(strconv.AppendQuoteRuneToASCII(buf, r)) } else { - quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c)) + f.pad(strconv.AppendQuoteRune(buf, r)) } - f.pad(quoted) } -// floating-point - -func doPrec(f *fmt, def int) int { +// fmt_float formats a float64. It assumes that verb is a valid format specifier +// for strconv.AppendFloat and therefore fits into a byte. +func (f *fmt) fmt_float(v float64, size int, verb rune, prec int) { + // Explicit precision in format specifier overrules default precision. if f.precPresent { - return f.prec + prec = f.prec } - return def -} - -// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...). -func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { // Format number, reserving space for leading + sign if needed. - num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) + num := strconv.AppendFloat(f.intbuf[:1], v, byte(verb), prec, size) if num[1] == '-' || num[1] == '+' { num = num[1:] } else { num[0] = '+' } - // Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros. - if math.IsInf(v, 0) { - if f.zero { - defer func() { f.zero = true }() - f.zero = false - } + // f.space means to add a leading space instead of a "+" sign unless + // the sign is explicitly asked for by f.plus. + if f.space && num[0] == '+' && !f.plus { + num[0] = ' ' } - // num is now a signed version of the number. - // If we're zero padding, want the sign before the leading zeros. - // Achieve this by writing the sign out and then padding the unsigned number. - if f.zero && f.widPresent && f.wid > len(num) { - if f.space && v >= 0 { - f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space. - f.wid-- - } else if f.plus || v < 0 { - f.buf.WriteByte(num[0]) - f.wid-- + // Special handling for infinities and NaN, + // which don't look like a number so shouldn't be padded with zeros. + if num[1] == 'I' || num[1] == 'N' { + oldZero := f.zero + f.zero = false + // Remove sign before NaN if not asked for. + if num[1] == 'N' && !f.space && !f.plus { + num = num[1:] } - f.pad(num[1:]) - return - } - // f.space says to replace a leading + with a space. - if f.space && num[0] == '+' { - num[0] = ' ' f.pad(num) + f.zero = oldZero return } - // Now we know the sign is attached directly to the number, if present at all. - // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf). - if f.plus || num[0] == '-' || math.IsInf(v, 0) { + // We want a sign if asked for and if the sign is not positive. + if f.plus || num[0] != '+' { + // If we're zero padding to the left we want the sign before the leading zeros. + // Achieve this by writing the sign out and then padding the unsigned number. + if f.zero && f.widPresent && f.wid > len(num) { + f.buf.WriteByte(num[0]) + f.writePadding(f.wid - len(num)) + f.buf.Write(num[1:]) + return + } f.pad(num) return } // No sign to show and the number is positive; just print the unsigned number. f.pad(num[1:]) } - -// fmt_e64 formats a float64 in the form -1.23e+12. -func (f *fmt) fmt_e64(v float64) { f.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.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.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.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.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.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.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.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.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.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.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.formatFloat(float64(v), 'b', 0, 32) } - -// fmt_c64 formats a complex64 according to the verb. -func (f *fmt) fmt_c64(v complex64, verb rune) { - f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb) -} - -// fmt_c128 formats a complex128 according to the verb. -func (f *fmt) fmt_c128(v complex128, verb rune) { - f.fmt_complex(real(v), imag(v), 64, verb) -} - -// fmt_complex formats a complex number as (r+ji). -func (f *fmt) fmt_complex(r, j float64, size int, verb rune) { - f.buf.WriteByte('(') - oldPlus := f.plus - oldSpace := f.space - oldWid := f.wid - for i := 0; ; i++ { - switch verb { - case 'b': - f.formatFloat(r, 'b', 0, size) - case 'e': - f.formatFloat(r, 'e', doPrec(f, 6), size) - case 'E': - f.formatFloat(r, 'E', doPrec(f, 6), size) - case 'f', 'F': - f.formatFloat(r, 'f', doPrec(f, 6), size) - case 'g': - f.formatFloat(r, 'g', doPrec(f, -1), size) - case 'G': - f.formatFloat(r, 'G', doPrec(f, -1), size) - } - if i != 0 { - break - } - // Imaginary part always has a sign. - f.plus = true - f.space = false - f.wid = oldWid - r = j - } - f.space = oldSpace - f.plus = oldPlus - f.wid = oldWid - f.buf.Write(irparenBytes) -} diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index ebfa13e4d37..f8c731656e5 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -13,24 +13,23 @@ import ( "unicode/utf8" ) -// Some constants in the form of bytes, to avoid string overhead. -// Needlessly fastidious, I suppose. -var ( - commaSpaceBytes = []byte(", ") - nilAngleBytes = []byte("<nil>") - nilParenBytes = []byte("(nil)") - nilBytes = []byte("nil") - mapBytes = []byte("map[") - percentBangBytes = []byte("%!") - missingBytes = []byte("(MISSING)") - badIndexBytes = []byte("(BADINDEX)") - panicBytes = []byte("(PANIC=") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - badWidthBytes = []byte("%!(BADWIDTH)") - badPrecBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") +// Strings for use with buffer.WriteString. +// This is less overhead than using buffer.Write with byte arrays. +const ( + commaSpaceString = ", " + nilAngleString = "<nil>" + nilParenString = "(nil)" + nilString = "nil" + mapString = "map[" + percentBangString = "%!" + missingString = "(MISSING)" + badIndexString = "(BADINDEX)" + panicString = "(PANIC=" + extraString = "%!(EXTRA " + badWidthString = "%!(BADWIDTH)" + badPrecString = "%!(BADPREC)" + noVerbString = "%!(NOVERB)" + invReflectString = "<invalid reflect.Value>" ) // State represents the printer state passed to custom formatters. @@ -38,7 +37,7 @@ var ( // the flags and options for the operand's format specifier. type State interface { // Write is the function to call to emit formatted output to be printed. - Write(b []byte) (ret int, err error) + Write(b []byte) (n int, err error) // Width returns the value of the width option and whether it has been set. Width() (wid int, ok bool) // Precision returns the value of the precision option and whether it has been set. @@ -75,25 +74,22 @@ type GoStringer interface { // Use simple []byte instead of bytes.Buffer to avoid large dependency. type buffer []byte -func (b *buffer) Write(p []byte) (n int, err error) { +func (b *buffer) Write(p []byte) { *b = append(*b, p...) - return len(p), nil } -func (b *buffer) WriteString(s string) (n int, err error) { +func (b *buffer) WriteString(s string) { *b = append(*b, s...) - return len(s), nil } -func (b *buffer) WriteByte(c byte) error { +func (b *buffer) WriteByte(c byte) { *b = append(*b, c) - return nil } -func (bp *buffer) WriteRune(r rune) error { +func (bp *buffer) WriteRune(r rune) { if r < utf8.RuneSelf { *bp = append(*bp, byte(r)) - return nil + return } b := *bp @@ -103,25 +99,29 @@ func (bp *buffer) WriteRune(r rune) error { } w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r) *bp = b[:n+w] - return nil } +// pp is used to store a printer's state and is reused with sync.Pool to avoid allocations. type pp struct { - n int - panicking bool - erroring bool // printing an error condition - buf buffer + buf buffer + // arg holds the current item, as an interface{}. arg interface{} - // value holds the current item, as a reflect.Value, and will be - // the zero Value if the item has not been reflected. + + // value is used instead of arg for reflect values. value reflect.Value + + // fmt is used to format basic items such as integers or strings. + fmt fmt + // reordered records whether the format string used argument reordering. reordered bool // goodArgNum records whether the most recent reordering directive was valid. goodArgNum bool - runeBuf [utf8.UTFMax]byte - fmt fmt + // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion. + panicking bool + // erroring is set when printing an error string to guard against calling handleMethods. + erroring bool } var ppFree = sync.Pool{ @@ -139,10 +139,6 @@ func newPrinter() *pp { // free saves used pp structs in ppFree; avoids an allocation per invocation. func (p *pp) free() { - // Don't hold on to pp structs with large buffers. - if cap(p.buf) > 1024 { - return - } p.buf = p.buf[:0] p.arg = nil p.value = reflect.Value{} @@ -158,9 +154,9 @@ func (p *pp) Flag(b int) bool { case '-': return p.fmt.minus case '+': - return p.fmt.plus + return p.fmt.plus || p.fmt.plusV case '#': - return p.fmt.sharp + return p.fmt.sharp || p.fmt.sharpV case ' ': return p.fmt.space case '0': @@ -169,14 +165,11 @@ func (p *pp) Flag(b int) bool { return false } -func (p *pp) add(c rune) { - p.buf.WriteRune(c) -} - // Implement Write so we can call Fprintf on a pp (through State), for // recursive use in custom verbs. func (p *pp) Write(b []byte) (ret int, err error) { - return p.buf.Write(b) + p.buf.Write(b) + return len(b), nil } // These routines end in 'f' and take a format string. @@ -219,7 +212,7 @@ func Errorf(format string, a ...interface{}) error { // It returns the number of bytes written and any write error encountered. func Fprint(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() - p.doPrint(a, false, false) + p.doPrint(a) n, err = w.Write(p.buf) p.free() return @@ -236,7 +229,7 @@ func Print(a ...interface{}) (n int, err error) { // Spaces are added between operands when neither is a string. func Sprint(a ...interface{}) string { p := newPrinter() - p.doPrint(a, false, false) + p.doPrint(a) s := string(p.buf) p.free() return s @@ -251,7 +244,7 @@ func Sprint(a ...interface{}) string { // It returns the number of bytes written and any write error encountered. func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { p := newPrinter() - p.doPrint(a, true, true) + p.doPrintln(a) n, err = w.Write(p.buf) p.free() return @@ -268,7 +261,7 @@ func Println(a ...interface{}) (n int, err error) { // Spaces are always added between operands and a newline is appended. func Sprintln(a ...interface{}) string { p := newPrinter() - p.doPrint(a, true, true) + p.doPrintln(a) s := string(p.buf) p.free() return s @@ -309,7 +302,7 @@ func parsenum(s string, start, end int) (num int, isnum bool, newi int) { func (p *pp) unknownType(v reflect.Value) { if !v.IsValid() { - p.buf.Write(nilAngleBytes) + p.buf.WriteString(nilAngleString) return } p.buf.WriteByte('?') @@ -319,23 +312,22 @@ func (p *pp) unknownType(v reflect.Value) { func (p *pp) badVerb(verb rune) { p.erroring = true - p.add('%') - p.add('!') - p.add(verb) - p.add('(') + p.buf.WriteString(percentBangString) + p.buf.WriteRune(verb) + p.buf.WriteByte('(') switch { case p.arg != nil: p.buf.WriteString(reflect.TypeOf(p.arg).String()) - p.add('=') - p.printArg(p.arg, 'v', 0) + p.buf.WriteByte('=') + p.printArg(p.arg, 'v') case p.value.IsValid(): p.buf.WriteString(p.value.Type().String()) - p.add('=') + p.buf.WriteByte('=') p.printValue(p.value, 'v', 0) default: - p.buf.Write(nilAngleBytes) + p.buf.WriteString(nilAngleString) } - p.add(')') + p.buf.WriteByte(')') p.erroring = false } @@ -348,162 +340,82 @@ func (p *pp) fmtBool(v bool, verb rune) { } } -// fmtC formats a rune for the 'c' format. -func (p *pp) fmtC(c int64) { - r := rune(c) // Check for overflow. - if int64(r) != c { - r = utf8.RuneError - } - w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], r) - p.fmt.pad(p.runeBuf[0:w]) -} - -func (p *pp) fmtInt64(v int64, verb rune) { - switch verb { - case 'b': - p.fmt.integer(v, 2, signed, ldigits) - case 'c': - p.fmtC(v) - case 'd', 'v': - p.fmt.integer(v, 10, signed, ldigits) - case 'o': - p.fmt.integer(v, 8, signed, ldigits) - case 'q': - if 0 <= v && v <= utf8.MaxRune { - p.fmt.fmt_qc(v) - } else { - p.badVerb(verb) - } - case 'x': - p.fmt.integer(v, 16, signed, ldigits) - case 'U': - p.fmtUnicode(v) - case 'X': - p.fmt.integer(v, 16, signed, udigits) - default: - p.badVerb(verb) - } -} - // fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or // not, as requested, by temporarily setting the sharp flag. func (p *pp) fmt0x64(v uint64, leading0x bool) { sharp := p.fmt.sharp p.fmt.sharp = leading0x - p.fmt.integer(int64(v), 16, unsigned, ldigits) + p.fmt.fmt_integer(v, 16, unsigned, ldigits) p.fmt.sharp = sharp } -// fmtUnicode formats a uint64 in U+1234 form by -// temporarily turning on the unicode flag and tweaking the precision. -func (p *pp) fmtUnicode(v int64) { - precPresent := p.fmt.precPresent - sharp := p.fmt.sharp - p.fmt.sharp = false - prec := p.fmt.prec - if !precPresent { - // If prec is already set, leave it alone; otherwise 4 is minimum. - p.fmt.prec = 4 - p.fmt.precPresent = true - } - p.fmt.unicode = true // turn on U+ - p.fmt.uniQuote = sharp - p.fmt.integer(int64(v), 16, unsigned, udigits) - p.fmt.unicode = false - p.fmt.uniQuote = false - p.fmt.prec = prec - p.fmt.precPresent = precPresent - p.fmt.sharp = sharp -} - -func (p *pp) fmtUint64(v uint64, verb rune) { +// fmtInteger formats a signed or unsigned integer. +func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) { switch verb { - case 'b': - p.fmt.integer(int64(v), 2, unsigned, ldigits) - case 'c': - p.fmtC(int64(v)) - case 'd': - p.fmt.integer(int64(v), 10, unsigned, ldigits) case 'v': - if p.fmt.sharpV { + if p.fmt.sharpV && !isSigned { p.fmt0x64(v, true) } else { - p.fmt.integer(int64(v), 10, unsigned, ldigits) + p.fmt.fmt_integer(v, 10, isSigned, ldigits) } + case 'd': + p.fmt.fmt_integer(v, 10, isSigned, ldigits) + case 'b': + p.fmt.fmt_integer(v, 2, isSigned, ldigits) case 'o': - p.fmt.integer(int64(v), 8, unsigned, ldigits) + p.fmt.fmt_integer(v, 8, isSigned, ldigits) + case 'x': + p.fmt.fmt_integer(v, 16, isSigned, ldigits) + case 'X': + p.fmt.fmt_integer(v, 16, isSigned, udigits) + case 'c': + p.fmt.fmt_c(v) case 'q': - if 0 <= v && v <= utf8.MaxRune { - p.fmt.fmt_qc(int64(v)) + if v <= utf8.MaxRune { + p.fmt.fmt_qc(v) } else { p.badVerb(verb) } - case 'x': - p.fmt.integer(int64(v), 16, unsigned, ldigits) - case 'X': - p.fmt.integer(int64(v), 16, unsigned, udigits) case 'U': - p.fmtUnicode(int64(v)) + p.fmt.fmt_unicode(v) default: p.badVerb(verb) } } -func (p *pp) fmtFloat32(v float32, verb rune) { +// fmtFloat formats a float. The default precision for each verb +// is specified as last argument in the call to fmt_float. +func (p *pp) fmtFloat(v float64, size int, verb rune) { switch verb { - case 'b': - p.fmt.fmt_fb32(v) - case 'e': - p.fmt.fmt_e32(v) - case 'E': - p.fmt.fmt_E32(v) - case 'f', 'F': - p.fmt.fmt_f32(v) - case 'g', 'v': - p.fmt.fmt_g32(v) - case 'G': - p.fmt.fmt_G32(v) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtFloat64(v float64, verb rune) { - switch verb { - case 'b': - p.fmt.fmt_fb64(v) - case 'e': - p.fmt.fmt_e64(v) - case 'E': - p.fmt.fmt_E64(v) - case 'f', 'F': - p.fmt.fmt_f64(v) - case 'g', 'v': - p.fmt.fmt_g64(v) - case 'G': - p.fmt.fmt_G64(v) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtComplex64(v complex64, verb rune) { - switch verb { - case 'b', 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c64(v, verb) case 'v': - p.fmt.fmt_c64(v, 'g') + p.fmt.fmt_float(v, size, 'g', -1) + case 'b', 'g', 'G': + p.fmt.fmt_float(v, size, verb, -1) + case 'f', 'e', 'E': + p.fmt.fmt_float(v, size, verb, 6) + case 'F': + p.fmt.fmt_float(v, size, 'f', 6) default: p.badVerb(verb) } } -func (p *pp) fmtComplex128(v complex128, verb rune) { +// fmtComplex formats a complex number v with +// r = real(v) and j = imag(v) as (r+ji) using +// fmtFloat for r and j formatting. +func (p *pp) fmtComplex(v complex128, size int, verb rune) { + // Make sure any unsupported verbs are found before the + // calls to fmtFloat to not generate an incorrect error string. switch verb { - case 'b', 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c128(v, verb) - case 'v': - p.fmt.fmt_c128(v, 'g') + case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E': + oldPlus := p.fmt.plus + p.buf.WriteByte('(') + p.fmtFloat(real(v), size/2, verb) + // Imaginary part always has a sign. + p.fmt.plus = true + p.fmtFloat(imag(v), size/2, verb) + p.buf.WriteString("i)") + p.fmt.plus = oldPlus default: p.badVerb(verb) } @@ -530,45 +442,33 @@ func (p *pp) fmtString(v string, verb rune) { } } -func (p *pp) fmtBytes(v []byte, verb rune, typ reflect.Type, depth int) { - if verb == 'v' || verb == 'd' { +func (p *pp) fmtBytes(v []byte, verb rune, typeString string) { + switch verb { + case 'v', 'd': if p.fmt.sharpV { + p.buf.WriteString(typeString) if v == nil { - if typ == nil { - p.buf.WriteString("[]byte(nil)") - } else { - p.buf.WriteString(typ.String()) - p.buf.Write(nilParenBytes) - } + p.buf.WriteString(nilParenString) return } - if typ == nil { - p.buf.Write(bytesBytes) - } else { - p.buf.WriteString(typ.String()) - p.buf.WriteByte('{') + p.buf.WriteByte('{') + for i, c := range v { + if i > 0 { + p.buf.WriteString(commaSpaceString) + } + p.fmt0x64(uint64(c), true) } + p.buf.WriteByte('}') } else { p.buf.WriteByte('[') - } - for i, c := range v { - if i > 0 { - if p.fmt.sharpV { - p.buf.Write(commaSpaceBytes) - } else { + for i, c := range v { + if i > 0 { p.buf.WriteByte(' ') } + p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits) } - p.printArg(c, 'v', depth+1) - } - if p.fmt.sharpV { - p.buf.WriteByte('}') - } else { p.buf.WriteByte(']') } - return - } - switch verb { case 's': p.fmt.fmt_s(string(v)) case 'x': @@ -578,23 +478,11 @@ func (p *pp) fmtBytes(v []byte, verb rune, typ reflect.Type, depth int) { case 'q': p.fmt.fmt_q(string(v)) default: - p.badVerb(verb) + p.printValue(reflect.ValueOf(v), verb, 0) } } func (p *pp) fmtPointer(value reflect.Value, verb rune) { - use0x64 := true - switch verb { - case 'p', 'v': - // ok - case 'b', 'd', 'o', 'x', 'X': - use0x64 = false - // ok - default: - p.badVerb(verb) - return - } - var u uintptr switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: @@ -604,40 +492,41 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune) { return } - if p.fmt.sharpV { - p.add('(') - p.buf.WriteString(value.Type().String()) - p.add(')') - p.add('(') - if u == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(u), true) - } - p.add(')') - } else if verb == 'v' && u == 0 { - p.buf.Write(nilAngleBytes) - } else { - if use0x64 { - p.fmt0x64(uint64(u), !p.fmt.sharp) + switch verb { + case 'v': + if p.fmt.sharpV { + p.buf.WriteByte('(') + p.buf.WriteString(value.Type().String()) + p.buf.WriteString(")(") + if u == 0 { + p.buf.WriteString(nilString) + } else { + p.fmt0x64(uint64(u), true) + } + p.buf.WriteByte(')') } else { - p.fmtUint64(uint64(u), verb) + if u == 0 { + p.fmt.padString(nilAngleString) + } else { + p.fmt0x64(uint64(u), !p.fmt.sharp) + } } + case 'p': + p.fmt0x64(uint64(u), !p.fmt.sharp) + case 'b', 'o', 'd', 'x', 'X': + p.fmtInteger(uint64(u), unsigned, verb) + default: + p.badVerb(verb) } } -var ( - intBits = reflect.TypeOf(0).Bits() - uintptrBits = reflect.TypeOf(uintptr(0)).Bits() -) - func (p *pp) catchPanic(arg interface{}, verb rune) { if err := recover(); err != nil { // If it's a nil pointer, just say "<nil>". The likeliest causes are a // Stringer that fails to guard against nil or a nil pointer for a // value receiver, and in either case, "<nil>" is a nice result. if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() { - p.buf.Write(nilAngleBytes) + p.buf.WriteString(nilAngleString) return } // Otherwise print a concise panic message. Most of the time the panic @@ -647,52 +536,23 @@ func (p *pp) catchPanic(arg interface{}, verb rune) { panic(err) } p.fmt.clearflags() // We are done, and for this output we want default behavior. - p.buf.Write(percentBangBytes) - p.add(verb) - p.buf.Write(panicBytes) + p.buf.WriteString(percentBangString) + p.buf.WriteRune(verb) + p.buf.WriteString(panicString) p.panicking = true - p.printArg(err, 'v', 0) + p.printArg(err, 'v') p.panicking = false p.buf.WriteByte(')') } } -// clearSpecialFlags pushes %#v back into the regular flags and returns their old state. -func (p *pp) clearSpecialFlags() (plusV, sharpV bool) { - plusV = p.fmt.plusV - if plusV { - p.fmt.plus = true - p.fmt.plusV = false - } - sharpV = p.fmt.sharpV - if sharpV { - p.fmt.sharp = true - p.fmt.sharpV = false - } - return -} - -// restoreSpecialFlags, whose argument should be a call to clearSpecialFlags, -// restores the setting of the plusV and sharpV flags. -func (p *pp) restoreSpecialFlags(plusV, sharpV bool) { - if plusV { - p.fmt.plus = false - p.fmt.plusV = true - } - if sharpV { - p.fmt.sharp = false - p.fmt.sharpV = true - } -} - -func (p *pp) handleMethods(verb rune, depth int) (handled bool) { +func (p *pp) handleMethods(verb rune) (handled bool) { if p.erroring { return } // Is it a Formatter? if formatter, ok := p.arg.(Formatter); ok { handled = true - defer p.restoreSpecialFlags(p.clearSpecialFlags()) defer p.catchPanic(p.arg, verb) formatter.Format(p, verb) return @@ -721,13 +581,13 @@ func (p *pp) handleMethods(verb rune, depth int) (handled bool) { case error: handled = true defer p.catchPanic(p.arg, verb) - p.printArg(v.Error(), verb, depth) + p.fmtString(v.Error(), verb) return case Stringer: handled = true defer p.catchPanic(p.arg, verb) - p.printArg(v.String(), verb, depth) + p.fmtString(v.String(), verb) return } } @@ -735,28 +595,29 @@ func (p *pp) handleMethods(verb rune, depth int) (handled bool) { return false } -func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) { +func (p *pp) printArg(arg interface{}, verb rune) { p.arg = arg p.value = reflect.Value{} if arg == nil { - if verb == 'T' || verb == 'v' { - p.fmt.pad(nilAngleBytes) - } else { + switch verb { + case 'T', 'v': + p.fmt.padString(nilAngleString) + default: p.badVerb(verb) } - return false + return } // Special processing considerations. // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': - p.printArg(reflect.TypeOf(arg).String(), 's', 0) - return false + p.fmt.fmt_s(reflect.TypeOf(arg).String()) + return case 'p': - p.fmtPointer(reflect.ValueOf(arg), verb) - return false + p.fmtPointer(reflect.ValueOf(arg), 'p') + return } // Some types can be done without reflection. @@ -764,137 +625,110 @@ func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) { case bool: p.fmtBool(f, verb) case float32: - p.fmtFloat32(f, verb) + p.fmtFloat(float64(f), 32, verb) case float64: - p.fmtFloat64(f, verb) + p.fmtFloat(f, 64, verb) case complex64: - p.fmtComplex64(f, verb) + p.fmtComplex(complex128(f), 64, verb) case complex128: - p.fmtComplex128(f, verb) + p.fmtComplex(f, 128, verb) case int: - p.fmtInt64(int64(f), verb) + p.fmtInteger(uint64(f), signed, verb) case int8: - p.fmtInt64(int64(f), verb) + p.fmtInteger(uint64(f), signed, verb) case int16: - p.fmtInt64(int64(f), verb) + p.fmtInteger(uint64(f), signed, verb) case int32: - p.fmtInt64(int64(f), verb) + p.fmtInteger(uint64(f), signed, verb) case int64: - p.fmtInt64(f, verb) + p.fmtInteger(uint64(f), signed, verb) case uint: - p.fmtUint64(uint64(f), verb) + p.fmtInteger(uint64(f), unsigned, verb) case uint8: - p.fmtUint64(uint64(f), verb) + p.fmtInteger(uint64(f), unsigned, verb) case uint16: - p.fmtUint64(uint64(f), verb) + p.fmtInteger(uint64(f), unsigned, verb) case uint32: - p.fmtUint64(uint64(f), verb) + p.fmtInteger(uint64(f), unsigned, verb) case uint64: - p.fmtUint64(f, verb) + p.fmtInteger(f, unsigned, verb) case uintptr: - p.fmtUint64(uint64(f), verb) + p.fmtInteger(uint64(f), unsigned, verb) case string: p.fmtString(f, verb) - wasString = verb == 's' || verb == 'v' case []byte: - p.fmtBytes(f, verb, nil, depth) - wasString = verb == 's' + p.fmtBytes(f, verb, "[]byte") case reflect.Value: - return p.printReflectValue(f, verb, depth) + p.printValue(f, verb, 0) default: // If the type is not simple, it might have methods. - if handled := p.handleMethods(verb, depth); handled { - return false + if !p.handleMethods(verb) { + // Need to use reflection, since the type had no + // interface methods that could be used for formatting. + p.printValue(reflect.ValueOf(f), verb, 0) } - // Need to use reflection - return p.printReflectValue(reflect.ValueOf(arg), verb, depth) } - p.arg = nil - return } -// printValue is like printArg but starts with a reflect value, not an interface{} value. -func (p *pp) printValue(value reflect.Value, verb rune, depth int) (wasString bool) { - if !value.IsValid() { - if verb == 'T' || verb == 'v' { - p.buf.Write(nilAngleBytes) - } else { - p.badVerb(verb) - } - return false - } - - // Special processing considerations. - // %T (the value's type) and %p (its address) are special; we always do them first. - switch verb { - case 'T': - p.printArg(value.Type().String(), 's', 0) - return false - case 'p': - p.fmtPointer(value, verb) - return false - } +var byteType = reflect.TypeOf(byte(0)) - // Handle values with special methods. - // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us. - p.arg = nil // Make sure it's cleared, for safety. - if value.CanInterface() { +// printValue is similar to printArg but starts with a reflect value, not an interface{} value. +// It does not handle 'p' and 'T' verbs because these should have been already handled by printArg. +func (p *pp) printValue(value reflect.Value, verb rune, depth int) { + // Handle values with special methods if not already handled by printArg (depth == 0). + if depth > 0 && value.IsValid() && value.CanInterface() { p.arg = value.Interface() + if p.handleMethods(verb) { + return + } } - if handled := p.handleMethods(verb, depth); handled { - return false - } - - return p.printReflectValue(value, verb, depth) -} - -var byteType = reflect.TypeOf(byte(0)) - -// printReflectValue is the fallback for both printArg and printValue. -// It uses reflect to print the value. -func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasString bool) { - oldValue := p.value + p.arg = nil p.value = value -BigSwitch: - switch f := value; f.Kind() { + + switch f := value; value.Kind() { case reflect.Invalid: - p.buf.WriteString("<invalid reflect.Value>") + if depth == 0 { + p.buf.WriteString(invReflectString) + } else { + switch verb { + case 'v': + p.buf.WriteString(nilAngleString) + default: + p.badVerb(verb) + } + } case reflect.Bool: p.fmtBool(f.Bool(), verb) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p.fmtInt64(f.Int(), verb) + p.fmtInteger(uint64(f.Int()), signed, verb) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(f.Uint(), verb) - case reflect.Float32, reflect.Float64: - if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Float()), verb) - } else { - p.fmtFloat64(f.Float(), verb) - } - case reflect.Complex64, reflect.Complex128: - if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Complex()), verb) - } else { - p.fmtComplex128(f.Complex(), verb) - } + p.fmtInteger(f.Uint(), unsigned, verb) + case reflect.Float32: + p.fmtFloat(f.Float(), 32, verb) + case reflect.Float64: + p.fmtFloat(f.Float(), 64, verb) + case reflect.Complex64: + p.fmtComplex(f.Complex(), 64, verb) + case reflect.Complex128: + p.fmtComplex(f.Complex(), 128, verb) case reflect.String: p.fmtString(f.String(), verb) case reflect.Map: if p.fmt.sharpV { p.buf.WriteString(f.Type().String()) if f.IsNil() { - p.buf.WriteString("(nil)") - break + p.buf.WriteString(nilParenString) + return } p.buf.WriteByte('{') } else { - p.buf.Write(mapBytes) + p.buf.WriteString(mapString) } keys := f.MapKeys() for i, key := range keys { if i > 0 { if p.fmt.sharpV { - p.buf.Write(commaSpaceBytes) + p.buf.WriteString(commaSpaceString) } else { p.buf.WriteByte(' ') } @@ -910,26 +744,24 @@ BigSwitch: } case reflect.Struct: if p.fmt.sharpV { - p.buf.WriteString(value.Type().String()) + p.buf.WriteString(f.Type().String()) } - p.add('{') - v := f - t := v.Type() - for i := 0; i < v.NumField(); i++ { + p.buf.WriteByte('{') + for i := 0; i < f.NumField(); i++ { if i > 0 { if p.fmt.sharpV { - p.buf.Write(commaSpaceBytes) + p.buf.WriteString(commaSpaceString) } else { p.buf.WriteByte(' ') } } if p.fmt.plusV || p.fmt.sharpV { - if f := t.Field(i); f.Name != "" { - p.buf.WriteString(f.Name) + if name := f.Type().Field(i).Name; name != "" { + p.buf.WriteString(name) p.buf.WriteByte(':') } } - p.printValue(getField(v, i), verb, depth+1) + p.printValue(getField(f, i), verb, depth+1) } p.buf.WriteByte('}') case reflect.Interface: @@ -937,91 +769,79 @@ BigSwitch: if !value.IsValid() { if p.fmt.sharpV { p.buf.WriteString(f.Type().String()) - p.buf.Write(nilParenBytes) + p.buf.WriteString(nilParenString) } else { - p.buf.Write(nilAngleBytes) + p.buf.WriteString(nilAngleString) } } else { - wasString = p.printValue(value, verb, depth+1) + p.printValue(value, verb, depth+1) } case reflect.Array, reflect.Slice: - // Byte slices are special: - // - Handle []byte (== []uint8) with fmtBytes. - // - Handle []T, where T is a named byte type, with fmtBytes only - // for the s, q, an x verbs. For other verbs, T might be a - // Stringer, so we use printValue to print each element. - if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 && (typ.Elem() == byteType || verb == 's' || verb == 'q' || verb == 'x') { - var bytes []byte - if f.Kind() == reflect.Slice { - bytes = f.Bytes() - } else if f.CanAddr() { - bytes = f.Slice(0, f.Len()).Bytes() - } else { - // We have an array, but we cannot Slice() a non-addressable array, - // so we build a slice by hand. This is a rare case but it would be nice - // if reflection could help a little more. - bytes = make([]byte, f.Len()) - for i := range bytes { - bytes[i] = byte(f.Index(i).Uint()) + switch verb { + case 's', 'q', 'x', 'X': + // Handle byte and uint8 slices and arrays special for the above verbs. + t := f.Type() + if t.Elem().Kind() == reflect.Uint8 { + var bytes []byte + if f.Kind() == reflect.Slice { + bytes = f.Bytes() + } else if f.CanAddr() { + bytes = f.Slice(0, f.Len()).Bytes() + } else { + // We have an array, but we cannot Slice() a non-addressable array, + // so we build a slice by hand. This is a rare case but it would be nice + // if reflection could help a little more. + bytes = make([]byte, f.Len()) + for i := range bytes { + bytes[i] = byte(f.Index(i).Uint()) + } } + p.fmtBytes(bytes, verb, t.String()) + return } - p.fmtBytes(bytes, verb, typ, depth) - wasString = verb == 's' - break } if p.fmt.sharpV { - p.buf.WriteString(value.Type().String()) + p.buf.WriteString(f.Type().String()) if f.Kind() == reflect.Slice && f.IsNil() { - p.buf.WriteString("(nil)") - break + p.buf.WriteString(nilParenString) + return + } else { + p.buf.WriteByte('{') + for i := 0; i < f.Len(); i++ { + if i > 0 { + p.buf.WriteString(commaSpaceString) + } + p.printValue(f.Index(i), verb, depth+1) + } + p.buf.WriteByte('}') } - p.buf.WriteByte('{') } else { p.buf.WriteByte('[') - } - for i := 0; i < f.Len(); i++ { - if i > 0 { - if p.fmt.sharpV { - p.buf.Write(commaSpaceBytes) - } else { + for i := 0; i < f.Len(); i++ { + if i > 0 { p.buf.WriteByte(' ') } + p.printValue(f.Index(i), verb, depth+1) } - p.printValue(f.Index(i), verb, depth+1) - } - if p.fmt.sharpV { - p.buf.WriteByte('}') - } else { p.buf.WriteByte(']') } case reflect.Ptr: - v := f.Pointer() // pointer to array or slice or struct? ok at top level // but not embedded (avoid loops) - if v != 0 && depth == 0 { + if depth == 0 && f.Pointer() != 0 { switch a := f.Elem(); a.Kind() { - case reflect.Array, reflect.Slice: - p.buf.WriteByte('&') - p.printValue(a, verb, depth+1) - break BigSwitch - case reflect.Struct: - p.buf.WriteByte('&') - p.printValue(a, verb, depth+1) - break BigSwitch - case reflect.Map: + case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map: p.buf.WriteByte('&') p.printValue(a, verb, depth+1) - break BigSwitch + return } } fallthrough case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(value, verb) + p.fmtPointer(f, verb) default: p.unknownType(f) } - p.value = oldValue - return wasString } // intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has integer type. @@ -1098,11 +918,24 @@ func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum return argNum, i + wid, ok } +func (p *pp) badArgNum(verb rune) { + p.buf.WriteString(percentBangString) + p.buf.WriteRune(verb) + p.buf.WriteString(badIndexString) +} + +func (p *pp) missingArg(verb rune) { + p.buf.WriteString(percentBangString) + p.buf.WriteRune(verb) + p.buf.WriteString(missingString) +} + func (p *pp) doPrintf(format string, a []interface{}) { end := len(format) argNum := 0 // we process one argument per non-trivial format afterIndex := false // previous item in format was an index like [3]. p.reordered = false +formatLoop: for i := 0; i < end; { p.goodArgNum = true lasti := i @@ -1122,21 +955,40 @@ func (p *pp) doPrintf(format string, a []interface{}) { // Do we have flags? p.fmt.clearflags() - F: + simpleFormat: for ; i < end; i++ { - switch format[i] { + c := format[i] + switch c { case '#': p.fmt.sharp = true case '0': - p.fmt.zero = true + p.fmt.zero = !p.fmt.minus // Only allow zero padding to the left. case '+': p.fmt.plus = true case '-': p.fmt.minus = true + p.fmt.zero = false // Do not pad with zeros to the right. case ' ': p.fmt.space = true default: - break F + // Fast path for common case of ascii lower case simple verbs + // without precision or width or argument indices. + if 'a' <= c && c <= 'z' && argNum < len(a) { + if c == 'v' { + // Go syntax + p.fmt.sharpV = p.fmt.sharp + p.fmt.sharp = false + // Struct-field syntax + p.fmt.plusV = p.fmt.plus + p.fmt.plus = false + } + p.printArg(a[argNum], rune(c)) + argNum++ + i++ + continue formatLoop + } + // Format is more complex than simple flags and a verb or is malformed. + break simpleFormat } } @@ -1149,7 +1001,7 @@ func (p *pp) doPrintf(format string, a []interface{}) { p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum) if !p.fmt.widPresent { - p.buf.Write(badWidthBytes) + p.buf.WriteString(badWidthString) } // We have a negative width, so take its value and ensure @@ -1157,6 +1009,7 @@ func (p *pp) doPrintf(format string, a []interface{}) { if p.fmt.wid < 0 { p.fmt.wid = -p.fmt.wid p.fmt.minus = true + p.fmt.zero = false // Do not pad with zeros to the right. } afterIndex = false } else { @@ -1182,7 +1035,7 @@ func (p *pp) doPrintf(format string, a []interface{}) { p.fmt.precPresent = false } if !p.fmt.precPresent { - p.buf.Write(badPrecBytes) + p.buf.WriteString(badPrecString) } afterIndex = false } else { @@ -1199,80 +1052,77 @@ func (p *pp) doPrintf(format string, a []interface{}) { } if i >= end { - p.buf.Write(noVerbBytes) - continue + p.buf.WriteString(noVerbString) + break } - c, w := utf8.DecodeRuneInString(format[i:]) + + verb, w := utf8.DecodeRuneInString(format[i:]) i += w - // percent is special - absorbs no operand - if c == '%' { - p.buf.WriteByte('%') // We ignore width and prec. - continue - } - if !p.goodArgNum { - p.buf.Write(percentBangBytes) - p.add(c) - p.buf.Write(badIndexBytes) - continue - } else if argNum >= len(a) { // out of operands - p.buf.Write(percentBangBytes) - p.add(c) - p.buf.Write(missingBytes) - continue - } - arg := a[argNum] - argNum++ - - if c == 'v' { - if p.fmt.sharp { - // Go syntax. Set the flag in the fmt and clear the sharp flag. - p.fmt.sharp = false - p.fmt.sharpV = true - } - if p.fmt.plus { - // Struct-field syntax. Set the flag in the fmt and clear the plus flag. - p.fmt.plus = false - p.fmt.plusV = true - } + + switch { + case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec. + p.buf.WriteByte('%') + case !p.goodArgNum: + p.badArgNum(verb) + case argNum >= len(a): // No argument left over to print for the current verb. + p.missingArg(verb) + case verb == 'v': + // Go syntax + p.fmt.sharpV = p.fmt.sharp + p.fmt.sharp = false + // Struct-field syntax + p.fmt.plusV = p.fmt.plus + p.fmt.plus = false + fallthrough + default: + p.printArg(a[argNum], verb) + argNum++ } - p.printArg(arg, c, 0) } // Check for extra arguments unless the call accessed the arguments // out of order, in which case it's too expensive to detect if they've all // been used and arguably OK if they're not. if !p.reordered && argNum < len(a) { - p.buf.Write(extraBytes) - for ; argNum < len(a); argNum++ { - arg := a[argNum] - if arg != nil { + p.fmt.clearflags() + p.buf.WriteString(extraString) + for i, arg := range a[argNum:] { + if i > 0 { + p.buf.WriteString(commaSpaceString) + } + if arg == nil { + p.buf.WriteString(nilAngleString) + } else { p.buf.WriteString(reflect.TypeOf(arg).String()) p.buf.WriteByte('=') - } - p.printArg(arg, 'v', 0) - if argNum+1 < len(a) { - p.buf.Write(commaSpaceBytes) + p.printArg(arg, 'v') } } p.buf.WriteByte(')') } } -func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { +func (p *pp) doPrint(a []interface{}) { prevString := false - for argNum := 0; argNum < len(a); argNum++ { - p.fmt.clearflags() - // always add spaces if we're doing Println - arg := a[argNum] - if argNum > 0 { - isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String - if addspace || !isString && !prevString { - p.buf.WriteByte(' ') - } + for argNum, arg := range a { + isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String + // Add a space between two non-string arguments. + if argNum > 0 && !isString && !prevString { + p.buf.WriteByte(' ') } - prevString = p.printArg(arg, 'v', 0) + p.printArg(arg, 'v') + prevString = isString } - if addnewline { - p.buf.WriteByte('\n') +} + +// doPrintln is like doPrint but always adds a space between arguments +// and a newline after the last argument. +func (p *pp) doPrintln(a []interface{}) { + for argNum, arg := range a { + if argNum > 0 { + p.buf.WriteByte(' ') + } + p.printArg(arg, 'v') } + p.buf.WriteByte('\n') } diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index 4618ed4a827..fdf419795d9 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -15,14 +15,6 @@ import ( "unicode/utf8" ) -// runeUnreader is the interface to something that can unread runes. -// If the object provided to Scan does not satisfy this interface, -// a local buffer will be used to back up the input, but its contents -// will be lost when Scan returns. -type runeUnreader interface { - UnreadRune() error -} - // ScanState represents the scanner state passed to custom scanners. // Scanners may do rune-at-a-time scanning or ask the ScanState // to discover the next space-delimited token. @@ -41,7 +33,7 @@ type ScanState interface { // Token skips space in the input if skipSpace is true, then returns the // run of Unicode code points c satisfying f(c). If f is nil, // !unicode.IsSpace(c) is used; that is, the token will hold non-space - // characters. Newlines are treated appropriately for the operation being + // characters. Newlines are treated appropriately for the operation being // performed; see the package documentation for more information. // The returned slice points to shared data that may be overwritten // by the next call to Token, a call to a Scan function using the ScanState @@ -58,15 +50,15 @@ type ScanState interface { // Scanner is implemented by any value that has a Scan method, which scans // the input for the representation of a value and stores the result in the -// receiver, which must be a pointer to be useful. The Scan method is called +// receiver, which must be a pointer to be useful. The Scan method is called // for any argument to Scan, Scanf, or Scanln that implements it. type Scanner interface { Scan(state ScanState, verb rune) error } // Scan scans text read from standard input, storing successive -// space-separated values into successive arguments. Newlines count -// as space. It returns the number of items successfully scanned. +// space-separated values into successive arguments. Newlines count +// as space. It returns the number of items successfully scanned. // If that is less than the number of arguments, err will report why. func Scan(a ...interface{}) (n int, err error) { return Fscan(os.Stdin, a...) @@ -80,7 +72,7 @@ func Scanln(a ...interface{}) (n int, err error) { // Scanf scans text read from standard input, storing successive // space-separated values into successive arguments as determined by -// the format. It returns the number of items successfully scanned. +// the format. It returns the number of items successfully scanned. // If that is less than the number of arguments, err will report why. // Newlines in the input must match newlines in the format. // The one exception: the verb %c always scans the next rune in the @@ -101,8 +93,8 @@ func (r *stringReader) Read(b []byte) (n int, err error) { } // Sscan scans the argument string, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less +// values into successive arguments. Newlines count as space. It +// returns the number of items successfully scanned. If that is less // than the number of arguments, err will report why. func Sscan(str string, a ...interface{}) (n int, err error) { return Fscan((*stringReader)(&str), a...) @@ -115,7 +107,7 @@ func Sscanln(str string, a ...interface{}) (n int, err error) { } // Sscanf scans the argument string, storing successive space-separated -// values into successive arguments as determined by the format. It +// values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. func Sscanf(str string, format string, a ...interface{}) (n int, err error) { @@ -123,8 +115,8 @@ func Sscanf(str string, format string, a ...interface{}) (n int, err error) { } // Fscan scans text read from r, storing successive space-separated -// values into successive arguments. Newlines count as space. It -// returns the number of items successfully scanned. If that is less +// values into successive arguments. Newlines count as space. It +// returns the number of items successfully scanned. If that is less // than the number of arguments, err will report why. func Fscan(r io.Reader, a ...interface{}) (n int, err error) { s, old := newScanState(r, true, false) @@ -143,7 +135,7 @@ func Fscanln(r io.Reader, a ...interface{}) (n int, err error) { } // Fscanf scans text read from r, storing successive space-separated -// values into successive arguments as determined by the format. It +// values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) { @@ -163,12 +155,10 @@ const eof = -1 // ss is the internal implementation of ScanState. type ss struct { - rr io.RuneReader // where to read input - buf buffer // token accumulator - peekRune rune // one-rune lookahead - prevRune rune // last rune returned by ReadRune - count int // runes consumed so far. - atEOF bool // already read EOF + rs io.RuneScanner // where to read input + buf buffer // token accumulator + count int // runes consumed so far. + atEOF bool // already read EOF ssave } @@ -191,23 +181,17 @@ func (s *ss) Read(buf []byte) (n int, err error) { } func (s *ss) ReadRune() (r rune, size int, err error) { - if s.peekRune >= 0 { - s.count++ - r = s.peekRune - size = utf8.RuneLen(r) - s.prevRune = r - s.peekRune = -1 - return - } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.argLimit { + if s.atEOF || s.count >= s.argLimit { err = io.EOF return } - r, size, err = s.rr.ReadRune() + r, size, err = s.rs.ReadRune() if err == nil { s.count++ - s.prevRune = r + if s.nlIsEnd && r == '\n' { + s.atEOF = true + } } else if err == io.EOF { s.atEOF = true } @@ -246,12 +230,8 @@ func (s *ss) mustReadRune() (r rune) { } func (s *ss) UnreadRune() error { - if u, ok := s.rr.(runeUnreader); ok { - u.UnreadRune() - } else { - s.peekRune = s.prevRune - } - s.prevRune = -1 + s.rs.UnreadRune() + s.atEOF = false s.count-- return nil } @@ -326,13 +306,14 @@ func (s *ss) SkipSpace() { } // readRune is a structure to enable reading UTF-8 encoded code points -// from an io.Reader. It is used if the Reader given to the scanner does -// not already implement io.RuneReader. +// from an io.Reader. It is used if the Reader given to the scanner does +// not already implement io.RuneScanner. type readRune struct { - reader io.Reader - buf [utf8.UTFMax]byte // used only inside ReadRune - pending int // number of bytes in pendBuf; only >0 for bad UTF-8 - pendBuf [utf8.UTFMax]byte // bytes left over + reader io.Reader + buf [utf8.UTFMax]byte // used only inside ReadRune + pending int // number of bytes in pendBuf; only >0 for bad UTF-8 + pendBuf [utf8.UTFMax]byte // bytes left over + peekRune rune // if >=0 next rune; when <0 is ^(previous Rune) } // readByte returns the next byte from the input, which may be @@ -344,33 +325,35 @@ func (r *readRune) readByte() (b byte, err error) { r.pending-- return } - n, err := io.ReadFull(r.reader, r.pendBuf[0:1]) + n, err := io.ReadFull(r.reader, r.pendBuf[:1]) if n != 1 { return 0, err } return r.pendBuf[0], err } -// unread saves the bytes for the next read. -func (r *readRune) unread(buf []byte) { - copy(r.pendBuf[r.pending:], buf) - r.pending += len(buf) -} - // ReadRune returns the next UTF-8 encoded code point from the // io.Reader inside r. func (r *readRune) ReadRune() (rr rune, size int, err error) { + if r.peekRune >= 0 { + rr = r.peekRune + r.peekRune = ^r.peekRune + size = utf8.RuneLen(rr) + return + } r.buf[0], err = r.readByte() if err != nil { - return 0, 0, err + return } if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case rr = rune(r.buf[0]) size = 1 // Known to be 1. + // Flip the bits of the rune so it's available to UnreadRune. + r.peekRune = ^rr return } var n int - for n = 1; !utf8.FullRune(r.buf[0:n]); n++ { + for n = 1; !utf8.FullRune(r.buf[:n]); n++ { r.buf[n], err = r.readByte() if err != nil { if err == io.EOF { @@ -380,13 +363,25 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) { return } } - rr, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) + rr, size = utf8.DecodeRune(r.buf[:n]) + if size < n { // an error, save the bytes for the next read + copy(r.pendBuf[r.pending:], r.buf[size:n]) + r.pending += n - size } + // Flip the bits of the rune so it's available to UnreadRune. + r.peekRune = ^rr return } +func (r *readRune) UnreadRune() error { + if r.peekRune >= 0 { + return errors.New("fmt: scanning called UnreadRune with no rune available") + } + // Reverse bit flip of previously read rune to obtain valid >=0 state. + r.peekRune = ^r.peekRune + return nil +} + var ssFree = sync.Pool{ New: func() interface{} { return new(ss) }, } @@ -394,15 +389,13 @@ var ssFree = sync.Pool{ // newScanState allocates a new ss struct or grab a cached one. func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { s = ssFree.Get().(*ss) - if rr, ok := r.(io.RuneReader); ok { - s.rr = rr + if rs, ok := r.(io.RuneScanner); ok { + s.rs = rs } else { - s.rr = &readRune{reader: r} + s.rs = &readRune{reader: r, peekRune: -1} } s.nlIsSpace = nlIsSpace s.nlIsEnd = nlIsEnd - s.prevRune = -1 - s.peekRune = -1 s.atEOF = false s.limit = hugeWid s.argLimit = hugeWid @@ -424,7 +417,7 @@ func (s *ss) free(old ssave) { return } s.buf = s.buf[:0] - s.rr = nil + s.rs = nil ssFree.Put(s) } @@ -455,8 +448,8 @@ func (s *ss) skipSpace(stopAtNewline bool) { } } -// token returns the next space-delimited string from the input. It -// skips white space. For Scanln, it stops at newlines. For Scan, +// token returns the next space-delimited string from the input. It +// skips white space. For Scanln, it stops at newlines. For Scan, // newlines are treated as spaces. func (s *ss) token(skipSpace bool, f func(rune) bool) []byte { if skipSpace { @@ -525,7 +518,7 @@ func (s *ss) notEOF() { s.UnreadRune() } -// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the +// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the // buffer and returns true. Otherwise it return false. func (s *ss) accept(ok string) bool { return s.consume(ok, true) @@ -549,7 +542,7 @@ func (s *ss) scanBool(verb rune) bool { if !s.okVerb(verb, "tv", "boolean") { return false } - // Syntax-checking a boolean is annoying. We're not fastidious about case. + // Syntax-checking a boolean is annoying. We're not fastidious about case. switch s.getRune() { case '0': return false @@ -643,7 +636,7 @@ func (s *ss) scanBasePrefix() (base int, digits string, found bool) { } // scanInt returns the value of the integer represented by the next -// token, checking for overflow. Any error is stored in s.err. +// token, checking for overflow. Any error is stored in s.err. func (s *ss) scanInt(verb rune, bitSize int) int64 { if verb == 'c' { return s.scanRune(bitSize) @@ -676,7 +669,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 { } // scanUint returns the value of the unsigned integer represented -// by the next token, checking for overflow. Any error is stored in s.err. +// by the next token, checking for overflow. Any error is stored in s.err. func (s *ss) scanUint(verb rune, bitSize int) uint64 { if verb == 'c' { return uint64(s.scanRune(bitSize)) @@ -846,7 +839,7 @@ func (s *ss) quotedString() string { return string(s.buf) case '"': // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) + s.buf.WriteByte('"') for { r := s.mustReadRune() s.buf.WriteRune(r) @@ -922,9 +915,14 @@ func (s *ss) hexString() string { return string(s.buf) } -const floatVerbs = "beEfFgGv" +const ( + floatVerbs = "beEfFgGv" -const hugeWid = 1 << 30 + hugeWid = 1 << 30 + + intBits = 32 << (^uint(0) >> 63) + uintptrBits = 32 << (^uintptr(0) >> 63) +) // scanOne scans a single value, deriving the scanner from the type of the argument. func (s *ss) scanOne(verb rune, arg interface{}) { @@ -1142,7 +1140,7 @@ func (s *ss) advance(format string) (i int) { } // doScanf does the real work when scanning with a format string. -// At the moment, it handles only pointers to basic types. +// At the moment, it handles only pointers to basic types. func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err error) { defer errorHandler(&err) end := len(format) - 1 @@ -1155,7 +1153,7 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro } // Either we failed to advance, we have a percent character, or we ran out of input. if format[i] != '%' { - // Can't advance format. Why not? + // Can't advance format. Why not? if w < 0 { s.errorString("input does not match format") } diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go index 7ac74dcb4bd..e36b62e78a8 100644 --- a/libgo/go/fmt/scan_test.go +++ b/libgo/go/fmt/scan_test.go @@ -15,6 +15,7 @@ import ( "regexp" "strings" "testing" + "testing/iotest" "unicode/utf8" ) @@ -78,12 +79,6 @@ var ( renamedComplex128Val renamedComplex128 ) -type FloatTest struct { - text string - in float64 - out float64 -} - // Xs accepts any non-empty run of the verb character type Xs string @@ -124,20 +119,6 @@ func (s *IntString) Scan(state ScanState, verb rune) error { var intStringVal IntString -// myStringReader implements Read but not ReadRune, allowing us to test our readRune wrapper -// type that creates something that can read runes given only Read(). -type myStringReader struct { - r *strings.Reader -} - -func (s *myStringReader) Read(p []byte) (n int, err error) { - return s.r.Read(p) -} - -func newReader(s string) *myStringReader { - return &myStringReader{strings.NewReader(s)} -} - var scanTests = []ScanTest{ // Basic types {"T\n", &boolVal, true}, // boolean test vals toggle to be sure they are written @@ -369,25 +350,38 @@ var multiTests = []ScanfMultiTest{ {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""}, } -func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) { +var readers = []struct { + name string + f func(string) io.Reader +}{ + {"StringReader", func(s string) io.Reader { + return strings.NewReader(s) + }}, + {"ReaderOnly", func(s string) io.Reader { + return struct{ io.Reader }{strings.NewReader(s)} + }}, + {"OneByteReader", func(s string) io.Reader { + return iotest.OneByteReader(strings.NewReader(s)) + }}, + {"DataErrReader", func(s string) io.Reader { + return iotest.DataErrReader(strings.NewReader(s)) + }}, +} + +func testScan(t *testing.T, f func(string) io.Reader, scan func(r io.Reader, a ...interface{}) (int, error)) { for _, test := range scanTests { - var r io.Reader - if name == "StringReader" { - r = strings.NewReader(test.text) - } else { - r = newReader(test.text) - } + r := f(test.text) n, err := scan(r, test.in) if err != nil { m := "" if n > 0 { m = Sprintf(" (%d fields ok)", n) } - t.Errorf("%s got error scanning %q: %s%s", name, test.text, err, m) + t.Errorf("got error scanning %q: %s%s", test.text, err, m) continue } if n != 1 { - t.Errorf("%s count error on entry %q: got %d", name, test.text, n) + t.Errorf("count error on entry %q: got %d", test.text, n) continue } // The incoming value may be a pointer @@ -397,25 +391,25 @@ func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{} } val := v.Interface() if !reflect.DeepEqual(val, test.out) { - t.Errorf("%s scanning %q: expected %#v got %#v, type %T", name, test.text, test.out, val, val) + t.Errorf("scanning %q: expected %#v got %#v, type %T", test.text, test.out, val, val) } } } func TestScan(t *testing.T) { - testScan("StringReader", t, Fscan) -} - -func TestMyReaderScan(t *testing.T) { - testScan("myStringReader", t, Fscan) + for _, r := range readers { + t.Run(r.name, func(t *testing.T) { + testScan(t, r.f, Fscan) + }) + } } func TestScanln(t *testing.T) { - testScan("StringReader", t, Fscanln) -} - -func TestMyReaderScanln(t *testing.T) { - testScan("myStringReader", t, Fscanln) + for _, r := range readers { + t.Run(r.name, func(t *testing.T) { + testScan(t, r.f, Fscanln) + }) + } } func TestScanf(t *testing.T) { @@ -506,20 +500,15 @@ func TestInf(t *testing.T) { } } -func testScanfMulti(name string, t *testing.T) { +func testScanfMulti(t *testing.T, f func(string) io.Reader) { sliceType := reflect.TypeOf(make([]interface{}, 1)) for _, test := range multiTests { - var r io.Reader - if name == "StringReader" { - r = strings.NewReader(test.text) - } else { - r = newReader(test.text) - } + r := f(test.text) n, err := Fscanf(r, test.format, test.in...) if err != nil { if test.err == "" { t.Errorf("got error scanning (%q, %q): %q", test.format, test.text, err) - } else if strings.Index(err.Error(), test.err) < 0 { + } else if !strings.Contains(err.Error(), test.err) { t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err) } continue @@ -545,11 +534,11 @@ func testScanfMulti(name string, t *testing.T) { } func TestScanfMulti(t *testing.T) { - testScanfMulti("StringReader", t) -} - -func TestMyReaderScanfMulti(t *testing.T) { - testScanfMulti("myStringReader", t) + for _, r := range readers { + t.Run(r.name, func(t *testing.T) { + testScanfMulti(t, r.f) + }) + } } func TestScanMultiple(t *testing.T) { @@ -613,7 +602,7 @@ func TestScanNotPointer(t *testing.T) { _, err := Fscan(r, a) if err == nil { t.Error("expected error scanning non-pointer") - } else if strings.Index(err.Error(), "pointer") < 0 { + } else if !strings.Contains(err.Error(), "pointer") { t.Errorf("expected pointer error scanning non-pointer, got: %s", err) } } @@ -623,7 +612,7 @@ func TestScanlnNoNewline(t *testing.T) { _, err := Sscanln("1 x\n", &a) if err == nil { t.Error("expected error scanning string missing newline") - } else if strings.Index(err.Error(), "newline") < 0 { + } else if !strings.Contains(err.Error(), "newline") { t.Errorf("expected newline error scanning string missing newline, got: %s", err) } } @@ -634,7 +623,7 @@ func TestScanlnWithMiddleNewline(t *testing.T) { _, err := Fscanln(r, &a, &b) if err == nil { t.Error("expected error scanning string with extra newline") - } else if strings.Index(err.Error(), "newline") < 0 { + } else if !strings.Contains(err.Error(), "newline") { t.Errorf("expected newline error scanning string with extra newline, got: %s", err) } } @@ -767,7 +756,7 @@ func TestUnreadRuneWithBufio(t *testing.T) { type TwoLines string -// Scan attempts to read two lines into the object. Scanln should prevent this +// Scan attempts to read two lines into the object. Scanln should prevent this // because it stops at newline; Scan and Scanf should be fine. func (t *TwoLines) Scan(state ScanState, verb rune) error { chars := make([]rune, 0, 100) @@ -824,20 +813,10 @@ 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) -} - // TestLineByLineFscanf tests that Fscanf does not read past newline. Issue // 3481. func TestLineByLineFscanf(t *testing.T) { - r := &simpleReader{strings.NewReader("1\n2\n")} + r := struct{ io.Reader }{strings.NewReader("1\n2\n")} var i, j int n, err := Fscanf(r, "%v\n", &i) if n != 1 || err != nil { @@ -1001,6 +980,18 @@ func BenchmarkScanRecursiveInt(b *testing.B) { } } +func BenchmarkScanRecursiveIntReaderWrapper(b *testing.B) { + b.ResetTimer() + ints := makeInts(intCount) + var r RecursiveInt + for i := b.N - 1; i >= 0; i-- { + buf := struct{ io.Reader }{strings.NewReader(string(ints))} + b.StartTimer() + Fscan(buf, &r) + b.StopTimer() + } +} + // Issue 9124. // %x on bytes couldn't handle non-space bytes terminating the scan. func TestHexBytes(t *testing.T) { |