diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:11:55 +0200 |
commit | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/pkg/fmt | |
parent | 28592ee1ea1f5cdffcf85472f9de0285d928cf12 (diff) | |
download | golang-80f18fc933cf3f3e829c5455a1023d69f7b86e52.tar.gz |
Imported Upstream version 60
Diffstat (limited to 'src/pkg/fmt')
-rw-r--r-- | src/pkg/fmt/Makefile | 14 | ||||
-rw-r--r-- | src/pkg/fmt/doc.go | 181 | ||||
-rw-r--r-- | src/pkg/fmt/fmt_test.go | 738 | ||||
-rw-r--r-- | src/pkg/fmt/format.go | 447 | ||||
-rw-r--r-- | src/pkg/fmt/print.go | 993 | ||||
-rw-r--r-- | src/pkg/fmt/scan.go | 1114 | ||||
-rw-r--r-- | src/pkg/fmt/scan_test.go | 921 | ||||
-rw-r--r-- | src/pkg/fmt/stringer_test.go | 61 |
8 files changed, 0 insertions, 4469 deletions
diff --git a/src/pkg/fmt/Makefile b/src/pkg/fmt/Makefile deleted file mode 100644 index 44b48bc67..000000000 --- a/src/pkg/fmt/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2009 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. - -include ../../Make.inc - -TARG=fmt -GOFILES=\ - doc.go\ - format.go\ - print.go\ - scan.go\ - -include ../../Make.pkg diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go deleted file mode 100644 index 35a11e19f..000000000 --- a/src/pkg/fmt/doc.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2009 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. - -/* - Package fmt implements formatted I/O with functions analogous - to C's printf and scanf. The format 'verbs' are derived from C's but - are simpler. - - Printing: - - The verbs: - - General: - %v the value in a default format. - when printing structs, the plus flag (%+v) adds field names - %#v a Go-syntax representation of the value - %T a Go-syntax representation of the type of the value - %% a literal percent sign; consumes no value - - Boolean: - %t the word true or false - Integer: - %b base 2 - %c the character represented by the corresponding Unicode code point - %d base 10 - %o base 8 - %q a single-quoted character literal safely escaped with Go syntax. - %x base 16, with lower-case letters for a-f - %X base 16, with upper-case letters for A-F - %U Unicode format: U+1234; same as "U+%04X" - Floating-point and complex constituents: - %b decimalless scientific notation with exponent a power - of two, in the manner of strconv.Ftoa32, e.g. -123456p-78 - %e scientific notation, e.g. -1234.456e+78 - %E scientific notation, e.g. -1234.456E+78 - %f decimal point but no exponent, e.g. 123.456 - %g whichever of %e or %f produces more compact output - %G whichever of %E or %f produces more compact output - String and slice of bytes: - %s the uninterpreted bytes of the string or slice - %q a double-quoted string safely escaped with Go syntax - %x base 16, lower-case, two characters per byte - %X base 16, upper-case, two characters per byte - Pointer: - %p base 16 notation, with leading 0x - - There is no 'u' flag. Integers are printed unsigned if they have unsigned type. - Similarly, there is no need to specify the size of the operand (int8, int64). - - The width and precision control formatting and are in units of Unicode - code points. (This differs from C's printf where the units are numbers - of bytes.) Either or both of the flags may be replaced with the - character '*', causing their values to be obtained from the next - operand, which must be of type int. - - For numeric values, width sets the width of the field and precision - sets the number of places after the decimal, if appropriate. For - example, the format %6.2f prints 123.45. - - For strings, width is the minimum number of characters to output, - padding with spaces if necessary, and precision is the maximum - number of characters to output, truncating if necessary. - - Other flags: - + always print a sign for numeric values; - guarantee ASCII-only output for %q (%+q) - - pad with spaces on the right rather than the left (left-justify the field) - # alternate format: add leading 0 for octal (%#o), 0x for hex (%#x); - 0X for hex (%#X); suppress 0x for %p (%#p); - print a raw (backquoted) string if possible for %q (%#q); - write e.g. U+0078 'x' if the character is printable for %U (%#U). - ' ' (space) leave a space for elided sign in numbers (% d); - put spaces between bytes printing strings or slices in hex (% x, % X) - 0 pad with leading zeros rather than spaces - - For each Printf-like function, there is also a Print function - that takes no format and is equivalent to saying %v for every - operand. Another variant Println inserts blanks between - operands and appends a newline. - - Regardless of the verb, if an operand is an interface value, - the internal concrete value is used, not the interface itself. - Thus: - var i interface{} = 23 - fmt.Printf("%v\n", i) - will print 23. - - If an operand implements interface Formatter, that interface - can be used for fine control of formatting. - - If an operand implements method String() string that method - will be used to convert the object to a string, which will then - be formatted as required by the verb (if any). To avoid - recursion in cases such as - type X int - func (x X) String() string { return Sprintf("%d", x) } - cast the value before recurring: - func (x X) String() string { return Sprintf("%d", int(x)) } - - Format errors: - - If an invalid argument is given for a verb, such as providing - a string to %d, the generated string will contain a - description of the problem, as in these examples: - - Wrong type or unknown verb: %!verb(type=value) - Printf("%d", hi): %!d(string=hi) - Too many arguments: %!(EXTRA type=value) - Printf("hi", "guys"): hi%!(EXTRA string=guys) - Too few arguments: %!verb(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 - - All errors begin with the string "%!" followed sometimes - by a single character (the verb) and end with a parenthesized - description. - - Scanning: - - An analogous set of functions scans formatted text to yield - values. Scan, Scanf and Scanln read from os.Stdin; Fscan, - Fscanf and Fscanln read from a specified os.Reader; Sscan, - Sscanf and Sscanln read from an argument string. Scanln, - Fscanln and Sscanln stop scanning at a newline and require that - the items be followed by one; Sscanf, Fscanf and Sscanf require - newlines in the input to match newlines in the format; the other - routines treat newlines as spaces. - - Scanf, Fscanf, and Sscanf parse the arguments according to a - format string, analogous to that of Printf. For example, %x - will scan an integer as a hexadecimal number, and %v will scan - the default representation format for the value. - - The formats behave analogously to those of Printf with the - following exceptions: - - %p is not implemented - %T is not implemented - %e %E %f %F %g %G are all equivalent and scan any floating point or complex value - %s and %v on strings scan a space-delimited token - - The familiar base-setting prefixes 0 (octal) and 0x - (hexadecimal) are accepted when scanning integers without a - format or with the %v verb. - - Width is interpreted in the input text (%5s means at most - five runes of input will be read to scan a string) but there - is no syntax for scanning with a precision (no %5.2f, just - %5f). - - When scanning with a format, all non-empty runs of space - characters (except newline) are equivalent to a single - space in both the format and the input. With that proviso, - text in the format string must match the input text; scanning - stops if it does not, with the return value of the function - indicating the number of arguments scanned. - - In all the scanning functions, if an operand implements method - Scan (that is, it implements the Scanner interface) that - method will be used to scan the text for that operand. Also, - if the number of arguments scanned is less than the number of - arguments provided, an error is returned. - - All arguments to be scanned must be either pointers to basic - types or implementations of the Scanner interface. - - Note: Fscan etc. can read one character (rune) past the input - they return, which means that a loop calling a scan routine - may skip some of the input. This is usually a problem only - when there is no space between input values. If the reader - provided to Fscan implements ReadRune, that method will be used - to read characters. If the reader also implements UnreadRune, - that method will be used to save the character and successive - calls will not lose data. To attach ReadRune and UnreadRune - methods to a reader without that capability, use - bufio.NewReader. -*/ -package fmt diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go deleted file mode 100644 index 9a8024528..000000000 --- a/src/pkg/fmt/fmt_test.go +++ /dev/null @@ -1,738 +0,0 @@ -// Copyright 2009 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. - -package fmt_test - -import ( - . "fmt" - "io" - "math" - "runtime" // for the malloc count test only - "strings" - "testing" -) - -type ( - renamedBool bool - renamedInt int - renamedInt8 int8 - renamedInt16 int16 - renamedInt32 int32 - renamedInt64 int64 - renamedUint uint - renamedUint8 uint8 - renamedUint16 uint16 - renamedUint32 uint32 - renamedUint64 uint64 - renamedUintptr uintptr - renamedString string - renamedBytes []byte - renamedFloat32 float32 - renamedFloat64 float64 - renamedComplex64 complex64 - renamedComplex128 complex128 -) - -func TestFmtInterface(t *testing.T) { - var i1 interface{} - i1 = "abc" - s := Sprintf("%s", i1) - if s != "abc" { - t.Errorf(`Sprintf("%%s", empty("abc")) = %q want %q`, s, "abc") - } -} - - -const b32 uint32 = 1<<32 - 1 -const b64 uint64 = 1<<64 - 1 - -var array = []int{1, 2, 3, 4, 5} -var iarray = []interface{}{1, "hello", 2.5, nil} - -type A struct { - i int - j uint - s string - x []int -} - -type I int - -func (i I) String() string { return Sprintf("<%d>", int(i)) } - -type B struct { - i I - j int -} - -type C struct { - i int - B -} - -type F int - -func (f F) Format(s State, c int) { - Fprintf(s, "<%c=F(%d)>", c, int(f)) -} - -type G int - -func (g G) GoString() string { - return Sprintf("GoString(%d)", int(g)) -} - -type S struct { - f F // a struct field that Formats - g G // a struct field that GoStrings -} - -// A type with a String method with pointer receiver for testing %p -type P int - -var pValue P - -func (p *P) String() string { - return "String(p)" -} - -var b byte - -var fmttests = []struct { - fmt string - val interface{} - out string -}{ - {"%d", 12345, "12345"}, - {"%v", 12345, "12345"}, - {"%t", true, "true"}, - - // basic string - {"%s", "abc", "abc"}, - {"%x", "abc", "616263"}, - {"%x", "xyz", "78797a"}, - {"%X", "xyz", "78797A"}, - {"%q", "abc", `"abc"`}, - - // basic bytes - {"%s", []byte("abc"), "abc"}, - {"%x", []byte("abc"), "616263"}, - {"% x", []byte("abc\xff"), "61 62 63 ff"}, - {"% X", []byte("abc\xff"), "61 62 63 FF"}, - {"%x", []byte("xyz"), "78797a"}, - {"%X", []byte("xyz"), "78797A"}, - {"%q", []byte("abc"), `"abc"`}, - - // 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", "abc\xffdef", `"abc\xffdef"`}, - {"%q", "\u263a", `"☺"`}, - {"%+q", "\u263a", `"\u263a"`}, - {"%q", "\U0010ffff", `"\U0010ffff"`}, - - // 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", '"', `'"'`}, - {"%q", '\'', `'\''`}, - {"%q", "\u263a", `"☺"`}, - {"%+q", "\u263a", `"\u263a"`}, - - // width - {"%5s", "abc", " abc"}, - {"%2s", "\u263a", " ☺"}, - {"%-5s", "abc", "abc "}, - {"%-8q", "abc", `"abc" `}, - {"%05s", "abc", "00abc"}, - {"%08q", "abc", `000"abc"`}, - {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}, - {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"}, - {"%.5s", "日本語日本語", "日本語日本"}, - {"%.5s", []byte("日本語日本語"), "日本語日本"}, - {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`}, - {"%.3q", "日本語日本語", `"日本語"`}, - {"%.3q", []byte("日本語日本語"), `"日本語"`}, - {"%10.1q", "日本語日本語", ` "日"`}, - - // integers - {"%d", 12345, "12345"}, - {"%d", -12345, "-12345"}, - {"%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"}, - - // 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", '\n', `U+000A`}, - {"%#U", '\n', `U+000A`}, - {"%U", 'x', `U+0078`}, - {"%#U", 'x', `U+0078 'x'`}, - {"%U", '\u263a', `U+263A`}, - {"%#U", '\u263a', `U+263A '☺'`}, - - // floats - {"%+.3e", 0.0, "+0.000e+00"}, - {"%+.3e", 1.0, "+1.000e+00"}, - {"%+.3f", -1.0, "-1.000"}, - {"% .3E", -1.0, "-1.000E+00"}, - {"% .3e", 1.0, " 1.000e+00"}, - {"%+.3g", 0.0, "+0"}, - {"%+.3g", 1.0, "+1"}, - {"%+.3g", -1.0, "-1"}, - {"% .3g", -1.0, "-1"}, - {"% .3g", 1.0, " 1"}, - - // complex values - {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"}, - {"%+.3f", 0i, "(+0.000+0.000i)"}, - {"%+.3g", 0i, "(+0+0i)"}, - {"%+.3e", 1 + 2i, "(+1.000e+00+2.000e+00i)"}, - {"%+.3f", 1 + 2i, "(+1.000+2.000i)"}, - {"%+.3g", 1 + 2i, "(+1+2i)"}, - {"%.3e", 0i, "(0.000e+00+0.000e+00i)"}, - {"%.3f", 0i, "(0.000+0.000i)"}, - {"%.3g", 0i, "(0+0i)"}, - {"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"}, - {"%.3f", 1 + 2i, "(1.000+2.000i)"}, - {"%.3g", 1 + 2i, "(1+2i)"}, - {"%.3e", -1 - 2i, "(-1.000e+00-2.000e+00i)"}, - {"%.3f", -1 - 2i, "(-1.000-2.000i)"}, - {"%.3g", -1 - 2i, "(-1-2i)"}, - {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"}, - {"%+.3g", complex64(1 + 2i), "(+1+2i)"}, - {"%+.3g", complex128(1 + 2i), "(+1+2i)"}, - - // erroneous formats - {"", 2, "%!(EXTRA int=2)"}, - {"%d", "hello", "%!d(string=hello)"}, - - // 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"}, - {"%e", -7.0, "-7.000000e+00"}, - {"%e", -1e-9, "-1.000000e-09"}, - {"%f", 1234.5678e3, "1234567.800000"}, - {"%f", 1234.5678e-8, "0.000012"}, - {"%f", -7.0, "-7.000000"}, - {"%f", -1e-9, "-0.000000"}, - {"%g", 1234.5678e3, "1.2345678e+06"}, - {"%g", float32(1234.5678e3), "1.2345678e+06"}, - {"%g", 1234.5678e-8, "1.2345678e-05"}, - {"%g", -7.0, "-7"}, - {"%g", -1e-9, "-1e-09"}, - {"%g", float32(-1e-9), "-1e-09"}, - {"%E", 1.0, "1.000000E+00"}, - {"%E", 1234.5678e3, "1.234568E+06"}, - {"%E", 1234.5678e-8, "1.234568E-05"}, - {"%E", -7.0, "-7.000000E+00"}, - {"%E", -1e-9, "-1.000000E-09"}, - {"%G", 1234.5678e3, "1.2345678E+06"}, - {"%G", float32(1234.5678e3), "1.2345678E+06"}, - {"%G", 1234.5678e-8, "1.2345678E-05"}, - {"%G", -7.0, "-7"}, - {"%G", -1e-9, "-1E-09"}, - {"%G", float32(-1e-9), "-1E-09"}, - {"%c", 'x', "x"}, - {"%c", 0xe4, "ä"}, - {"%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 "}, - {"%20c", 'x', " x"}, - {"%-20c", 'x', "x "}, - {"%20.6e", 1.2345e3, " 1.234500e+03"}, - {"%20.6e", 1.2345e-3, " 1.234500e-03"}, - {"%20e", 1.2345e3, " 1.234500e+03"}, - {"%20e", 1.2345e-3, " 1.234500e-03"}, - {"%20.8e", 1.2345e3, " 1.23450000e+03"}, - {"%20f", 1.23456789e3, " 1234.567890"}, - {"%20f", 1.23456789e-3, " 0.001235"}, - {"%20f", 12345678901.23456789, " 12345678901.234568"}, - {"%-20f", 1.23456789e3, "1234.567890 "}, - {"%20.8f", 1.23456789e3, " 1234.56789000"}, - {"%20.8f", 1.23456789e-3, " 0.00123457"}, - {"%g", 1.23456789e3, "1234.56789"}, - {"%g", 1.23456789e-3, "0.00123456789"}, - {"%g", 1.23456789e20, "1.23456789e+20"}, - {"%20e", math.Inf(1), " +Inf"}, - {"%-20f", math.Inf(-1), "-Inf "}, - {"%20g", math.NaN(), " NaN"}, - - // arrays - {"%v", array, "[1 2 3 4 5]"}, - {"%v", iarray, "[1 hello 2.5 <nil>]"}, - {"%v", &array, "&[1 2 3 4 5]"}, - {"%v", &iarray, "&[1 hello 2.5 <nil>]"}, - - // 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]}`}, - {"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`}, - - // +v on structs with Stringable items - {"%+v", B{1, 2}, `{i:<1> j:2}`}, - {"%+v", C{1, B{2, 3}}, `{i:1 B:{i:<2> j:3}}`}, - - // q on Stringable items - {"%s", I(23), `<23>`}, - {"%q", I(23), `"<23>"`}, - {"%x", I(23), `3c32333e`}, - {"%d", I(23), `%!d(string=<23>)`}, - - // 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", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, - {"%#v", make(chan int), "(chan int)(0xPTR)"}, - {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, - {"%#v", 1000000000, "1000000000"}, - {"%#v", map[string]int{"a": 1, "b": 2}, `map[string] int{"a":1, "b":2}`}, - {"%#v", map[string]B{"a": {1, 2}, "b": {3, 4}}, `map[string] fmt_test.B{"a":fmt_test.B{i:1, j:2}, "b":fmt_test.B{i:3, j:4}}`}, - {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`}, - - // slices with other formats - {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, - {"%x", []int{1, 2, 15}, `[1 2 f]`}, - {"%d", []int{1, 2, 15}, `[1 2 15]`}, - {"%d", []byte{1, 2, 15}, `[1 2 15]`}, - {"%q", []string{"a", "b"}, `["a" "b"]`}, - - // renamings - {"%v", renamedBool(true), "true"}, - {"%d", renamedBool(true), "%!d(fmt_test.renamedBool=true)"}, - {"%o", renamedInt(8), "10"}, - {"%d", renamedInt8(-9), "-9"}, - {"%v", renamedInt16(10), "10"}, - {"%v", renamedInt32(-11), "-11"}, - {"%X", renamedInt64(255), "FF"}, - {"%v", renamedUint(13), "13"}, - {"%o", renamedUint8(14), "16"}, - {"%X", renamedUint16(15), "F"}, - {"%d", renamedUint32(16), "16"}, - {"%X", renamedUint64(17), "11"}, - {"%o", renamedUintptr(18), "22"}, - {"%x", renamedString("thing"), "7468696e67"}, - {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`}, - {"%q", renamedBytes([]byte("hello")), `"hello"`}, - {"%v", renamedFloat32(22), "22"}, - {"%v", renamedFloat64(33), "33"}, - {"%v", renamedComplex64(3 + 4i), "(3+4i)"}, - {"%v", renamedComplex128(4 - 3i), "(4-3i)"}, - - // Formatter - {"%x", F(1), "<x=F(1)>"}, - {"%x", G(2), "2"}, - {"%+v", S{F(4), G(5)}, "{f:<v=F(4)> g:5}"}, - - // GoStringer - {"%#v", G(6), "GoString(6)"}, - {"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"}, - - // %T - {"%T", (4 - 3i), "complex128"}, - {"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"}, - {"%T", intVal, "int"}, - {"%6T", &intVal, " *int"}, - - // %p - {"p0=%p", new(int), "p0=0xPTR"}, - {"p1=%s", &pValue, "p1=String(p)"}, // String method... - {"p2=%p", &pValue, "p2=0xPTR"}, // ... not called with %p - {"p4=%#p", new(int), "p4=PTR"}, - - // %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 - - // erroneous things - {"%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)"}, -} - -func TestSprintf(t *testing.T) { - for _, tt := range fmttests { - s := Sprintf(tt.fmt, tt.val) - if i := strings.Index(tt.out, "PTR"); i >= 0 { - j := i - for ; j < len(s); j++ { - c := s[j] - if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') { - break - } - } - s = s[0:i] + "PTR" + s[j:] - } - if s != tt.out { - if _, ok := tt.val.(string); ok { - // Don't requote the already-quoted strings. - // It's too confusing to read the errors. - t.Errorf("Sprintf(%q, %q) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out) - } else { - t.Errorf("Sprintf(%q, %v) = %q want %q", tt.fmt, tt.val, s, tt.out) - } - } - } -} - -func BenchmarkSprintfEmpty(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("") - } -} - -func BenchmarkSprintfString(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%s", "hello") - } -} - -func BenchmarkSprintfInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%d", 5) - } -} - -func BenchmarkSprintfIntInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%d %d", 5, 6) - } -} - -func BenchmarkSprintfPrefixedInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6) - } -} - -func TestCountMallocs(t *testing.T) { - if testing.Short() { - return - } - mallocs := 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { - Sprintf("") - } - mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100) - mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { - Sprintf("xxx") - } - mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100) - mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { - Sprintf("%x", i) - } - mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100) - mallocs = 0 - runtime.MemStats.Mallocs - for i := 0; i < 100; i++ { - Sprintf("%x %x", i, i) - } - mallocs += runtime.MemStats.Mallocs - Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100) -} - -type flagPrinter struct{} - -func (*flagPrinter) Format(f State, c int) { - s := "%" - for i := 0; i < 128; i++ { - if f.Flag(i) { - s += string(i) - } - } - if w, ok := f.Width(); ok { - s += Sprintf("%d", w) - } - if p, ok := f.Precision(); ok { - s += Sprintf(".%d", p) - } - s += string(c) - io.WriteString(f, "["+s+"]") -} - -var flagtests = []struct { - in string - out string -}{ - {"%a", "[%a]"}, - {"%-a", "[%-a]"}, - {"%+a", "[%+a]"}, - {"%#a", "[%#a]"}, - {"% a", "[% a]"}, - {"%0a", "[%0a]"}, - {"%1.2a", "[%1.2a]"}, - {"%-1.2a", "[%-1.2a]"}, - {"%+1.2a", "[%+1.2a]"}, - {"%-+1.2a", "[%+-1.2a]"}, - {"%-+1.2abc", "[%+-1.2a]bc"}, - {"%-1.2abc", "[%-1.2a]bc"}, -} - -func TestFlagParser(t *testing.T) { - var flagprinter flagPrinter - for _, tt := range flagtests { - s := Sprintf(tt.in, &flagprinter) - if s != tt.out { - t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out) - } - } -} - -func TestStructPrinter(t *testing.T) { - var s struct { - a string - b string - c int - } - s.a = "abc" - s.b = "def" - s.c = 123 - var tests = []struct { - fmt string - out string - }{ - {"%v", "{abc def 123}"}, - {"%+v", "{a:abc b:def c:123}"}, - } - for _, tt := range tests { - out := Sprintf(tt.fmt, s) - if out != tt.out { - t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out) - } - } -} - -// Check map printing using substrings so we don't depend on the print order. -func presentInMap(s string, a []string, t *testing.T) { - for i := 0; i < len(a); i++ { - loc := strings.Index(s, a[i]) - if loc < 0 { - t.Errorf("map print: expected to find %q in %q", a[i], s) - } - // make sure the match ends here - loc += len(a[i]) - if loc >= len(s) || (s[loc] != ' ' && s[loc] != ']') { - t.Errorf("map print: %q not properly terminated in %q", a[i], s) - } - } -} - -func TestMapPrinter(t *testing.T) { - m0 := make(map[int]string) - s := Sprint(m0) - if s != "map[]" { - t.Errorf("empty map printed as %q not %q", s, "map[]") - } - m1 := map[int]string{1: "one", 2: "two", 3: "three"} - a := []string{"1:one", "2:two", "3:three"} - presentInMap(Sprintf("%v", m1), a, t) - presentInMap(Sprint(m1), a, t) -} - -func TestEmptyMap(t *testing.T) { - const emptyMapStr = "map[]" - var m map[string]int - s := Sprint(m) - if s != emptyMapStr { - t.Errorf("nil map printed as %q not %q", s, emptyMapStr) - } - m = make(map[string]int) - s = Sprint(m) - if s != emptyMapStr { - t.Errorf("empty map printed as %q not %q", s, emptyMapStr) - } -} - -// Check that Sprint (and hence Print, Fprint) puts spaces in the right places, -// that is, between arg pairs in which neither is a string. -func TestBlank(t *testing.T) { - got := Sprint("<", 1, ">:", 1, 2, 3, "!") - expect := "<1>:1 2 3!" - if got != expect { - t.Errorf("got %q expected %q", got, expect) - } -} - -// Check that Sprintln (and hence Println, Fprintln) puts spaces in the right places, -// that is, between all arg pairs. -func TestBlankln(t *testing.T) { - got := Sprintln("<", 1, ">:", 1, 2, 3, "!") - expect := "< 1 >: 1 2 3 !\n" - if got != expect { - t.Errorf("got %q expected %q", got, expect) - } -} - - -// Check Formatter with Sprint, Sprintln, Sprintf -func TestFormatterPrintln(t *testing.T) { - f := F(1) - expect := "<v=F(1)>\n" - s := Sprint(f, "\n") - if s != expect { - t.Errorf("Sprint wrong with Formatter: expected %q got %q", expect, s) - } - s = Sprintln(f) - if s != expect { - t.Errorf("Sprintln wrong with Formatter: expected %q got %q", expect, s) - } - s = Sprintf("%v\n", f) - if s != expect { - t.Errorf("Sprintf wrong with Formatter: expected %q got %q", expect, s) - } -} - -func args(a ...interface{}) []interface{} { return a } - -var startests = []struct { - fmt string - in []interface{} - out string -}{ - {"%*d", args(4, 42), " 42"}, - {"%.*d", args(4, 42), "0042"}, - {"%*.*d", args(8, 4, 42), " 0042"}, - {"%0*d", args(4, 42), "0042"}, - {"%-*d", args(4, 42), "42 "}, - - // erroneous - {"%*d", args(nil, 42), "%!(BADWIDTH)42"}, - {"%.*d", args(nil, 42), "%!(BADPREC)42"}, - {"%*d", args(5, "foo"), "%!d(string= foo)"}, - {"%*% %d", args(20, 5), "% 5"}, - {"%*", args(4), "%!(NOVERB)"}, - {"%*d", args(int32(4), 42), "%!(BADWIDTH)42"}, -} - -func TestWidthAndPrecision(t *testing.T) { - for _, tt := range startests { - s := Sprintf(tt.fmt, tt.in...) - if s != tt.out { - t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out) - } - } -} - -// A type that panics in String. -type Panic struct { - message interface{} -} - -// Value receiver. -func (p Panic) GoString() string { - panic(p.message) -} - -// Value receiver. -func (p Panic) String() string { - panic(p.message) -} - -// A type that panics in Format. -type PanicF struct { - message interface{} -} - -// Value receiver. -func (p PanicF) Format(f State, c int) { - panic(p.message) -} - -var panictests = []struct { - fmt string - in interface{} - out string -}{ - // String - {"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"}, - {"%d", Panic{3}, "%d(PANIC=3)"}, - // GoString - {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"}, - {"%#v", Panic{3}, "%v(PANIC=3)"}, - // Format - {"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case - {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"}, - {"%s", PanicF{3}, "%s(PANIC=3)"}, -} - -func TestPanics(t *testing.T) { - for _, tt := range panictests { - s := Sprintf(tt.fmt, tt.in) - if s != tt.out { - t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out) - } - } -} diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go deleted file mode 100644 index bec55f75b..000000000 --- a/src/pkg/fmt/format.go +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2009 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. - -package fmt - -import ( - "bytes" - "strconv" - "unicode" - "utf8" -) - -const ( - nByte = 64 - - ldigits = "0123456789abcdef" - udigits = "0123456789ABCDEF" -) - -const ( - signed = true - unsigned = false -) - -var padZeroBytes = make([]byte, nByte) -var padSpaceBytes = make([]byte, nByte) - -var newline = []byte{'\n'} - -func init() { - for i := 0; i < nByte; i++ { - padZeroBytes[i] = '0' - padSpaceBytes[i] = ' ' - } -} - -// A fmt is the raw formatter used by Printf etc. -// It prints into a bytes.Buffer that must be set up externally. -type fmt struct { - intbuf [nByte]byte - buf *bytes.Buffer - // width, precision - wid int - prec int - // flags - widPresent bool - precPresent bool - minus bool - plus bool - sharp bool - space bool - unicode bool - uniQuote bool // Use 'x'= prefix for %U if printable. - zero bool -} - -func (f *fmt) clearflags() { - f.wid = 0 - f.widPresent = false - f.prec = 0 - f.precPresent = false - f.minus = false - f.plus = false - f.sharp = false - f.space = false - f.unicode = false - f.uniQuote = false - f.zero = false -} - -func (f *fmt) init(buf *bytes.Buffer) { - f.buf = buf - f.clearflags() -} - -// Compute 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 -} - -// Generate 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 - } -} - -// Append b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus) -// clear flags afterwards. -func (f *fmt) pad(b []byte) { - var padding []byte - var left, right int - if f.widPresent && f.wid != 0 { - padding, left, right = f.computePadding(len(b)) - } - if left > 0 { - f.writePadding(left, padding) - } - f.buf.Write(b) - if right > 0 { - f.writePadding(right, padding) - } -} - -// append s to buf, padded on left (w > 0) or right (w < 0 or f.minus). -// clear flags afterwards. -func (f *fmt) padString(s string) { - var padding []byte - var left, right int - if f.widPresent && f.wid != 0 { - padding, left, right = f.computePadding(utf8.RuneCountInString(s)) - } - if left > 0 { - f.writePadding(left, padding) - } - f.buf.WriteString(s) - if right > 0 { - f.writePadding(right, padding) - } -} - -func putint(buf []byte, base, val uint64, digits string) int { - i := len(buf) - 1 - for val >= base { - buf[i] = digits[val%base] - i-- - val /= base - } - buf[i] = digits[val] - return i - 1 -} - -// fmt_boolean formats a boolean. -func (f *fmt) fmt_boolean(v bool) { - if v { - f.padString("true") - } else { - 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) { - var buf []byte = f.intbuf[0:] - negative := signedness == signed && a < 0 - if negative { - a = -a - } - - // two ways to ask for extra leading zero digits: %.3d or %03d. - // apparently the first cancels the second. - prec := 0 - if f.precPresent { - prec = f.prec - f.zero = false - } else if f.zero && f.widPresent && !f.minus && f.wid > 0 { - 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. - i := len(f.intbuf) - ua := uint64(a) - for ua >= base { - i-- - buf[i] = digits[ua%base] - ua /= base - } - i-- - buf[i] = digits[ua] - for i > 0 && prec > nByte-i { - i-- - buf[i] = '0' - } - - // Various prefixes: 0x, -, etc. - if f.sharp { - switch base { - case 8: - if buf[i] != '0' { - i-- - buf[i] = '0' - } - case 16: - i-- - buf[i] = 'x' + digits[10] - 'a' - i-- - buf[i] = '0' - } - } - if f.unicode { - i-- - buf[i] = '+' - i-- - buf[i] = 'U' - } - - if negative { - i-- - buf[i] = '-' - } else if f.plus { - i-- - buf[i] = '+' - } else if f.space { - i-- - 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 <= unicode.MaxRune && unicode.IsPrint(int(a)) { - runeWidth := utf8.RuneLen(int(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:], int(a)) - j += runeWidth - buf[j] = '\'' - } - - f.pad(buf[i:]) -} - -// 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) { - n := f.prec - for i := range s { - if n == 0 { - s = s[:i] - break - } - n-- - } - } - return s -} - -// fmt_s formats a string. -func (f *fmt) fmt_s(s string) { - s = f.truncate(s) - f.padString(s) -} - -// fmt_sx formats a string as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sx(s string) { - t := "" - for i := 0; i < len(s); i++ { - if i > 0 && f.space { - t += " " - } - v := s[i] - t += string(ldigits[v>>4]) - t += string(ldigits[v&0xF]) - } - f.padString(t) -} - -// fmt_sX formats a string as an uppercase hexadecimal encoding of its bytes. -func (f *fmt) fmt_sX(s string) { - t := "" - for i := 0; i < len(s); i++ { - if i > 0 && f.space { - t += " " - } - v := s[i] - t += string(udigits[v>>4]) - t += string(udigits[v&0xF]) - } - f.padString(t) -} - -// fmt_q formats a string as a double-quoted, escaped Go string constant. -func (f *fmt) fmt_q(s string) { - s = f.truncate(s) - var quoted string - if f.sharp && strconv.CanBackquote(s) { - quoted = "`" + s + "`" - } else { - if f.plus { - quoted = strconv.QuoteToASCII(s) - } else { - quoted = strconv.Quote(s) - } - } - f.padString(quoted) -} - -// fmt_qc formats the 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 int64) { - var quoted string - if f.plus { - quoted = strconv.QuoteRuneToASCII(int(c)) - } else { - quoted = strconv.QuoteRune(int(c)) - } - f.padString(quoted) -} - -// floating-point - -func doPrec(f *fmt, def int) int { - if f.precPresent { - return f.prec - } - return def -} - -// Add a plus sign or space to the floating-point string representation if missing and required. -func (f *fmt) plusSpace(s string) { - if s[0] != '-' { - if f.plus { - s = "+" + s - } else if f.space { - s = " " + s - } - } - f.padString(s) -} - -// fmt_e64 formats a float64 in the form -1.23e+12. -func (f *fmt) fmt_e64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'e', doPrec(f, 6))) } - -// fmt_E64 formats a float64 in the form -1.23E+12. -func (f *fmt) fmt_E64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'E', doPrec(f, 6))) } - -// fmt_f64 formats a float64 in the form -1.23. -func (f *fmt) fmt_f64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'f', doPrec(f, 6))) } - -// fmt_g64 formats a float64 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'g', doPrec(f, -1))) } - -// fmt_g64 formats a float64 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'G', doPrec(f, -1))) } - -// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb64(v float64) { f.plusSpace(strconv.Ftoa64(v, 'b', 0)) } - -// float32 -// cannot defer to float64 versions -// because it will get rounding wrong in corner cases. - -// fmt_e32 formats a float32 in the form -1.23e+12. -func (f *fmt) fmt_e32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'e', doPrec(f, 6))) } - -// fmt_E32 formats a float32 in the form -1.23E+12. -func (f *fmt) fmt_E32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'E', doPrec(f, 6))) } - -// fmt_f32 formats a float32 in the form -1.23. -func (f *fmt) fmt_f32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'f', doPrec(f, 6))) } - -// fmt_g32 formats a float32 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'g', doPrec(f, -1))) } - -// fmt_G32 formats a float32 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f, -1))) } - -// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) } - -// fmt_c64 formats a complex64 according to the verb. -func (f *fmt) fmt_c64(v complex64, verb int) { - f.buf.WriteByte('(') - r := real(v) - for i := 0; ; i++ { - switch verb { - case 'e': - f.fmt_e32(r) - case 'E': - f.fmt_E32(r) - case 'f': - f.fmt_f32(r) - case 'g': - f.fmt_g32(r) - case 'G': - f.fmt_G32(r) - } - if i != 0 { - break - } - f.plus = true - r = imag(v) - } - f.buf.Write(irparenBytes) -} - -// fmt_c128 formats a complex128 according to the verb. -func (f *fmt) fmt_c128(v complex128, verb int) { - f.buf.WriteByte('(') - r := real(v) - for i := 0; ; i++ { - switch verb { - case 'e': - f.fmt_e64(r) - case 'E': - f.fmt_E64(r) - case 'f': - f.fmt_f64(r) - case 'g': - f.fmt_g64(r) - case 'G': - f.fmt_G64(r) - } - if i != 0 { - break - } - f.plus = true - r = imag(v) - } - f.buf.Write(irparenBytes) -} diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go deleted file mode 100644 index 5c083e5e9..000000000 --- a/src/pkg/fmt/print.go +++ /dev/null @@ -1,993 +0,0 @@ -// Copyright 2009 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. - -package fmt - -import ( - "bytes" - "io" - "os" - "reflect" - "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[") - missingBytes = []byte("(MISSING)") - panicBytes = []byte("(PANIC=") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - widthBytes = []byte("%!(BADWIDTH)") - precBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") -) - -// State represents the printer state passed to custom formatters. -// It provides access to the io.Writer interface plus information about -// 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 os.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. - Precision() (prec int, ok bool) - - // Flag returns whether the flag c, a character, has been set. - Flag(c int) bool -} - -// Formatter is the interface implemented by values with a custom formatter. -// The implementation of Format may call Sprintf or Fprintf(f) etc. -// to generate its output. -type Formatter interface { - Format(f State, c int) -} - -// Stringer is implemented by any value that has a String method(), -// which defines the ``native'' format for that value. -// The String method is used to print values passed as an operand -// to a %s or %v format or to an unformatted printer such as Print. -type Stringer interface { - String() string -} - -// GoStringer is implemented by any value that has a GoString() method, -// which defines the Go syntax for that value. -// The GoString method is used to print values passed as an operand -// to a %#v format. -type GoStringer interface { - GoString() string -} - -type pp struct { - n int - panicking bool - buf bytes.Buffer - runeBuf [utf8.UTFMax]byte - fmt fmt -} - -// A cache holds a set of reusable objects. -// The buffered channel holds the currently available objects. -// If more are needed, the cache creates them by calling new. -type cache struct { - saved chan interface{} - new func() interface{} -} - -func (c *cache) put(x interface{}) { - select { - case c.saved <- x: - // saved in cache - default: - // discard - } -} - -func (c *cache) get() interface{} { - select { - case x := <-c.saved: - return x // reused from cache - default: - return c.new() - } - panic("not reached") -} - -func newCache(f func() interface{}) *cache { - return &cache{make(chan interface{}, 100), f} -} - -var ppFree = newCache(func() interface{} { return new(pp) }) - -// Allocate a new pp struct or grab a cached one. -func newPrinter() *pp { - p := ppFree.get().(*pp) - p.panicking = false - p.fmt.init(&p.buf) - return p -} - -// Save 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.Bytes()) > 1024 { - return - } - p.buf.Reset() - ppFree.put(p) -} - -func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent } - -func (p *pp) Precision() (prec int, ok bool) { return p.fmt.prec, p.fmt.precPresent } - -func (p *pp) Flag(b int) bool { - switch b { - case '-': - return p.fmt.minus - case '+': - return p.fmt.plus - case '#': - return p.fmt.sharp - case ' ': - return p.fmt.space - case '0': - return p.fmt.zero - } - return false -} - -func (p *pp) add(c int) { - 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 os.Error) { - return p.buf.Write(b) -} - -// These routines end in 'f' and take a format string. - -// Fprintf formats according to a format specifier and writes to w. -// It returns the number of bytes written and any write error encountered. -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err os.Error) { - p := newPrinter() - p.doPrintf(format, a) - n64, err := p.buf.WriteTo(w) - p.free() - return int(n64), err -} - -// Printf formats according to a format specifier and writes to standard output. -// It returns the number of bytes written and any write error encountered. -func Printf(format string, a ...interface{}) (n int, err os.Error) { - return Fprintf(os.Stdout, format, a...) -} - -// Sprintf formats according to a format specifier and returns the resulting string. -func Sprintf(format string, a ...interface{}) string { - p := newPrinter() - p.doPrintf(format, a) - s := p.buf.String() - p.free() - return s -} - -// Errorf formats according to a format specifier and returns the string -// converted to an os.ErrorString, which satisfies the os.Error interface. -func Errorf(format string, a ...interface{}) os.Error { - return os.NewError(Sprintf(format, a...)) -} - -// These routines do not take a format string - -// Fprint formats using the default formats for its operands and writes to w. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Fprint(w io.Writer, a ...interface{}) (n int, err os.Error) { - p := newPrinter() - p.doPrint(a, false, false) - n64, err := p.buf.WriteTo(w) - p.free() - return int(n64), err -} - -// Print formats using the default formats for its operands and writes to standard output. -// Spaces are added between operands when neither is a string. -// It returns the number of bytes written and any write error encountered. -func Print(a ...interface{}) (n int, err os.Error) { - return Fprint(os.Stdout, a...) -} - -// Sprint formats using the default formats for its operands and returns the resulting string. -// Spaces are added between operands when neither is a string. -func Sprint(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, false, false) - s := p.buf.String() - p.free() - return s -} - -// These routines end in 'ln', do not take a format string, -// always add spaces between operands, and add a newline -// after the last operand. - -// Fprintln formats using the default formats for its operands and writes to w. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Fprintln(w io.Writer, a ...interface{}) (n int, err os.Error) { - p := newPrinter() - p.doPrint(a, true, true) - n64, err := p.buf.WriteTo(w) - p.free() - return int(n64), err -} - -// Println formats using the default formats for its operands and writes to standard output. -// Spaces are always added between operands and a newline is appended. -// It returns the number of bytes written and any write error encountered. -func Println(a ...interface{}) (n int, err os.Error) { - return Fprintln(os.Stdout, a...) -} - -// Sprintln formats using the default formats for its operands and returns the resulting string. -// Spaces are always added between operands and a newline is appended. -func Sprintln(a ...interface{}) string { - p := newPrinter() - p.doPrint(a, true, true) - s := p.buf.String() - p.free() - return s -} - - -// Get the i'th arg of the struct value. -// If the arg itself is an interface, return a value for -// the thing inside the interface, not the interface itself. -func getField(v reflect.Value, i int) reflect.Value { - val := v.Field(i) - if i := val; i.Kind() == reflect.Interface { - if inter := i.Interface(); inter != nil { - return reflect.ValueOf(inter) - } - } - return val -} - -// Convert ASCII to integer. n is 0 (and got is false) if no number present. -func parsenum(s string, start, end int) (num int, isnum bool, newi int) { - if start >= end { - return 0, false, end - } - for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ { - num = num*10 + int(s[newi]-'0') - isnum = true - } - return -} - -func (p *pp) unknownType(v interface{}) { - if v == nil { - p.buf.Write(nilAngleBytes) - return - } - p.buf.WriteByte('?') - p.buf.WriteString(reflect.TypeOf(v).String()) - p.buf.WriteByte('?') -} - -func (p *pp) badVerb(verb int, val interface{}) { - p.add('%') - p.add('!') - p.add(verb) - p.add('(') - if val == nil { - p.buf.Write(nilAngleBytes) - } else { - p.buf.WriteString(reflect.TypeOf(val).String()) - p.add('=') - p.printField(val, 'v', false, false, 0) - } - p.add(')') -} - -func (p *pp) fmtBool(v bool, verb int, value interface{}) { - switch verb { - case 't', 'v': - p.fmt.fmt_boolean(v) - default: - p.badVerb(verb, value) - } -} - -// fmtC formats a rune for the 'c' format. -func (p *pp) fmtC(c int64) { - rune := int(c) // Check for overflow. - if int64(rune) != c { - rune = utf8.RuneError - } - w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], rune) - p.fmt.pad(p.runeBuf[0:w]) -} - -func (p *pp) fmtInt64(v int64, verb int, value interface{}) { - 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 <= unicode.MaxRune { - p.fmt.fmt_qc(v) - } else { - p.badVerb(verb, value) - } - 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, value) - } -} - -// 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.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 int, goSyntax bool, value interface{}) { - 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 goSyntax { - p.fmt0x64(v, true) - } else { - p.fmt.integer(int64(v), 10, unsigned, ldigits) - } - case 'o': - p.fmt.integer(int64(v), 8, unsigned, ldigits) - case 'q': - if 0 <= v && v <= unicode.MaxRune { - p.fmt.fmt_qc(int64(v)) - } else { - p.badVerb(verb, value) - } - 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)) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat32(v float32, verb int, value interface{}) { - 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': - p.fmt.fmt_f32(v) - case 'g', 'v': - p.fmt.fmt_g32(v) - case 'G': - p.fmt.fmt_G32(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtFloat64(v float64, verb int, value interface{}) { - 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': - p.fmt.fmt_f64(v) - case 'g', 'v': - p.fmt.fmt_g64(v) - case 'G': - p.fmt.fmt_G64(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex64(v complex64, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c64(v, verb) - case 'v': - p.fmt.fmt_c64(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtComplex128(v complex128, verb int, value interface{}) { - switch verb { - case 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c128(v, verb) - case 'v': - p.fmt.fmt_c128(v, 'g') - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtString(v string, verb int, goSyntax bool, value interface{}) { - switch verb { - case 'v': - if goSyntax { - p.fmt.fmt_q(v) - } else { - p.fmt.fmt_s(v) - } - case 's': - p.fmt.fmt_s(v) - case 'x': - p.fmt.fmt_sx(v) - case 'X': - p.fmt.fmt_sX(v) - case 'q': - p.fmt.fmt_q(v) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interface{}) { - if verb == 'v' || verb == 'd' { - if goSyntax { - p.buf.Write(bytesBytes) - } else { - p.buf.WriteByte('[') - } - for i, c := range v { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(c, 'v', p.fmt.plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - return - } - s := string(v) - switch verb { - case 's': - p.fmt.fmt_s(s) - case 'x': - p.fmt.fmt_sx(s) - case 'X': - p.fmt.fmt_sX(s) - case 'q': - p.fmt.fmt_q(s) - default: - p.badVerb(verb, value) - } -} - -func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) { - var u uintptr - switch value.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - u = value.Pointer() - default: - p.badVerb(verb, field) - return - } - if goSyntax { - p.add('(') - p.buf.WriteString(reflect.TypeOf(field).String()) - p.add(')') - p.add('(') - if u == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(u), true) - } - p.add(')') - } else { - p.fmt0x64(uint64(u), !p.fmt.sharp) - } -} - -var ( - intBits = reflect.TypeOf(0).Bits() - floatBits = reflect.TypeOf(0.0).Bits() - complexBits = reflect.TypeOf(1i).Bits() - uintptrBits = reflect.TypeOf(uintptr(0)).Bits() -) - -func (p *pp) catchPanic(val interface{}, verb int) { - 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(val); v.Kind() == reflect.Ptr && v.IsNil() { - p.buf.Write(nilAngleBytes) - return - } - // Otherwise print a concise panic message. Most of the time the panic - // value will print itself nicely. - if p.panicking { - // Nested panics; the recursion in printField cannot succeed. - panic(err) - } - p.buf.WriteByte('%') - p.add(verb) - p.buf.Write(panicBytes) - p.panicking = true - p.printField(err, 'v', false, false, 0) - p.panicking = false - p.buf.WriteByte(')') - } -} - -func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) { - if field == nil { - if verb == 'T' || verb == 'v' { - p.buf.Write(nilAngleBytes) - } else { - p.badVerb(verb, field) - } - 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.printField(reflect.TypeOf(field).String(), 's', false, false, 0) - return false - case 'p': - p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax) - return false - } - // Is it a Formatter? - if formatter, ok := field.(Formatter); ok { - defer p.catchPanic(field, verb) - formatter.Format(p, verb) - return false // this value is not a string - - } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } - // If we're doing Go syntax and the field knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false - if stringer, ok := field.(GoStringer); ok { - defer p.catchPanic(field, verb) - // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false, field) - return false // this value is not a string - } - } else { - // Is it a Stringer? - if stringer, ok := field.(Stringer); ok { - defer p.catchPanic(field, verb) - p.printField(stringer.String(), verb, plus, false, depth) - return false // this value is not a string - } - } - - // Some types can be done without reflection. - switch f := field.(type) { - case bool: - p.fmtBool(f, verb, field) - return false - case float32: - p.fmtFloat32(f, verb, field) - return false - case float64: - p.fmtFloat64(f, verb, field) - return false - case complex64: - p.fmtComplex64(complex64(f), verb, field) - return false - case complex128: - p.fmtComplex128(f, verb, field) - return false - case int: - p.fmtInt64(int64(f), verb, field) - return false - case int8: - p.fmtInt64(int64(f), verb, field) - return false - case int16: - p.fmtInt64(int64(f), verb, field) - return false - case int32: - p.fmtInt64(int64(f), verb, field) - return false - case int64: - p.fmtInt64(f, verb, field) - return false - case uint: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint8: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint16: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint32: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case uint64: - p.fmtUint64(f, verb, goSyntax, field) - return false - case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax, field) - return false - case string: - p.fmtString(f, verb, goSyntax, field) - return verb == 's' || verb == 'v' - case []byte: - p.fmtBytes(f, verb, goSyntax, depth, field) - return verb == 's' - } - - // Need to use reflection - value := reflect.ValueOf(field) - -BigSwitch: - switch f := value; f.Kind() { - case reflect.Bool: - p.fmtBool(f.Bool(), verb, field) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p.fmtInt64(f.Int(), verb, field) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(uint64(f.Uint()), verb, goSyntax, field) - case reflect.Float32, reflect.Float64: - if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Float()), verb, field) - } else { - p.fmtFloat64(float64(f.Float()), verb, field) - } - case reflect.Complex64, reflect.Complex128: - if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Complex()), verb, field) - } else { - p.fmtComplex128(complex128(f.Complex()), verb, field) - } - case reflect.String: - p.fmtString(f.String(), verb, goSyntax, field) - case reflect.Map: - if goSyntax { - p.buf.WriteString(f.Type().String()) - p.buf.WriteByte('{') - } else { - p.buf.Write(mapBytes) - } - keys := f.MapKeys() - for i, key := range keys { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(key.Interface(), verb, plus, goSyntax, depth+1) - p.buf.WriteByte(':') - p.printField(f.MapIndex(key).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case reflect.Struct: - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - } - p.add('{') - v := f - t := v.Type() - for i := 0; i < v.NumField(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - if plus || goSyntax { - if f := t.Field(i); f.Name != "" { - p.buf.WriteString(f.Name) - p.buf.WriteByte(':') - } - } - p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1) - } - p.buf.WriteByte('}') - case reflect.Interface: - value := f.Elem() - if !value.IsValid() { - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.Write(nilParenBytes) - } else { - p.buf.Write(nilAngleBytes) - } - } else { - return p.printField(value.Interface(), verb, plus, goSyntax, depth+1) - } - case reflect.Array, reflect.Slice: - // Byte slices are special. - if f.Type().Elem().Kind() == reflect.Uint8 { - // We know it's a slice of bytes, but we also know it does not have static type - // []byte, or it would have been caught above. Therefore we cannot convert - // it directly in the (slightly) obvious way: f.Interface().([]byte); it doesn't have - // that type, and we can't write an expression of the right type and do a - // conversion because we don't have a static way to write the right type. - // 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, goSyntax, depth, field) - return verb == 's' - } - if goSyntax { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte('{') - } else { - p.buf.WriteByte('[') - } - for i := 0; i < f.Len(); i++ { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printField(f.Index(i).Interface(), verb, plus, goSyntax, depth+1) - } - if goSyntax { - 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 { - switch a := f.Elem(); a.Kind() { - case reflect.Array, reflect.Slice: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - case reflect.Struct: - p.buf.WriteByte('&') - p.printField(a.Interface(), verb, plus, goSyntax, depth+1) - break BigSwitch - } - } - if goSyntax { - p.buf.WriteByte('(') - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte(')') - p.buf.WriteByte('(') - if v == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(v), true) - } - p.buf.WriteByte(')') - break - } - if v == 0 { - p.buf.Write(nilAngleBytes) - break - } - p.fmt0x64(uint64(v), true) - case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(field, value, verb, goSyntax) - default: - p.unknownType(f) - } - return false -} - -// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int. -func intFromArg(a []interface{}, end, i, fieldnum int) (num int, isInt bool, newi, newfieldnum int) { - newi, newfieldnum = end, fieldnum - if i < end && fieldnum < len(a) { - num, isInt = a[fieldnum].(int) - newi, newfieldnum = i+1, fieldnum+1 - } - return -} - -func (p *pp) doPrintf(format string, a []interface{}) { - end := len(format) - fieldnum := 0 // we process one field per non-trivial format - for i := 0; i < end; { - lasti := i - for i < end && format[i] != '%' { - i++ - } - if i > lasti { - p.buf.WriteString(format[lasti:i]) - } - if i >= end { - // done processing format string - break - } - - // Process one verb - i++ - // flags and widths - p.fmt.clearflags() - F: - for ; i < end; i++ { - switch format[i] { - case '#': - p.fmt.sharp = true - case '0': - p.fmt.zero = true - case '+': - p.fmt.plus = true - case '-': - p.fmt.minus = true - case ' ': - p.fmt.space = true - default: - break F - } - } - // do we have width? - if i < end && format[i] == '*' { - p.fmt.wid, p.fmt.widPresent, i, fieldnum = intFromArg(a, end, i, fieldnum) - if !p.fmt.widPresent { - p.buf.Write(widthBytes) - } - } else { - p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end) - } - // do we have precision? - if i < end && format[i] == '.' { - if format[i+1] == '*' { - p.fmt.prec, p.fmt.precPresent, i, fieldnum = intFromArg(a, end, i+1, fieldnum) - if !p.fmt.precPresent { - p.buf.Write(precBytes) - } - } else { - p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i+1, end) - } - } - if i >= end { - p.buf.Write(noVerbBytes) - continue - } - c, 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 fieldnum >= len(a) { // out of operands - p.buf.WriteByte('%') - p.add(c) - p.buf.Write(missingBytes) - continue - } - field := a[fieldnum] - fieldnum++ - - goSyntax := c == 'v' && p.fmt.sharp - plus := c == 'v' && p.fmt.plus - p.printField(field, c, plus, goSyntax, 0) - } - - if fieldnum < len(a) { - p.buf.Write(extraBytes) - for ; fieldnum < len(a); fieldnum++ { - field := a[fieldnum] - if field != nil { - p.buf.WriteString(reflect.TypeOf(field).String()) - p.buf.WriteByte('=') - } - p.printField(field, 'v', false, false, 0) - if fieldnum+1 < len(a) { - p.buf.Write(commaSpaceBytes) - } - } - p.buf.WriteByte(')') - } -} - -func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { - prevString := false - for fieldnum := 0; fieldnum < len(a); fieldnum++ { - p.fmt.clearflags() - // always add spaces if we're doing println - field := a[fieldnum] - if fieldnum > 0 { - isString := field != nil && reflect.TypeOf(field).Kind() == reflect.String - if addspace || !isString && !prevString { - p.buf.WriteByte(' ') - } - } - prevString = p.printField(field, 'v', false, false, 0) - } - if addnewline { - p.buf.WriteByte('\n') - } -} diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go deleted file mode 100644 index d93a8c1da..000000000 --- a/src/pkg/fmt/scan.go +++ /dev/null @@ -1,1114 +0,0 @@ -// Copyright 2010 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. - -package fmt - -import ( - "bytes" - "io" - "math" - "os" - "reflect" - "strconv" - "strings" - "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() os.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. -type ScanState interface { - // ReadRune reads the next rune (Unicode code point) from the input. - // If invoked during Scanln, Fscanln, or Sscanln, ReadRune() will - // return EOF after returning the first '\n' or when reading beyond - // the specified width. - ReadRune() (rune int, size int, err os.Error) - // UnreadRune causes the next call to ReadRune to return the same rune. - UnreadRune() os.Error - // SkipSpace skips space in the input. Newlines are treated as space - // unless the scan operation is Scanln, Fscanln or Sscanln, in which case - // a newline is treated as EOF. - SkipSpace() - // 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 as space unless the scan operation - // is Scanln, Fscanln or Sscanln, in which case a newline is treated as - // EOF. 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 - // as input, or when the calling Scan method returns. - Token(skipSpace bool, f func(int) bool) (token []byte, err os.Error) - // Width returns the value of the width option and whether it has been set. - // The unit is Unicode code points. - Width() (wid int, ok bool) - // Because ReadRune is implemented by the interface, Read should never be - // called by the scanning routines and a valid implementation of - // ScanState may choose always to return an error from Read. - Read(buf []byte) (n int, err os.Error) -} - -// 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 -// for any argument to Scan, Scanf, or Scanln that implements it. -type Scanner interface { - Scan(state ScanState, verb int) os.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. -// If that is less than the number of arguments, err will report why. -func Scan(a ...interface{}) (n int, err os.Error) { - return Fscan(os.Stdin, a...) -} - -// Scanln is similar to Scan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Scanln(a ...interface{}) (n int, err os.Error) { - return Fscanln(os.Stdin, a...) -} - -// 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. -func Scanf(format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(os.Stdin, format, a...) -} - -// 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 -// than the number of arguments, err will report why. -func Sscan(str string, a ...interface{}) (n int, err os.Error) { - return Fscan(strings.NewReader(str), a...) -} - -// Sscanln is similar to Sscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Sscanln(str string, a ...interface{}) (n int, err os.Error) { - return Fscanln(strings.NewReader(str), a...) -} - -// Sscanf scans the argument string, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Sscanf(str string, format string, a ...interface{}) (n int, err os.Error) { - return Fscanf(strings.NewReader(str), format, a...) -} - -// 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 -// than the number of arguments, err will report why. -func Fscan(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, true, false) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanln is similar to Fscan, but stops scanning at a newline and -// after the final item there must be a newline or EOF. -func Fscanln(r io.Reader, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, true) - n, err = s.doScan(a) - s.free(old) - return -} - -// Fscanf scans text read from r, storing successive space-separated -// values into successive arguments as determined by the format. It -// returns the number of items successfully parsed. -func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err os.Error) { - s, old := newScanState(r, false, false) - n, err = s.doScanf(format, a) - s.free(old) - return -} - -// scanError represents an error generated by the scanning software. -// It's used as a unique signature to identify such errors when recovering. -type scanError struct { - err os.Error -} - -const eof = -1 - -// ss is the internal implementation of ScanState. -type ss struct { - rr io.RuneReader // where to read input - buf bytes.Buffer // token accumulator - peekRune int // one-rune lookahead - prevRune int // last rune returned by ReadRune - count int // runes consumed so far. - atEOF bool // already read EOF - ssave -} - -// ssave holds the parts of ss that need to be -// saved and restored on recursive scans. -type ssave struct { - validSave bool // is or was a part of an actual ss. - nlIsEnd bool // whether newline terminates scan - nlIsSpace bool // whether newline counts as white space - fieldLimit int // max value of ss.count for this field; fieldLimit <= limit - limit int // max value of ss.count. - maxWid int // width of this field. -} - -// The Read method is only in ScanState so that ScanState -// satisfies io.Reader. It will never be called when used as -// intended, so there is no need to make it actually work. -func (s *ss) Read(buf []byte) (n int, err os.Error) { - return 0, os.NewError("ScanState's Read should not be called. Use ReadRune") -} - -func (s *ss) ReadRune() (rune int, size int, err os.Error) { - if s.peekRune >= 0 { - s.count++ - rune = s.peekRune - size = utf8.RuneLen(rune) - s.prevRune = rune - s.peekRune = -1 - return - } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit { - err = os.EOF - return - } - - rune, size, err = s.rr.ReadRune() - if err == nil { - s.count++ - s.prevRune = rune - } else if err == os.EOF { - s.atEOF = true - } - return -} - -func (s *ss) Width() (wid int, ok bool) { - if s.maxWid == hugeWid { - return 0, false - } - return s.maxWid, true -} - -// The public method returns an error; this private one panics. -// If getRune reaches EOF, the return value is EOF (-1). -func (s *ss) getRune() (rune int) { - rune, _, err := s.ReadRune() - if err != nil { - if err == os.EOF { - return eof - } - s.error(err) - } - return -} - -// mustReadRune turns os.EOF into a panic(io.ErrUnexpectedEOF). -// It is called in cases such as string scanning where an EOF is a -// syntax error. -func (s *ss) mustReadRune() (rune int) { - rune = s.getRune() - if rune == eof { - s.error(io.ErrUnexpectedEOF) - } - return -} - -func (s *ss) UnreadRune() os.Error { - if u, ok := s.rr.(runeUnreader); ok { - u.UnreadRune() - } else { - s.peekRune = s.prevRune - } - s.prevRune = -1 - s.count-- - return nil -} - -func (s *ss) error(err os.Error) { - panic(scanError{err}) -} - -func (s *ss) errorString(err string) { - panic(scanError{os.NewError(err)}) -} - -func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.Error) { - defer func() { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { - err = se.err - } else { - panic(e) - } - } - }() - if f == nil { - f = notSpace - } - s.buf.Reset() - tok = s.token(skipSpace, f) - return -} - -// notSpace is the default scanning function used in Token. -func notSpace(r int) bool { - return !unicode.IsSpace(r) -} - - -// skipSpace provides Scan() methods the ability to skip space and newline characters -// in keeping with the current scanning mode set by format strings and Scan()/Scanln(). -func (s *ss) SkipSpace() { - s.skipSpace(false) -} - - -// 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. -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 -} - -// readByte returns the next byte from the input, which may be -// left over from a previous read if the UTF-8 was ill-formed. -func (r *readRune) readByte() (b byte, err os.Error) { - if r.pending > 0 { - b = r.pendBuf[0] - copy(r.pendBuf[0:], r.pendBuf[1:]) - r.pending-- - return - } - _, err = r.reader.Read(r.pendBuf[0:1]) - 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() (rune int, size int, err os.Error) { - r.buf[0], err = r.readByte() - if err != nil { - return 0, 0, err - } - if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case - rune = int(r.buf[0]) - return - } - var n int - for n = 1; !utf8.FullRune(r.buf[0:n]); n++ { - r.buf[n], err = r.readByte() - if err != nil { - if err == os.EOF { - err = nil - break - } - return - } - } - rune, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) - } - return -} - - -var ssFree = newCache(func() interface{} { return new(ss) }) - -// Allocate a new ss struct or grab a cached one. -func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { - // If the reader is a *ss, then we've got a recursive - // call to Scan, so re-use the scan state. - s, ok := r.(*ss) - if ok { - old = s.ssave - s.limit = s.fieldLimit - s.nlIsEnd = nlIsEnd || s.nlIsEnd - s.nlIsSpace = nlIsSpace - return - } - - s = ssFree.get().(*ss) - if rr, ok := r.(io.RuneReader); ok { - s.rr = rr - } else { - s.rr = &readRune{reader: r} - } - s.nlIsSpace = nlIsSpace - s.nlIsEnd = nlIsEnd - s.prevRune = -1 - s.peekRune = -1 - s.atEOF = false - s.limit = hugeWid - s.fieldLimit = hugeWid - s.maxWid = hugeWid - s.validSave = true - return -} - -// Save used ss structs in ssFree; avoid an allocation per invocation. -func (s *ss) free(old ssave) { - // If it was used recursively, just restore the old state. - if old.validSave { - s.ssave = old - return - } - // Don't hold on to ss structs with large buffers. - if cap(s.buf.Bytes()) > 1024 { - return - } - s.buf.Reset() - s.rr = nil - ssFree.put(s) -} - -// skipSpace skips spaces and maybe newlines. -func (s *ss) skipSpace(stopAtNewline bool) { - for { - rune := s.getRune() - if rune == eof { - return - } - if rune == '\n' { - if stopAtNewline { - break - } - if s.nlIsSpace { - continue - } - s.errorString("unexpected newline") - return - } - if !unicode.IsSpace(rune) { - s.UnreadRune() - break - } - } -} - - -// 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(int) bool) []byte { - if skipSpace { - s.skipSpace(false) - } - // read until white space or newline - for { - rune := s.getRune() - if rune == eof { - break - } - if !f(rune) { - s.UnreadRune() - break - } - s.buf.WriteRune(rune) - } - return s.buf.Bytes() -} - -// typeError indicates that the type of the operand did not match the format -func (s *ss) typeError(field interface{}, expected string) { - s.errorString("expected field of type pointer to " + expected + "; found " + reflect.TypeOf(field).String()) -} - -var complexError = os.NewError("syntax error scanning complex number") -var boolError = os.NewError("syntax error scanning boolean") - -// consume reads the next rune in the input and reports whether it is in the ok string. -// If accept is true, it puts the character into the input token. -func (s *ss) consume(ok string, accept bool) bool { - rune := s.getRune() - if rune == eof { - return false - } - if strings.IndexRune(ok, rune) >= 0 { - if accept { - s.buf.WriteRune(rune) - } - return true - } - if rune != eof && accept { - s.UnreadRune() - } - return false -} - -// peek reports whether the next character is in the ok string, without consuming it. -func (s *ss) peek(ok string) bool { - rune := s.getRune() - if rune != eof { - s.UnreadRune() - } - return strings.IndexRune(ok, rune) >= 0 -} - -func (s *ss) notEOF() { - // Guarantee there is data to be read. - if rune := s.getRune(); rune == eof { - panic(os.EOF) - } - s.UnreadRune() -} - -// 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) -} - -// okVerb verifies that the verb is present in the list, setting s.err appropriately if not. -func (s *ss) okVerb(verb int, okVerbs, typ string) bool { - for _, v := range okVerbs { - if v == verb { - return true - } - } - s.errorString("bad verb %" + string(verb) + " for " + typ) - return false -} - -// scanBool returns the value of the boolean represented by the next token. -func (s *ss) scanBool(verb int) bool { - s.skipSpace(false) - s.notEOF() - if !s.okVerb(verb, "tv", "boolean") { - return false - } - // Syntax-checking a boolean is annoying. We're not fastidious about case. - switch s.getRune() { - case '0': - return false - case '1': - return true - case 't', 'T': - if s.accept("rR") && (!s.accept("uU") || !s.accept("eE")) { - s.error(boolError) - } - return true - case 'f', 'F': - if s.accept("aL") && (!s.accept("lL") || !s.accept("sS") || !s.accept("eE")) { - s.error(boolError) - } - return false - } - return false -} - -// Numerical elements -const ( - binaryDigits = "01" - octalDigits = "01234567" - decimalDigits = "0123456789" - hexadecimalDigits = "0123456789aAbBcCdDeEfF" - sign = "+-" - period = "." - exponent = "eEp" -) - -// getBase returns the numeric base represented by the verb and its digit string. -func (s *ss) getBase(verb int) (base int, digits string) { - s.okVerb(verb, "bdoUxXv", "integer") // sets s.err - base = 10 - digits = decimalDigits - switch verb { - case 'b': - base = 2 - digits = binaryDigits - case 'o': - base = 8 - digits = octalDigits - case 'x', 'X', 'U': - base = 16 - digits = hexadecimalDigits - } - return -} - -// scanNumber returns the numerical string with specified digits starting here. -func (s *ss) scanNumber(digits string, haveDigits bool) string { - s.notEOF() - if !haveDigits && !s.accept(digits) { - s.errorString("expected integer") - } - for s.accept(digits) { - } - return s.buf.String() -} - -// scanRune returns the next rune value in the input. -func (s *ss) scanRune(bitSize int) int64 { - s.notEOF() - rune := int64(s.getRune()) - n := uint(bitSize) - x := (rune << (64 - n)) >> (64 - n) - if x != rune { - s.errorString("overflow on character value " + string(rune)) - } - return rune -} - -// scanBasePrefix reports whether the integer begins with a 0 or 0x, -// and returns the base, digit string, and whether a zero was found. -// It is called only if the verb is %v. -func (s *ss) scanBasePrefix() (base int, digits string, found bool) { - if !s.peek("0") { - return 10, decimalDigits, false - } - s.accept("0") - found = true // We've put a digit into the token buffer. - // Special cases for '0' && '0x' - base, digits = 8, octalDigits - if s.peek("xX") { - s.consume("xX", false) - base, digits = 16, hexadecimalDigits - } - return -} - -// scanInt returns the value of the integer represented by the next -// token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanInt(verb int, bitSize int) int64 { - if verb == 'c' { - return s.scanRune(bitSize) - } - s.skipSpace(false) - s.notEOF() - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else { - s.accept(sign) // If there's a sign, it will be left in the token buffer. - if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoi64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("integer overflow on token " + tok) - } - return i -} - -// scanUint returns the value of the unsigned integer represented -// by the next token, checking for overflow. Any error is stored in s.err. -func (s *ss) scanUint(verb int, bitSize int) uint64 { - if verb == 'c' { - return uint64(s.scanRune(bitSize)) - } - s.skipSpace(false) - s.notEOF() - base, digits := s.getBase(verb) - haveDigits := false - if verb == 'U' { - if !s.consume("U", false) || !s.consume("+", false) { - s.errorString("bad unicode format ") - } - } else if verb == 'v' { - base, digits, haveDigits = s.scanBasePrefix() - } - tok := s.scanNumber(digits, haveDigits) - i, err := strconv.Btoui64(tok, base) - if err != nil { - s.error(err) - } - n := uint(bitSize) - x := (i << (64 - n)) >> (64 - n) - if x != i { - s.errorString("unsigned integer overflow on token " + tok) - } - return i -} - -// floatToken returns the floating-point number starting here, no longer than swid -// if the width is specified. It's not rigorous about syntax because it doesn't check that -// we have at least some digits, but Atof will do that. -func (s *ss) floatToken() string { - s.buf.Reset() - // NaN? - if s.accept("nN") && s.accept("aA") && s.accept("nN") { - return s.buf.String() - } - // leading sign? - s.accept(sign) - // Inf? - if s.accept("iI") && s.accept("nN") && s.accept("fF") { - return s.buf.String() - } - // digits? - for s.accept(decimalDigits) { - } - // decimal point? - if s.accept(period) { - // fraction? - for s.accept(decimalDigits) { - } - } - // exponent? - if s.accept(exponent) { - // leading sign? - s.accept(sign) - // digits? - for s.accept(decimalDigits) { - } - } - return s.buf.String() -} - -// complexTokens returns the real and imaginary parts of the complex number starting here. -// The number might be parenthesized and has the format (N+Ni) where N is a floating-point -// number and there are no spaces within. -func (s *ss) complexTokens() (real, imag string) { - // TODO: accept N and Ni independently? - parens := s.accept("(") - real = s.floatToken() - s.buf.Reset() - // Must now have a sign. - if !s.accept("+-") { - s.error(complexError) - } - // Sign is now in buffer - imagSign := s.buf.String() - imag = s.floatToken() - if !s.accept("i") { - s.error(complexError) - } - if parens && !s.accept(")") { - s.error(complexError) - } - return real, imagSign + imag -} - -// convertFloat converts the string to a float64value. -func (s *ss) convertFloat(str string, n int) float64 { - if p := strings.Index(str, "p"); p >= 0 { - // Atof doesn't handle power-of-2 exponents, - // but they're easy to evaluate. - f, err := strconv.AtofN(str[:p], n) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - n, err := strconv.Atoi(str[p+1:]) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - return math.Ldexp(f, n) - } - f, err := strconv.AtofN(str, n) - if err != nil { - s.error(err) - } - return f -} - -// convertComplex converts the next token to a complex128 value. -// The atof argument is a type-specific reader for the underlying type. -// If we're reading complex64, atof will parse float32s and convert them -// to float64's to avoid reproducing this code for each complex type. -func (s *ss) scanComplex(verb int, n int) complex128 { - if !s.okVerb(verb, floatVerbs, "complex") { - return 0 - } - s.skipSpace(false) - s.notEOF() - sreal, simag := s.complexTokens() - real := s.convertFloat(sreal, n/2) - imag := s.convertFloat(simag, n/2) - return complex(real, imag) -} - -// convertString returns the string represented by the next input characters. -// The format of the input is determined by the verb. -func (s *ss) convertString(verb int) (str string) { - if !s.okVerb(verb, "svqx", "string") { - return "" - } - s.skipSpace(false) - s.notEOF() - switch verb { - case 'q': - str = s.quotedString() - case 'x': - str = s.hexString() - default: - str = string(s.token(true, notSpace)) // %s and %v just return the next word - } - return -} - -// quotedString returns the double- or back-quoted string represented by the next input characters. -func (s *ss) quotedString() string { - s.notEOF() - quote := s.getRune() - switch quote { - case '`': - // Back-quoted: Anything goes until EOF or back quote. - for { - rune := s.mustReadRune() - if rune == quote { - break - } - s.buf.WriteRune(rune) - } - return s.buf.String() - case '"': - // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) - for { - rune := s.mustReadRune() - s.buf.WriteRune(rune) - if rune == '\\' { - // In a legal backslash escape, no matter how long, only the character - // immediately after the escape can itself be a backslash or quote. - // Thus we only need to protect the first character after the backslash. - rune := s.mustReadRune() - s.buf.WriteRune(rune) - } else if rune == '"' { - break - } - } - result, err := strconv.Unquote(s.buf.String()) - if err != nil { - s.error(err) - } - return result - default: - s.errorString("expected quoted string") - } - return "" -} - -// hexDigit returns the value of the hexadecimal digit -func (s *ss) hexDigit(digit int) int { - switch digit { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return digit - '0' - case 'a', 'b', 'c', 'd', 'e', 'f': - return 10 + digit - 'a' - case 'A', 'B', 'C', 'D', 'E', 'F': - return 10 + digit - 'A' - } - s.errorString("Scan: illegal hex digit") - return 0 -} - -// hexByte returns the next hex-encoded (two-character) byte from the input. -// There must be either two hexadecimal digits or a space character in the input. -func (s *ss) hexByte() (b byte, ok bool) { - rune1 := s.getRune() - if rune1 == eof { - return - } - if unicode.IsSpace(rune1) { - s.UnreadRune() - return - } - rune2 := s.mustReadRune() - return byte(s.hexDigit(rune1)<<4 | s.hexDigit(rune2)), true -} - -// hexString returns the space-delimited hexpair-encoded string. -func (s *ss) hexString() string { - s.notEOF() - for { - b, ok := s.hexByte() - if !ok { - break - } - s.buf.WriteByte(b) - } - if s.buf.Len() == 0 { - s.errorString("Scan: no hex data for %x string") - return "" - } - return s.buf.String() -} - -const floatVerbs = "beEfFgGv" - -const hugeWid = 1 << 30 - -// scanOne scans a single value, deriving the scanner from the type of the argument. -func (s *ss) scanOne(verb int, field interface{}) { - s.buf.Reset() - var err os.Error - // If the parameter has its own Scan method, use that. - if v, ok := field.(Scanner); ok { - err = v.Scan(s, verb) - if err != nil { - if err == os.EOF { - err = io.ErrUnexpectedEOF - } - s.error(err) - } - return - } - - switch v := field.(type) { - case *bool: - *v = s.scanBool(verb) - case *complex64: - *v = complex64(s.scanComplex(verb, 64)) - case *complex128: - *v = s.scanComplex(verb, 128) - case *int: - *v = int(s.scanInt(verb, intBits)) - case *int8: - *v = int8(s.scanInt(verb, 8)) - case *int16: - *v = int16(s.scanInt(verb, 16)) - case *int32: - *v = int32(s.scanInt(verb, 32)) - case *int64: - *v = s.scanInt(verb, 64) - case *uint: - *v = uint(s.scanUint(verb, intBits)) - case *uint8: - *v = uint8(s.scanUint(verb, 8)) - case *uint16: - *v = uint16(s.scanUint(verb, 16)) - case *uint32: - *v = uint32(s.scanUint(verb, 32)) - case *uint64: - *v = s.scanUint(verb, 64) - case *uintptr: - *v = uintptr(s.scanUint(verb, uintptrBits)) - // Floats are tricky because you want to scan in the precision of the result, not - // scan in high precision and convert, in order to preserve the correct error condition. - case *float32: - if s.okVerb(verb, floatVerbs, "float32") { - s.skipSpace(false) - s.notEOF() - *v = float32(s.convertFloat(s.floatToken(), 32)) - } - case *float64: - if s.okVerb(verb, floatVerbs, "float64") { - s.skipSpace(false) - s.notEOF() - *v = s.convertFloat(s.floatToken(), 64) - } - case *string: - *v = s.convertString(verb) - case *[]byte: - // We scan to string and convert so we get a copy of the data. - // If we scanned to bytes, the slice would point at the buffer. - *v = []byte(s.convertString(verb)) - default: - val := reflect.ValueOf(v) - ptr := val - if ptr.Kind() != reflect.Ptr { - s.errorString("Scan: type not a pointer: " + val.Type().String()) - return - } - switch v := ptr.Elem(); v.Kind() { - case reflect.Bool: - v.SetBool(s.scanBool(verb)) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - v.SetInt(s.scanInt(verb, v.Type().Bits())) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - v.SetUint(s.scanUint(verb, v.Type().Bits())) - case reflect.String: - v.SetString(s.convertString(verb)) - case reflect.Slice: - // For now, can only handle (renamed) []byte. - typ := v.Type() - if typ.Elem().Kind() != reflect.Uint8 { - s.errorString("Scan: can't handle type: " + val.Type().String()) - } - str := s.convertString(verb) - v.Set(reflect.MakeSlice(typ, len(str), len(str))) - for i := 0; i < len(str); i++ { - v.Index(i).SetUint(uint64(str[i])) - } - case reflect.Float32, reflect.Float64: - s.skipSpace(false) - s.notEOF() - v.SetFloat(s.convertFloat(s.floatToken(), v.Type().Bits())) - case reflect.Complex64, reflect.Complex128: - v.SetComplex(s.scanComplex(verb, v.Type().Bits())) - default: - s.errorString("Scan: can't handle type: " + val.Type().String()) - } - } -} - -// errorHandler turns local panics into error returns. -func errorHandler(errp *os.Error) { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { // catch local error - *errp = se.err - } else if eof, ok := e.(os.Error); ok && eof == os.EOF { // out of input - *errp = eof - } else { - panic(e) - } - } -} - -// doScan does the real work for scanning without a format string. -func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - for _, field := range a { - s.scanOne('v', field) - numProcessed++ - } - // Check for newline if required. - if !s.nlIsSpace { - for { - rune := s.getRune() - if rune == '\n' || rune == eof { - break - } - if !unicode.IsSpace(rune) { - s.errorString("Scan: expected newline") - break - } - } - } - return -} - -// advance determines whether the next characters in the input match -// those of the format. It returns the number of bytes (sic) consumed -// in the format. Newlines included, all runs of space characters in -// either input or format behave as a single space. This routine also -// handles the %% case. If the return value is zero, either format -// starts with a % (with no following %) or the input is empty. -// If it is negative, the input did not match the string. -func (s *ss) advance(format string) (i int) { - for i < len(format) { - fmtc, w := utf8.DecodeRuneInString(format[i:]) - if fmtc == '%' { - // %% acts like a real percent - nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty - if nextc != '%' { - return - } - i += w // skip the first % - } - sawSpace := false - for unicode.IsSpace(fmtc) && i < len(format) { - sawSpace = true - i += w - fmtc, w = utf8.DecodeRuneInString(format[i:]) - } - if sawSpace { - // There was space in the format, so there should be space (EOF) - // in the input. - inputc := s.getRune() - if inputc == eof { - return - } - if !unicode.IsSpace(inputc) { - // Space in format but not in input: error - s.errorString("expected space in input to match format") - } - s.skipSpace(true) - continue - } - inputc := s.mustReadRune() - if fmtc != inputc { - s.UnreadRune() - return -1 - } - i += w - } - return -} - -// doScanf does the real work when scanning with a format string. -// At the moment, it handles only pointers to basic types. -func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err os.Error) { - defer errorHandler(&err) - end := len(format) - 1 - // We process one item per non-trivial format - for i := 0; i <= end; { - w := s.advance(format[i:]) - if w > 0 { - i += w - continue - } - // 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? - if w < 0 { - s.errorString("input does not match format") - } - // Otherwise at EOF; "too many operands" error handled below - break - } - i++ // % is one byte - - // do we have 20 (width)? - var widPresent bool - s.maxWid, widPresent, i = parsenum(format, i, end) - if !widPresent { - s.maxWid = hugeWid - } - s.fieldLimit = s.limit - if f := s.count + s.maxWid; f < s.fieldLimit { - s.fieldLimit = f - } - - c, w := utf8.DecodeRuneInString(format[i:]) - i += w - - if numProcessed >= len(a) { // out of operands - s.errorString("too few operands for format %" + format[i-w:]) - break - } - field := a[numProcessed] - - s.scanOne(c, field) - numProcessed++ - s.fieldLimit = s.limit - } - if numProcessed < len(a) { - s.errorString("too many operands") - } - return -} diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go deleted file mode 100644 index 98b3b5493..000000000 --- a/src/pkg/fmt/scan_test.go +++ /dev/null @@ -1,921 +0,0 @@ -// Copyright 2009 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. - -package fmt_test - -import ( - "bufio" - "bytes" - . "fmt" - "io" - "math" - "os" - "reflect" - "regexp" - "strings" - "testing" - "utf8" -) - -type ScanTest struct { - text string - in interface{} - out interface{} -} - -type ScanfTest struct { - format string - text string - in interface{} - out interface{} -} - -type ScanfMultiTest struct { - format string - text string - in []interface{} - out []interface{} - err string -} - -var ( - boolVal bool - intVal int - int8Val int8 - int16Val int16 - int32Val int32 - int64Val int64 - uintVal uint - uint8Val uint8 - uint16Val uint16 - uint32Val uint32 - uint64Val uint64 - float32Val float32 - float64Val float64 - stringVal string - stringVal1 string - bytesVal []byte - complex64Val complex64 - complex128Val complex128 - renamedBoolVal renamedBool - renamedIntVal renamedInt - renamedInt8Val renamedInt8 - renamedInt16Val renamedInt16 - renamedInt32Val renamedInt32 - renamedInt64Val renamedInt64 - renamedUintVal renamedUint - renamedUint8Val renamedUint8 - renamedUint16Val renamedUint16 - renamedUint32Val renamedUint32 - renamedUint64Val renamedUint64 - renamedUintptrVal renamedUintptr - renamedStringVal renamedString - renamedBytesVal renamedBytes - renamedFloat32Val renamedFloat32 - renamedFloat64Val renamedFloat64 - renamedComplex64Val renamedComplex64 - renamedComplex128Val renamedComplex128 -) - -type FloatTest struct { - text string - in float64 - out float64 -} - -// Xs accepts any non-empty run of the verb character -type Xs string - -func (x *Xs) Scan(state ScanState, verb int) os.Error { - tok, err := state.Token(true, func(r int) bool { return r == verb }) - if err != nil { - return err - } - s := string(tok) - if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) { - return os.NewError("syntax error for xs") - } - *x = Xs(s) - return nil -} - -var xVal Xs - -// IntString accepts an integer followed immediately by a string. -// It tests the embedding of a scan within a scan. -type IntString struct { - i int - s string -} - -func (s *IntString) Scan(state ScanState, verb int) os.Error { - if _, err := Fscan(state, &s.i); err != nil { - return err - } - - tok, err := state.Token(true, nil) - if err != nil { - return err - } - s.s = string(tok) - return nil -} - -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 os.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 - {"F\n", &boolVal, false}, // restored to zero value - {"21\n", &intVal, 21}, - {"0\n", &intVal, 0}, - {"000\n", &intVal, 0}, - {"0x10\n", &intVal, 0x10}, - {"-0x10\n", &intVal, -0x10}, - {"0377\n", &intVal, 0377}, - {"-0377\n", &intVal, -0377}, - {"0\n", &uintVal, uint(0)}, - {"000\n", &uintVal, uint(0)}, - {"0x10\n", &uintVal, uint(0x10)}, - {"0377\n", &uintVal, uint(0377)}, - {"22\n", &int8Val, int8(22)}, - {"23\n", &int16Val, int16(23)}, - {"24\n", &int32Val, int32(24)}, - {"25\n", &int64Val, int64(25)}, - {"127\n", &int8Val, int8(127)}, - {"-21\n", &intVal, -21}, - {"-22\n", &int8Val, int8(-22)}, - {"-23\n", &int16Val, int16(-23)}, - {"-24\n", &int32Val, int32(-24)}, - {"-25\n", &int64Val, int64(-25)}, - {"-128\n", &int8Val, int8(-128)}, - {"+21\n", &intVal, +21}, - {"+22\n", &int8Val, int8(+22)}, - {"+23\n", &int16Val, int16(+23)}, - {"+24\n", &int32Val, int32(+24)}, - {"+25\n", &int64Val, int64(+25)}, - {"+127\n", &int8Val, int8(+127)}, - {"26\n", &uintVal, uint(26)}, - {"27\n", &uint8Val, uint8(27)}, - {"28\n", &uint16Val, uint16(28)}, - {"29\n", &uint32Val, uint32(29)}, - {"30\n", &uint64Val, uint64(30)}, - {"255\n", &uint8Val, uint8(255)}, - {"32767\n", &int16Val, int16(32767)}, - {"2.3\n", &float64Val, 2.3}, - {"2.3e1\n", &float32Val, float32(2.3e1)}, - {"2.3e2\n", &float64Val, 2.3e2}, - {"2.3p2\n", &float64Val, 2.3 * 4}, - {"2.3p+2\n", &float64Val, 2.3 * 4}, - {"2.3p+66\n", &float64Val, 2.3 * (1 << 32) * (1 << 32) * 4}, - {"2.3p-66\n", &float64Val, 2.3 / ((1 << 32) * (1 << 32) * 4)}, - {"2.35\n", &stringVal, "2.35"}, - {"2345678\n", &bytesVal, []byte("2345678")}, - {"(3.4e1-2i)\n", &complex128Val, 3.4e1 - 2i}, - {"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)}, - {"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)}, - {"hello\n", &stringVal, "hello"}, - - // Renamed types - {"true\n", &renamedBoolVal, renamedBool(true)}, - {"F\n", &renamedBoolVal, renamedBool(false)}, - {"101\n", &renamedIntVal, renamedInt(101)}, - {"102\n", &renamedIntVal, renamedInt(102)}, - {"103\n", &renamedUintVal, renamedUint(103)}, - {"104\n", &renamedUintVal, renamedUint(104)}, - {"105\n", &renamedInt8Val, renamedInt8(105)}, - {"106\n", &renamedInt16Val, renamedInt16(106)}, - {"107\n", &renamedInt32Val, renamedInt32(107)}, - {"108\n", &renamedInt64Val, renamedInt64(108)}, - {"109\n", &renamedUint8Val, renamedUint8(109)}, - {"110\n", &renamedUint16Val, renamedUint16(110)}, - {"111\n", &renamedUint32Val, renamedUint32(111)}, - {"112\n", &renamedUint64Val, renamedUint64(112)}, - {"113\n", &renamedUintptrVal, renamedUintptr(113)}, - {"114\n", &renamedStringVal, renamedString("114")}, - {"115\n", &renamedBytesVal, renamedBytes([]byte("115"))}, - - // Custom scanners. - {" vvv ", &xVal, Xs("vvv")}, - {" 1234hello", &intStringVal, IntString{1234, "hello"}}, - - // Fixed bugs - {"2147483648\n", &int64Val, int64(2147483648)}, // was: integer overflow -} - -var scanfTests = []ScanfTest{ - {"%v", "TRUE\n", &boolVal, true}, - {"%t", "false\n", &boolVal, false}, - {"%v", "-71\n", &intVal, -71}, - {"%v", "0377\n", &intVal, 0377}, - {"%v", "0x44\n", &intVal, 0x44}, - {"%d", "72\n", &intVal, 72}, - {"%c", "a\n", &intVal, 'a'}, - {"%c", "\u5072\n", &intVal, 0x5072}, - {"%c", "\u1234\n", &intVal, '\u1234'}, - {"%d", "73\n", &int8Val, int8(73)}, - {"%d", "+74\n", &int16Val, int16(74)}, - {"%d", "75\n", &int32Val, int32(75)}, - {"%d", "76\n", &int64Val, int64(76)}, - {"%b", "1001001\n", &intVal, 73}, - {"%o", "075\n", &intVal, 075}, - {"%x", "a75\n", &intVal, 0xa75}, - {"%v", "71\n", &uintVal, uint(71)}, - {"%d", "72\n", &uintVal, uint(72)}, - {"%d", "73\n", &uint8Val, uint8(73)}, - {"%d", "74\n", &uint16Val, uint16(74)}, - {"%d", "75\n", &uint32Val, uint32(75)}, - {"%d", "76\n", &uint64Val, uint64(76)}, - {"%b", "1001001\n", &uintVal, uint(73)}, - {"%o", "075\n", &uintVal, uint(075)}, - {"%x", "a75\n", &uintVal, uint(0xa75)}, - {"%x", "A75\n", &uintVal, uint(0xa75)}, - {"%U", "U+1234\n", &intVal, int(0x1234)}, - {"%U", "U+4567\n", &uintVal, uint(0x4567)}, - - // Strings - {"%s", "using-%s\n", &stringVal, "using-%s"}, - {"%x", "7573696e672d2578\n", &stringVal, "using-%x"}, - {"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"}, - {"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"}, - - // Byte slices - {"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")}, - {"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")}, - {"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")}, - {"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")}, - - // Renamed types - {"%v\n", "true\n", &renamedBoolVal, renamedBool(true)}, - {"%t\n", "F\n", &renamedBoolVal, renamedBool(false)}, - {"%v", "101\n", &renamedIntVal, renamedInt(101)}, - {"%c", "\u0101\n", &renamedIntVal, renamedInt('\u0101')}, - {"%o", "0146\n", &renamedIntVal, renamedInt(102)}, - {"%v", "103\n", &renamedUintVal, renamedUint(103)}, - {"%d", "104\n", &renamedUintVal, renamedUint(104)}, - {"%d", "105\n", &renamedInt8Val, renamedInt8(105)}, - {"%d", "106\n", &renamedInt16Val, renamedInt16(106)}, - {"%d", "107\n", &renamedInt32Val, renamedInt32(107)}, - {"%d", "108\n", &renamedInt64Val, renamedInt64(108)}, - {"%x", "6D\n", &renamedUint8Val, renamedUint8(109)}, - {"%o", "0156\n", &renamedUint16Val, renamedUint16(110)}, - {"%d", "111\n", &renamedUint32Val, renamedUint32(111)}, - {"%d", "112\n", &renamedUint64Val, renamedUint64(112)}, - {"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)}, - {"%s", "114\n", &renamedStringVal, renamedString("114")}, - {"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))}, - {"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)}, - {"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)}, - {"%g", "11+6e1i\n", &renamedComplex64Val, renamedComplex64(11 + 6e1i)}, - {"%g", "-11.+7e+1i", &renamedComplex128Val, renamedComplex128(-11. + 7e+1i)}, - - // Interesting formats - {"here is\tthe value:%d", "here is the\tvalue:118\n", &intVal, 118}, - {"%% %%:%d", "% %:119\n", &intVal, 119}, - - // Corner cases - {"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)}, - - // Custom scanner. - {"%s", " sss ", &xVal, Xs("sss")}, - {"%2s", "sssss", &xVal, Xs("ss")}, - - // Fixed bugs - {"%d\n", "27\n", &intVal, 27}, // ok - {"%d\n", "28 \n", &intVal, 28}, // was: "unexpected newline" -} - -var overflowTests = []ScanTest{ - {"128", &int8Val, 0}, - {"32768", &int16Val, 0}, - {"-129", &int8Val, 0}, - {"-32769", &int16Val, 0}, - {"256", &uint8Val, 0}, - {"65536", &uint16Val, 0}, - {"1e100", &float32Val, 0}, - {"1e500", &float64Val, 0}, - {"(1e100+0i)", &complex64Val, 0}, - {"(1+1e100i)", &complex64Val, 0}, - {"(1-1e500i)", &complex128Val, 0}, -} - -var i, j, k int -var f float64 -var s, t string -var c complex128 -var x, y Xs -var z IntString - -var multiTests = []ScanfMultiTest{ - {"", "", nil, nil, ""}, - {"%d", "23", args(&i), args(23), ""}, - {"%2s%3s", "22333", args(&s, &t), args("22", "333"), ""}, - {"%2d%3d", "44555", args(&i, &j), args(44, 555), ""}, - {"%2d.%3d", "66.777", args(&i, &j), args(66, 777), ""}, - {"%d, %d", "23, 18", args(&i, &j), args(23, 18), ""}, - {"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""}, - {"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""}, - {"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""}, - {"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""}, - - // Custom scanners. - {"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""}, - {"%4v%s", "12abcd", args(&z, &s), args(IntString{12, "ab"}, "cd"), ""}, - - // Errors - {"%t", "23 18", args(&i), nil, "bad verb"}, - {"%d %d %d", "23 18", args(&i, &j), args(23, 18), "too few operands"}, - {"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"}, - {"%c", "\u0100", args(&int8Val), nil, "overflow"}, - {"X%d", "10X", args(&intVal), nil, "input does not match format"}, - - // Bad UTF-8: should see every byte. - {"%c%c%c", "\xc2X\xc2", args(&i, &j, &k), args(utf8.RuneError, 'X', utf8.RuneError), ""}, -} - -func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, os.Error)) { - for _, test := range scanTests { - var r io.Reader - if name == "StringReader" { - r = strings.NewReader(test.text) - } else { - r = newReader(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) - continue - } - if n != 1 { - t.Errorf("%s count error on entry %q: got %d", name, test.text, n) - continue - } - // The incoming value may be a pointer - v := reflect.ValueOf(test.in) - if p := v; p.Kind() == reflect.Ptr { - v = p.Elem() - } - 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) - } - } -} - -func TestScan(t *testing.T) { - testScan("StringReader", t, Fscan) -} - -func TestMyReaderScan(t *testing.T) { - testScan("myStringReader", t, Fscan) -} - -func TestScanln(t *testing.T) { - testScan("StringReader", t, Fscanln) -} - -func TestMyReaderScanln(t *testing.T) { - testScan("myStringReader", t, Fscanln) -} - -func TestScanf(t *testing.T) { - for _, test := range scanfTests { - n, err := Sscanf(test.text, test.format, test.in) - if err != nil { - t.Errorf("got error scanning (%q, %q): %s", test.format, test.text, err) - continue - } - if n != 1 { - t.Errorf("count error on entry (%q, %q): got %d", test.format, test.text, n) - continue - } - // The incoming value may be a pointer - v := reflect.ValueOf(test.in) - if p := v; p.Kind() == reflect.Ptr { - v = p.Elem() - } - val := v.Interface() - if !reflect.DeepEqual(val, test.out) { - t.Errorf("scanning (%q, %q): expected %v got %v, type %T", test.format, test.text, test.out, val, val) - } - } -} - -func TestScanOverflow(t *testing.T) { - // different machines and different types report errors with different strings. - re := regexp.MustCompile("overflow|too large|out of range|not representable") - for _, test := range overflowTests { - _, err := Sscan(test.text, test.in) - if err == nil { - t.Errorf("expected overflow scanning %q", test.text) - continue - } - if !re.MatchString(err.String()) { - t.Errorf("expected overflow error scanning %q: %s", test.text, err) - } - } -} - -func verifyNaN(str string, t *testing.T) { - var f float64 - var f32 float32 - var f64 float64 - text := str + " " + str + " " + str - n, err := Fscan(strings.NewReader(text), &f, &f32, &f64) - if err != nil { - t.Errorf("got error scanning %q: %s", text, err) - } - if n != 3 { - t.Errorf("count error scanning %q: got %d", text, n) - } - if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) { - t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64) - } -} - -func TestNaN(t *testing.T) { - for _, s := range []string{"nan", "NAN", "NaN"} { - verifyNaN(s, t) - } -} - -func verifyInf(str string, t *testing.T) { - var f float64 - var f32 float32 - var f64 float64 - text := str + " " + str + " " + str - n, err := Fscan(strings.NewReader(text), &f, &f32, &f64) - if err != nil { - t.Errorf("got error scanning %q: %s", text, err) - } - if n != 3 { - t.Errorf("count error scanning %q: got %d", text, n) - } - sign := 1 - if str[0] == '-' { - sign = -1 - } - if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) { - t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64) - } -} - -func TestInf(t *testing.T) { - for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} { - verifyInf(s, t) - } -} - -func testScanfMulti(name string, t *testing.T) { - 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) - } - 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.String(), test.err) < 0 { - t.Errorf("got wrong error scanning (%q, %q): %q; expected %q", test.format, test.text, err, test.err) - } - continue - } - if test.err != "" { - t.Errorf("expected error %q error scanning (%q, %q)", test.err, test.format, test.text) - } - if n != len(test.out) { - t.Errorf("count error on entry (%q, %q): expected %d got %d", test.format, test.text, len(test.out), n) - continue - } - // Convert the slice of pointers into a slice of values - resultVal := reflect.MakeSlice(sliceType, n, n) - for i := 0; i < n; i++ { - v := reflect.ValueOf(test.in[i]).Elem() - resultVal.Index(i).Set(v) - } - result := resultVal.Interface() - if !reflect.DeepEqual(result, test.out) { - t.Errorf("scanning (%q, %q): expected %v got %v", test.format, test.text, test.out, result) - } - } -} - -func TestScanfMulti(t *testing.T) { - testScanfMulti("StringReader", t) -} - -func TestMyReaderScanfMulti(t *testing.T) { - testScanfMulti("myStringReader", t) -} - -func TestScanMultiple(t *testing.T) { - var a int - var s string - n, err := Sscan("123abc", &a, &s) - if n != 2 { - t.Errorf("Sscan count error: expected 2: got %d", n) - } - if err != nil { - t.Errorf("Sscan expected no error; got %s", err) - } - if a != 123 || s != "abc" { - t.Errorf("Sscan wrong values: got (%d %q) expected (123 \"abc\")", a, s) - } - n, err = Sscan("asdf", &s, &a) - if n != 1 { - t.Errorf("Sscan count error: expected 1: got %d", n) - } - if err == nil { - t.Errorf("Sscan expected error; got none: %s", err) - } - if s != "asdf" { - t.Errorf("Sscan wrong values: got %q expected \"asdf\"", s) - } -} - -// Empty strings are not valid input when scanning a string. -func TestScanEmpty(t *testing.T) { - var s1, s2 string - n, err := Sscan("abc", &s1, &s2) - if n != 1 { - t.Errorf("Sscan count error: expected 1: got %d", n) - } - if err == nil { - t.Error("Sscan <one item> expected error; got none") - } - if s1 != "abc" { - t.Errorf("Sscan wrong values: got %q expected \"abc\"", s1) - } - n, err = Sscan("", &s1, &s2) - if n != 0 { - t.Errorf("Sscan count error: expected 0: got %d", n) - } - if err == nil { - t.Error("Sscan <empty> expected error; got none") - } - // Quoted empty string is OK. - n, err = Sscanf(`""`, "%q", &s1) - if n != 1 { - t.Errorf("Sscanf count error: expected 1: got %d", n) - } - if err != nil { - t.Errorf("Sscanf <empty> expected no error with quoted string; got %s", err) - } -} - -func TestScanNotPointer(t *testing.T) { - r := strings.NewReader("1") - var a int - _, err := Fscan(r, a) - if err == nil { - t.Error("expected error scanning non-pointer") - } else if strings.Index(err.String(), "pointer") < 0 { - t.Errorf("expected pointer error scanning non-pointer, got: %s", err) - } -} - -func TestScanlnNoNewline(t *testing.T) { - var a int - _, err := Sscanln("1 x\n", &a) - if err == nil { - t.Error("expected error scanning string missing newline") - } else if strings.Index(err.String(), "newline") < 0 { - t.Errorf("expected newline error scanning string missing newline, got: %s", err) - } -} - -func TestScanlnWithMiddleNewline(t *testing.T) { - r := strings.NewReader("123\n456\n") - var a, b int - _, err := Fscanln(r, &a, &b) - if err == nil { - t.Error("expected error scanning string with extra newline") - } else if strings.Index(err.String(), "newline") < 0 { - t.Errorf("expected newline error scanning string with extra newline, got: %s", err) - } -} - -// Special Reader that counts reads at end of file. -type eofCounter struct { - reader *strings.Reader - eofCount int -} - -func (ec *eofCounter) Read(b []byte) (n int, err os.Error) { - n, err = ec.reader.Read(b) - if n == 0 { - ec.eofCount++ - } - return -} - -// Verify that when we scan, we see at most EOF once per call to a Scan function, -// and then only when it's really an EOF -func TestEOF(t *testing.T) { - ec := &eofCounter{strings.NewReader("123\n"), 0} - var a int - n, err := Fscanln(ec, &a) - if err != nil { - t.Error("unexpected error", err) - } - if n != 1 { - t.Error("expected to scan one item, got", n) - } - if ec.eofCount != 0 { - t.Error("expected zero EOFs", ec.eofCount) - ec.eofCount = 0 // reset for next test - } - n, err = Fscanln(ec, &a) - if err == nil { - t.Error("expected error scanning empty string") - } - if n != 0 { - t.Error("expected to scan zero items, got", n) - } - if ec.eofCount != 1 { - t.Error("expected one EOF, got", ec.eofCount) - } -} - -// Verify that we see an EOF error if we run out of input. -// This was a buglet: we used to get "expected integer". -func TestEOFAtEndOfInput(t *testing.T) { - var i, j int - n, err := Sscanf("23", "%d %d", &i, &j) - if n != 1 || i != 23 { - t.Errorf("Sscanf expected one value of 23; got %d %d", n, i) - } - if err != os.EOF { - t.Errorf("Sscanf expected EOF; got %q", err) - } - n, err = Sscan("234", &i, &j) - if n != 1 || i != 234 { - t.Errorf("Sscan expected one value of 234; got %d %d", n, i) - } - if err != os.EOF { - t.Errorf("Sscan expected EOF; got %q", err) - } - // Trailing space is tougher. - n, err = Sscan("234 ", &i, &j) - if n != 1 || i != 234 { - t.Errorf("Sscan expected one value of 234; got %d %d", n, i) - } - if err != os.EOF { - t.Errorf("Sscan expected EOF; got %q", err) - } -} - -var eofTests = []struct { - format string - v interface{} -}{ - {"%s", &stringVal}, - {"%q", &stringVal}, - {"%x", &stringVal}, - {"%v", &stringVal}, - {"%v", &bytesVal}, - {"%v", &intVal}, - {"%v", &uintVal}, - {"%v", &boolVal}, - {"%v", &float32Val}, - {"%v", &complex64Val}, - {"%v", &renamedStringVal}, - {"%v", &renamedBytesVal}, - {"%v", &renamedIntVal}, - {"%v", &renamedUintVal}, - {"%v", &renamedBoolVal}, - {"%v", &renamedFloat32Val}, - {"%v", &renamedComplex64Val}, -} - -func TestEOFAllTypes(t *testing.T) { - for i, test := range eofTests { - if _, err := Sscanf("", test.format, test.v); err != os.EOF { - t.Errorf("#%d: %s %T not eof on empty string: %s", i, test.format, test.v, err) - } - if _, err := Sscanf(" ", test.format, test.v); err != os.EOF { - t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err) - } - } -} - -// Verify that, at least when using bufio, successive calls to Fscan do not lose runes. -func TestUnreadRuneWithBufio(t *testing.T) { - r := bufio.NewReader(strings.NewReader("123αb")) - var i int - var a string - n, err := Fscanf(r, "%d", &i) - if n != 1 || err != nil { - t.Errorf("reading int expected one item, no errors; got %d %q", n, err) - } - if i != 123 { - t.Errorf("expected 123; got %d", i) - } - n, err = Fscanf(r, "%s", &a) - if n != 1 || err != nil { - t.Errorf("reading string expected one item, no errors; got %d %q", n, err) - } - if a != "αb" { - t.Errorf("expected αb; got %q", a) - } -} - -type TwoLines string - -// Attempt 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 int) os.Error { - chars := make([]int, 0, 100) - for nlCount := 0; nlCount < 2; { - c, _, err := state.ReadRune() - if err != nil { - return err - } - chars = append(chars, c) - if c == '\n' { - nlCount++ - } - } - *t = TwoLines(string(chars)) - return nil -} - -func TestMultiLine(t *testing.T) { - input := "abc\ndef\n" - // Sscan should work - var tscan TwoLines - n, err := Sscan(input, &tscan) - if n != 1 { - t.Errorf("Sscan: expected 1 item; got %d", n) - } - if err != nil { - t.Errorf("Sscan: expected no error; got %s", err) - } - if string(tscan) != input { - t.Errorf("Sscan: expected %q; got %q", input, tscan) - } - // Sscanf should work - var tscanf TwoLines - n, err = Sscanf(input, "%s", &tscanf) - if n != 1 { - t.Errorf("Sscanf: expected 1 item; got %d", n) - } - if err != nil { - t.Errorf("Sscanf: expected no error; got %s", err) - } - if string(tscanf) != input { - t.Errorf("Sscanf: expected %q; got %q", input, tscanf) - } - // Sscanln should not work - var tscanln TwoLines - n, err = Sscanln(input, &tscanln) - if n != 0 { - t.Errorf("Sscanln: expected 0 items; got %d: %q", n, tscanln) - } - if err == nil { - t.Error("Sscanln: expected error; got none") - } else if err != io.ErrUnexpectedEOF { - t.Errorf("Sscanln: expected io.ErrUnexpectedEOF (ha!); got %s", err) - } -} - -// RecursiveInt accepts an string matching %d.%d.%d.... -// and parses it into a linked list. -// It allows us to benchmark recursive descent style scanners. -type RecursiveInt struct { - i int - next *RecursiveInt -} - -func (r *RecursiveInt) Scan(state ScanState, verb int) (err os.Error) { - _, err = Fscan(state, &r.i) - if err != nil { - return - } - next := new(RecursiveInt) - _, err = Fscanf(state, ".%v", next) - if err != nil { - if err == os.NewError("input does not match format") || err == io.ErrUnexpectedEOF { - err = nil - } - return - } - r.next = next - return -} - -// Perform the same scanning task as RecursiveInt.Scan -// but without recurring through scanner, so we can compare -// performance more directly. -func scanInts(r *RecursiveInt, b *bytes.Buffer) (err os.Error) { - r.next = nil - _, err = Fscan(b, &r.i) - if err != nil { - return - } - var c int - c, _, err = b.ReadRune() - if err != nil { - if err == os.EOF { - err = nil - } - return - } - if c != '.' { - return - } - next := new(RecursiveInt) - err = scanInts(next, b) - if err == nil { - r.next = next - } - return -} - -func makeInts(n int) []byte { - var buf bytes.Buffer - Fprintf(&buf, "1") - for i := 1; i < n; i++ { - Fprintf(&buf, ".%d", i+1) - } - return buf.Bytes() -} - -func TestScanInts(t *testing.T) { - testScanInts(t, scanInts) - testScanInts(t, func(r *RecursiveInt, b *bytes.Buffer) (err os.Error) { - _, err = Fscan(b, r) - return - }) -} - -// 800 is small enough to not overflow the stack when using gccgo on a -// platform that does not support split stack. -const intCount = 800 - -func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) os.Error) { - r := new(RecursiveInt) - ints := makeInts(intCount) - buf := bytes.NewBuffer(ints) - err := scan(r, buf) - if err != nil { - t.Error("unexpected error", err) - } - i := 1 - for ; r != nil; r = r.next { - if r.i != i { - t.Fatalf("bad scan: expected %d got %d", i, r.i) - } - i++ - } - if i-1 != intCount { - t.Fatalf("bad scan count: expected %d got %d", intCount, i-1) - } -} - -func BenchmarkScanInts(b *testing.B) { - b.ResetTimer() - ints := makeInts(intCount) - var r RecursiveInt - for i := b.N - 1; i >= 0; i-- { - buf := bytes.NewBuffer(ints) - b.StartTimer() - scanInts(&r, buf) - b.StopTimer() - } -} - -func BenchmarkScanRecursiveInt(b *testing.B) { - b.ResetTimer() - ints := makeInts(intCount) - var r RecursiveInt - for i := b.N - 1; i >= 0; i-- { - buf := bytes.NewBuffer(ints) - b.StartTimer() - Fscan(buf, &r) - b.StopTimer() - } -} diff --git a/src/pkg/fmt/stringer_test.go b/src/pkg/fmt/stringer_test.go deleted file mode 100644 index 0ca3f522d..000000000 --- a/src/pkg/fmt/stringer_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2010 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. - -package fmt_test - -import ( - . "fmt" - "testing" -) - -type TI int -type TI8 int8 -type TI16 int16 -type TI32 int32 -type TI64 int64 -type TU uint -type TU8 uint8 -type TU16 uint16 -type TU32 uint32 -type TU64 uint64 -type TUI uintptr -type TF float64 -type TF32 float32 -type TF64 float64 -type TB bool -type TS string - -func (v TI) String() string { return Sprintf("I: %d", int(v)) } -func (v TI8) String() string { return Sprintf("I8: %d", int8(v)) } -func (v TI16) String() string { return Sprintf("I16: %d", int16(v)) } -func (v TI32) String() string { return Sprintf("I32: %d", int32(v)) } -func (v TI64) String() string { return Sprintf("I64: %d", int64(v)) } -func (v TU) String() string { return Sprintf("U: %d", uint(v)) } -func (v TU8) String() string { return Sprintf("U8: %d", uint8(v)) } -func (v TU16) String() string { return Sprintf("U16: %d", uint16(v)) } -func (v TU32) String() string { return Sprintf("U32: %d", uint32(v)) } -func (v TU64) String() string { return Sprintf("U64: %d", uint64(v)) } -func (v TUI) String() string { return Sprintf("UI: %d", uintptr(v)) } -func (v TF) String() string { return Sprintf("F: %f", float64(v)) } -func (v TF32) String() string { return Sprintf("F32: %f", float32(v)) } -func (v TF64) String() string { return Sprintf("F64: %f", float64(v)) } -func (v TB) String() string { return Sprintf("B: %t", bool(v)) } -func (v TS) String() string { return Sprintf("S: %q", string(v)) } - -func check(t *testing.T, got, want string) { - if got != want { - t.Error(got, "!=", want) - } -} - -func TestStringer(t *testing.T) { - s := Sprintf("%v %v %v %v %v", TI(0), TI8(1), TI16(2), TI32(3), TI64(4)) - check(t, s, "I: 0 I8: 1 I16: 2 I32: 3 I64: 4") - s = Sprintf("%v %v %v %v %v %v", TU(5), TU8(6), TU16(7), TU32(8), TU64(9), TUI(10)) - check(t, s, "U: 5 U8: 6 U16: 7 U32: 8 U64: 9 UI: 10") - s = Sprintf("%v %v %v", TF(1.0), TF32(2.0), TF64(3.0)) - check(t, s, "F: 1.000000 F32: 2.000000 F64: 3.000000") - s = Sprintf("%v %v", TB(true), TS("x")) - check(t, s, "B: true S: \"x\"") -} |