diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/fmt | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/fmt')
-rw-r--r-- | src/pkg/fmt/doc.go | 272 | ||||
-rw-r--r-- | src/pkg/fmt/export_test.go | 7 | ||||
-rw-r--r-- | src/pkg/fmt/fmt_test.go | 1147 | ||||
-rw-r--r-- | src/pkg/fmt/format.go | 492 | ||||
-rw-r--r-- | src/pkg/fmt/print.go | 1199 | ||||
-rw-r--r-- | src/pkg/fmt/scan.go | 1168 | ||||
-rw-r--r-- | src/pkg/fmt/scan_test.go | 960 | ||||
-rw-r--r-- | src/pkg/fmt/stringer_test.go | 61 |
8 files changed, 0 insertions, 5306 deletions
diff --git a/src/pkg/fmt/doc.go b/src/pkg/fmt/doc.go deleted file mode 100644 index 02642d6ae..000000000 --- a/src/pkg/fmt/doc.go +++ /dev/null @@ -1,272 +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.FormatFloat with the 'b' format, - 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 - %F synonym for %f - %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). - - Width is specified by an optional decimal number immediately following the verb. - If absent, the width is whatever is necessary to represent the value. - Precision is specified after the (optional) width by a period followed by a - decimal number. If no period is present, a default precision is used. - A period with no following number specifies a precision of zero. - Examples: - %f: default width, default precision - %9f width 9, default precision - %.2f default width, precision 2 - %9.2f width 9, precision 2 - %9.f width 9, precision 0 - - Width and precision are measured 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 most values, width is the minimum number of characters to output, - padding the formatted form with spaces if necessary. - For strings, precision is the maximum number of characters to output, - truncating if necessary. - - For floating-point values, width sets the minimum width of the field and - precision sets the number of places after the decimal, if appropriate, - except that for %g/%G it sets the total number of digits. For example, - given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5. - The default precision for %e and %f is 6; for %g it is the smallest - number of digits necessary to identify the value uniquely. - - For complex numbers, the width and precision apply to the two - components independently and the result is parenthesized, so %f applied - to 1.2+3.4i produces (1.200000+3.400000i). - - 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); - for %q, print a raw (backquoted) string if strconv.CanBackquote - returns true; - 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 numbers, this moves the padding after the sign - - Flags are ignored by verbs that do not expect them. - For example there is no alternate decimal format, so %#d and %d - behave identically. - - 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. - - Except when printed using the verbs %T and %p, special - formatting considerations apply for operands that implement - certain interfaces. In order of application: - - 1. If an operand implements the Formatter interface, it will - be invoked. Formatter provides fine control of formatting. - - 2. If the %v verb is used with the # flag (%#v) and the operand - implements the GoStringer interface, that will be invoked. - - If the format (which is implicitly %v for Println etc.) is valid - for a string (%s %q %v %x %X), the following two rules apply: - - 3. If an operand implements the error interface, the Error method - will be invoked to convert the object to a string, which will then - be formatted as required by the verb (if any). - - 4. If an operand implements method String() string, that method - will be invoked to convert the object to a string, which will then - be formatted as required by the verb (if any). - - For compound operands such as slices and structs, the format - applies to the elements of each operand, recursively, not to the - operand as a whole. Thus %q will quote each element of a slice - of strings, and %6.2f will control formatting for each element - of a floating-point array. - - To avoid recursion in cases such as - type X string - func (x X) String() string { return Sprintf("<%s>", x) } - convert the value before recurring: - func (x X) String() string { return Sprintf("<%s>", string(x)) } - - Explicit argument indexes: - - In Printf, Sprintf, and Fprintf, the default behavior is for each - formatting verb to format successive arguments passed in the call. - However, the notation [n] immediately before the verb indicates that the - nth one-indexed argument is to be formatted instead. The same notation - before a '*' for a width or precision selects the argument index holding - the value. After processing a bracketed expression [n], arguments n+1, - n+2, etc. will be processed unless otherwise directed. - - For example, - fmt.Sprintf("%[2]d %[1]d\n", 11, 22) - will yield "22, 11", while - fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6), - equivalent to - fmt.Sprintf("%6.2f", 12.0), - will yield " 12.00". Because an explicit index affects subsequent verbs, - this notation can be used to print the same values multiple times - by resetting the index for the first argument to be repeated: - fmt.Sprintf("%d %d %#[1]x %#x", 16, 17) - will yield "16 17 0x10 0x11". - - 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 - Invalid or invalid use of argument index: %!(BADINDEX) - Printf("%*[2]d", 7): %!d(BADINDEX) - Printf("%.[2]d", 7): %!d(BADINDEX) - - All errors begin with the string "%!" followed sometimes - by a single character (the verb) and end with a parenthesized - description. - - If an Error or String method triggers a panic when called by a - print routine, the fmt package reformats the error message - from the panic, decorating it with an indication that it came - through the fmt package. For example, if a String method - calls panic("bad"), the resulting formatted message will look - like - %!s(PANIC=bad) - - The %!s just shows the print verb in use when the failure - occurred. - - 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 io.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; Scanf, 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 - Flags # and + are not implemented. - - 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, a carriage return followed - immediately by a newline is treated as a plain newline - (\r\n means the same as \n). - - 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/export_test.go b/src/pkg/fmt/export_test.go deleted file mode 100644 index 89d57ee6c..000000000 --- a/src/pkg/fmt/export_test.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package fmt - -var IsSpace = isSpace diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go deleted file mode 100644 index 7e3d06b9f..000000000 --- a/src/pkg/fmt/fmt_test.go +++ /dev/null @@ -1,1147 +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 ( - "bytes" - . "fmt" - "io" - "math" - "runtime" - "strings" - "testing" - "time" - "unicode" -) - -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 = [5]int{1, 2, 3, 4, 5} -var iarray = [4]interface{}{1, "hello", 2.5, nil} -var slice = array[:] -var islice = iarray[:] - -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 rune) { - 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 -} - -type SI struct { - I interface{} -} - -// P is 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 barray = [5]renamedUint8{1, 2, 3, 4, 5} -var bslice = barray[:] - -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"), "0x610x620x630xff"}, - {"%#X", []byte("abc\xff"), "0X610X620X630XFF"}, - {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"}, - {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"}, - {"% 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", "日本語日本語", ` "日"`}, - {"%10v", nil, " <nil>"}, - {"%-10v", nil, "<nil> "}, - - // 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"}, - {"%.0d", 0, ""}, - {"%.d", 0, ""}, - - // 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"}, - {"%+.3F", -1.0, "-1.000"}, - {"%+.3F", float32(-1.0), "-1.000"}, - {"%+07.2f", 1.0, "+001.00"}, - {"%+07.2f", -1.0, "-001.00"}, - {"%+10.2f", +1.0, " +1.00"}, - {"%+10.2f", -1.0, " -1.00"}, - {"% .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"}, - {"%b", float32(1.0), "8388608p-23"}, - {"%b", 1.0, "4503599627370496p-52"}, - - // 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)"}, - {"%.3F", 0i, "(0.000+0.000i)"}, - {"%.3F", complex64(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)"}, - {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"}, - {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"}, - - // erroneous formats - {"", 2, "%!(EXTRA int=2)"}, - {"%d", "hello", "%!d(string=hello)"}, - - // 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", barray, "[1 2 3 4 5]"}, - {"%v", &array, "&[1 2 3 4 5]"}, - {"%v", &iarray, "&[1 hello 2.5 <nil>]"}, - {"%v", &barray, "&[1 2 3 4 5]"}, - - // slices - {"%v", slice, "[1 2 3 4 5]"}, - {"%v", islice, "[1 hello 2.5 <nil>]"}, - {"%v", bslice, "[1 2 3 4 5]"}, - {"%v", &slice, "&[1 2 3 4 5]"}, - {"%v", &islice, "&[1 hello 2.5 <nil>]"}, - {"%v", &bslice, "&[1 2 3 4 5]"}, - - // 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}}`}, - - // other formats on Stringable items - {"%s", I(23), `<23>`}, - {"%q", I(23), `"<23>"`}, - {"%x", I(23), `3c32333e`}, - {"%#x", I(23), `0x3c0x320x330x3e`}, - {"%# x", I(23), `0x3c 0x32 0x33 0x3e`}, - {"%d", I(23), `23`}, // Stringer applies only to string formats. - - // go syntax - {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, - {"%#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}, `map[string]int{"a":1}`}, - {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`}, - {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`}, - {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`}, - {"%#v", []int(nil), `[]int(nil)`}, - {"%#v", []int{}, `[]int{}`}, - {"%#v", array, `[5]int{1, 2, 3, 4, 5}`}, - {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`}, - {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, - {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, - {"%#v", map[int]byte(nil), `map[int]uint8(nil)`}, - {"%#v", map[int]byte{}, `map[int]uint8{}`}, - {"%#v", "foo", `"foo"`}, - {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, - {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, - {"%#v", []byte(nil), "[]byte(nil)"}, - {"%#v", []int32(nil), "[]int32(nil)"}, - - // 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"`}, - {"%x", []renamedUint8{'a', 'b', 'c'}, "616263"}, - {"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"}, - {"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"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"}, - {"%10T", nil, " <nil>"}, - {"%-10T", nil, "<nil> "}, - - // %p - {"p0=%p", new(int), "p0=0xPTR"}, - {"p1=%s", &pValue, "p1=String(p)"}, // String method... - {"p2=%p", &pValue, "p2=0xPTR"}, // ... not called with %p - {"p3=%p", (*int)(nil), "p3=0x0"}, - {"p4=%#p", new(int), "p4=PTR"}, - - // %p on non-pointers - {"%p", make(chan int), "0xPTR"}, - {"%p", make(map[int]int), "0xPTR"}, - {"%p", make([]int, 1), "0xPTR"}, - {"%p", 27, "%!p(int=27)"}, // not a pointer at all - - // %q on pointers - {"%q", (*int)(nil), "%!q(*int=<nil>)"}, - {"%q", new(int), "%!q(*int=0xPTR)"}, - - // %v on pointers formats 0 as <nil> - {"%v", (*int)(nil), "<nil>"}, - {"%v", new(int), "0xPTR"}, - - // %d etc. pointers use specified base. - {"%d", new(int), "PTR_d"}, - {"%o", new(int), "PTR_o"}, - {"%x", new(int), "PTR_x"}, - - // %d on Stringer should give integer if possible - {"%s", time.Time{}.Month(), "January"}, - {"%d", time.Time{}.Month(), "1"}, - - // erroneous things - {"%s %", "hello", "hello %!(NOVERB)"}, - {"%s %.2", "hello", "hello %!(NOVERB)"}, - {"%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)"}, - - // The "<nil>" show up because maps are printed by - // first obtaining a list of keys and then looking up - // each key. Since NaNs can be map keys but cannot - // be fetched directly, the lookup fails and returns a - // zero reflect.Value, which formats as <nil>. - // This test is just to check that it shows the two NaNs at all. - {"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN:<nil> NaN:<nil>]"}, - - // Used to crash because nByte didn't allow for a sign. - {"%b", int64(-1 << 63), zeroFill("-1", 63, "")}, - - // Used to panic. - {"%0100d", 1, zeroFill("", 100, "1")}, - {"%0100d", -1, zeroFill("-", 99, "1")}, - {"%0.100f", 1.0, zeroFill("1.", 100, "")}, - {"%0.100f", -1.0, zeroFill("-1.", 100, "")}, - - // Comparison of padding rules with C printf. - /* - C program: - #include <stdio.h> - - char *format[] = { - "[%.2f]", - "[% .2f]", - "[%+.2f]", - "[%7.2f]", - "[% 7.2f]", - "[%+7.2f]", - "[%07.2f]", - "[% 07.2f]", - "[%+07.2f]", - }; - - int main(void) { - int i; - for(i = 0; i < 9; i++) { - printf("%s: ", format[i]); - printf(format[i], 1.0); - printf(" "); - printf(format[i], -1.0); - printf("\n"); - } - } - - Output: - [%.2f]: [1.00] [-1.00] - [% .2f]: [ 1.00] [-1.00] - [%+.2f]: [+1.00] [-1.00] - [%7.2f]: [ 1.00] [ -1.00] - [% 7.2f]: [ 1.00] [ -1.00] - [%+7.2f]: [ +1.00] [ -1.00] - [%07.2f]: [0001.00] [-001.00] - [% 07.2f]: [ 001.00] [-001.00] - [%+07.2f]: [+001.00] [-001.00] - */ - {"%.2f", 1.0, "1.00"}, - {"%.2f", -1.0, "-1.00"}, - {"% .2f", 1.0, " 1.00"}, - {"% .2f", -1.0, "-1.00"}, - {"%+.2f", 1.0, "+1.00"}, - {"%+.2f", -1.0, "-1.00"}, - {"%7.2f", 1.0, " 1.00"}, - {"%7.2f", -1.0, " -1.00"}, - {"% 7.2f", 1.0, " 1.00"}, - {"% 7.2f", -1.0, " -1.00"}, - {"%+7.2f", 1.0, " +1.00"}, - {"%+7.2f", -1.0, " -1.00"}, - {"%07.2f", 1.0, "0001.00"}, - {"%07.2f", -1.0, "-001.00"}, - {"% 07.2f", 1.0, " 001.00"}, - {"% 07.2f", -1.0, "-001.00"}, - {"%+07.2f", 1.0, "+001.00"}, - {"%+07.2f", -1.0, "-001.00"}, - - // Complex numbers: exhaustively tested in TestComplexFormatting. - {"%7.2f", 1 + 2i, "( 1.00 +2.00i)"}, - {"%+07.2f", -1 - 2i, "(-001.00-002.00i)"}, - // Zero padding does not apply to infinities. - {"%020f", math.Inf(-1), " -Inf"}, - {"%020f", math.Inf(+1), " +Inf"}, - {"% 020f", math.Inf(-1), " -Inf"}, - {"% 020f", math.Inf(+1), " Inf"}, - {"%+020f", math.Inf(-1), " -Inf"}, - {"%+020f", math.Inf(+1), " +Inf"}, - {"%20f", -1.0, " -1.000000"}, - // Make sure we can handle very large widths. - {"%0100f", -1.0, zeroFill("-", 99, "1.000000")}, - - // Complex fmt used to leave the plus flag set for future entries in the array - // causing +2+0i and +3+0i instead of 2+0i and 3+0i. - {"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"}, - {"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"}, - - // Incomplete format specification caused crash. - {"%.", 3, "%!.(int=3)"}, - - // Used to panic with out-of-bounds for very large numeric representations. - // nByte is set to handle one bit per uint64 in %b format, with a negative number. - // See issue 6777. - {"%#064x", 1, zeroFill("0x", 64, "1")}, - {"%#064x", -1, zeroFill("-0x", 63, "1")}, - {"%#064b", 1, zeroFill("", 64, "1")}, - {"%#064b", -1, zeroFill("-", 63, "1")}, - {"%#064o", 1, zeroFill("", 64, "1")}, - {"%#064o", -1, zeroFill("-", 63, "1")}, - {"%#064d", 1, zeroFill("", 64, "1")}, - {"%#064d", -1, zeroFill("-", 63, "1")}, - // Test that we handle the crossover above the size of uint64 - {"%#072x", 1, zeroFill("0x", 72, "1")}, - {"%#072x", -1, zeroFill("-0x", 71, "1")}, - {"%#072b", 1, zeroFill("", 72, "1")}, - {"%#072b", -1, zeroFill("-", 71, "1")}, - {"%#072o", 1, zeroFill("", 72, "1")}, - {"%#072o", -1, zeroFill("-", 71, "1")}, - {"%#072d", 1, zeroFill("", 72, "1")}, - {"%#072d", -1, zeroFill("-", 71, "1")}, - - // Padding for complex numbers. Has been bad, then fixed, then bad again. - {"%+10.2f", +104.66 + 440.51i, "( +104.66 +440.51i)"}, - {"%+10.2f", -104.66 + 440.51i, "( -104.66 +440.51i)"}, - {"%+10.2f", +104.66 - 440.51i, "( +104.66 -440.51i)"}, - {"%+10.2f", -104.66 - 440.51i, "( -104.66 -440.51i)"}, - {"%+010.2f", +104.66 + 440.51i, "(+000104.66+000440.51i)"}, - {"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"}, - {"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"}, - {"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"}, -} - -// zeroFill generates zero-filled strings of the specified width. The length -// of the suffix (but not the prefix) is compensated for in the width calculation. -func zeroFill(prefix string, width int, suffix string) string { - return prefix + strings.Repeat("0", width-len(suffix)) + suffix -} - -func TestSprintf(t *testing.T) { - for _, tt := range fmtTests { - s := Sprintf(tt.fmt, tt.val) - if i := strings.Index(tt.out, "PTR"); i >= 0 { - pattern := "PTR" - chars := "0123456789abcdefABCDEF" - switch { - case strings.HasPrefix(tt.out[i:], "PTR_d"): - pattern = "PTR_d" - chars = chars[:10] - case strings.HasPrefix(tt.out[i:], "PTR_o"): - pattern = "PTR_o" - chars = chars[:8] - case strings.HasPrefix(tt.out[i:], "PTR_x"): - pattern = "PTR_x" - } - j := i - for ; j < len(s); j++ { - c := s[j] - if !strings.ContainsRune(chars, rune(c)) { - break - } - } - s = s[0:i] + pattern + 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) - } - } - } -} - -// TestComplexFormatting checks that a complex always formats to the same -// thing as if done by hand with two singleton prints. -func TestComplexFormatting(t *testing.T) { - var yesNo = []bool{true, false} - var signs = []float64{1, 0, -1} - for _, plus := range yesNo { - for _, zero := range yesNo { - for _, space := range yesNo { - for _, char := range "fFeEgG" { - realFmt := "%" - if zero { - realFmt += "0" - } - if space { - realFmt += " " - } - if plus { - realFmt += "+" - } - realFmt += "10.2" - realFmt += string(char) - // Imaginary part always has a sign, so force + and ignore space. - imagFmt := "%" - if zero { - imagFmt += "0" - } - imagFmt += "+" - imagFmt += "10.2" - imagFmt += string(char) - for _, realSign := range signs { - for _, imagSign := range signs { - one := Sprintf(realFmt, complex(realSign, imagSign)) - two := Sprintf("("+realFmt+imagFmt+"i)", realSign, imagSign) - if one != two { - t.Error(f, one, two) - } - } - } - } - } - } - } -} - -type SE []interface{} // slice of empty; notational compactness. - -var reorderTests = []struct { - fmt string - val SE - out string -}{ - {"%[1]d", SE{1}, "1"}, - {"%[2]d", SE{2, 1}, "1"}, - {"%[2]d %[1]d", SE{1, 2}, "2 1"}, - {"%[2]*[1]d", SE{2, 5}, " 2"}, - {"%6.2f", SE{12.0}, " 12.00"}, // Explicit version of next line. - {"%[3]*.[2]*[1]f", SE{12.0, 2, 6}, " 12.00"}, - {"%[1]*.[2]*[3]f", SE{6, 2, 12.0}, " 12.00"}, - {"%10f", SE{12.0}, " 12.000000"}, - {"%[1]*[3]f", SE{10, 99, 12.0}, " 12.000000"}, - {"%.6f", SE{12.0}, "12.000000"}, // Explicit version of next line. - {"%.[1]*[3]f", SE{6, 99, 12.0}, "12.000000"}, - {"%6.f", SE{12.0}, " 12"}, // // Explicit version of next line; empty precision means zero. - {"%[1]*.[3]f", SE{6, 3, 12.0}, " 12"}, - // An actual use! Print the same arguments twice. - {"%d %d %d %#[1]o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015"}, - - // Erroneous cases. - {"%[d", SE{2, 1}, "%!d(BADINDEX)"}, - {"%]d", SE{2, 1}, "%!](int=2)d%!(EXTRA int=1)"}, - {"%[]d", SE{2, 1}, "%!d(BADINDEX)"}, - {"%[-3]d", SE{2, 1}, "%!d(BADINDEX)"}, - {"%[99]d", SE{2, 1}, "%!d(BADINDEX)"}, - {"%[3]", SE{2, 1}, "%!(NOVERB)"}, - {"%[1].2d", SE{5, 6}, "%!d(BADINDEX)"}, - {"%[1]2d", SE{2, 1}, "%!d(BADINDEX)"}, - {"%3.[2]d", SE{7}, "%!d(BADINDEX)"}, - {"%.[2]d", SE{7}, "%!d(BADINDEX)"}, - {"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %!o(MISSING)"}, - {"%[5]d %[2]d %d", SE{1, 2, 3}, "%!d(BADINDEX) 2 3"}, - {"%d %[3]d %d", SE{1, 2}, "1 %!d(BADINDEX) 2"}, // Erroneous index does not affect sequence. -} - -func TestReorder(t *testing.T) { - for _, tt := range reorderTests { - s := Sprintf(tt.fmt, tt.val...) - if s != tt.out { - t.Errorf("Sprintf(%q, %v) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out) - } else { - } - } -} - -func BenchmarkSprintfEmpty(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("") - } - }) -} - -func BenchmarkSprintfString(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("%s", "hello") - } - }) -} - -func BenchmarkSprintfInt(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("%d", 5) - } - }) -} - -func BenchmarkSprintfIntInt(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("%d %d", 5, 6) - } - }) -} - -func BenchmarkSprintfPrefixedInt(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6) - } - }) -} - -func BenchmarkSprintfFloat(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - Sprintf("%g", 5.23184) - } - }) -} - -func BenchmarkManyArgs(b *testing.B) { - b.RunParallel(func(pb *testing.PB) { - var buf bytes.Buffer - for pb.Next() { - buf.Reset() - Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world") - } - }) -} - -var mallocBuf bytes.Buffer - -var mallocTest = []struct { - count int - desc string - fn func() -}{ - {0, `Sprintf("")`, func() { Sprintf("") }}, - {1, `Sprintf("xxx")`, func() { Sprintf("xxx") }}, - {1, `Sprintf("%x")`, func() { Sprintf("%x", 7) }}, - {2, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }}, - {1, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }}, - // For %g we use a float32, not float64, to guarantee passing the argument - // does not need to allocate memory to store the result in a pointer-sized word. - {2, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }}, - {0, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }}, - {1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }}, -} - -var _ bytes.Buffer - -func TestCountMallocs(t *testing.T) { - if testing.Short() { - t.Skip("skipping malloc count in short mode") - } - if runtime.GOMAXPROCS(0) > 1 { - t.Skip("skipping; GOMAXPROCS>1") - } - for _, mt := range mallocTest { - mallocs := testing.AllocsPerRun(100, mt.fn) - if got, max := mallocs, float64(mt.count); got > max { - t.Errorf("%s: got %v allocs, want <=%v", mt.desc, got, max) - } - } -} - -type flagPrinter struct{} - -func (*flagPrinter) Format(f State, c rune) { - 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) - } - } -} - -// presentInMap checks 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) - } -} - -// TestBlank checks 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) - } -} - -// TestBlankln checks 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) - } -} - -// TestFormatterPrintln checks 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) - } - } -} - -// Panic is 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) -} - -// PanicF is a type that panics in Format. -type PanicF struct { - message interface{} -} - -// Value receiver. -func (p PanicF) Format(f State, c rune) { - panic(p.message) -} - -var panictests = []struct { - fmt string - in interface{} - out string -}{ - // String - {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%s", Panic{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"}, - {"%s", Panic{3}, "%!s(PANIC=3)"}, - // GoString - {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case - {"%#v", Panic{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"}, - {"%#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) - } - } -} - -// recurCount tests that erroneous String routine doesn't cause fatal recursion. -var recurCount = 0 - -type Recur struct { - i int - failed *bool -} - -func (r *Recur) String() string { - if recurCount++; recurCount > 10 { - *r.failed = true - return "FAIL" - } - // This will call badVerb. Before the fix, that would cause us to recur into - // this routine to print %!p(value). Now we don't call the user's method - // during an error. - return Sprintf("recur@%p value: %d", r, r.i) -} - -func TestBadVerbRecursion(t *testing.T) { - failed := false - r := &Recur{3, &failed} - Sprintf("recur@%p value: %d\n", &r, r.i) - if failed { - t.Error("fail with pointer") - } - failed = false - r = &Recur{4, &failed} - Sprintf("recur@%p, value: %d\n", r, r.i) - if failed { - t.Error("fail with value") - } -} - -func TestIsSpace(t *testing.T) { - // This tests the internal isSpace function. - // IsSpace = isSpace is defined in export_test.go. - for i := rune(0); i <= unicode.MaxRune; i++ { - if IsSpace(i) != unicode.IsSpace(i) { - t.Errorf("isSpace(%U) = %v, want %v", i, IsSpace(i), unicode.IsSpace(i)) - } - } -} - -func TestNilDoesNotBecomeTyped(t *testing.T) { - type A struct{} - type B struct{} - var a *A = nil - var b B = B{} - got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil) - const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)" - if got != expect { - t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got) - } -} diff --git a/src/pkg/fmt/format.go b/src/pkg/fmt/format.go deleted file mode 100644 index a89c542cf..000000000 --- a/src/pkg/fmt/format.go +++ /dev/null @@ -1,492 +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 ( - "math" - "strconv" - "unicode/utf8" -) - -const ( - // %b of an int64, plus a sign. - // Hex can add 0x and we handle it specially. - nByte = 65 - - ldigits = "0123456789abcdef" - udigits = "0123456789ABCDEF" -) - -const ( - signed = true - unsigned = false -) - -var padZeroBytes = make([]byte, nByte) -var padSpaceBytes = make([]byte, nByte) - -func init() { - for i := 0; i < nByte; i++ { - padZeroBytes[i] = '0' - padSpaceBytes[i] = ' ' - } -} - -// A fmt is the raw formatter used by Printf etc. -// It prints into a buffer that must be set up separately. -type fmt struct { - intbuf [nByte]byte - buf *buffer - // width, precision - wid int - prec int - // 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 *buffer) { - f.buf = buf - f.clearflags() -} - -// computePadding computes left and right padding widths (only one will be non-zero). -func (f *fmt) computePadding(width int) (padding []byte, leftWidth, rightWidth int) { - left := !f.minus - w := f.wid - if w < 0 { - left = false - w = -w - } - w -= width - if w > 0 { - if left && f.zero { - return padZeroBytes, w, 0 - } - if left { - return padSpaceBytes, w, 0 - } else { - // can't be zero padding on the right - return padSpaceBytes, 0, w - } - } - return -} - -// writePadding generates n bytes of padding. -func (f *fmt) writePadding(n int, padding []byte) { - for n > 0 { - m := n - if m > nByte { - m = nByte - } - f.buf.Write(padding[0:m]) - n -= m - } -} - -// pad appends b to f.buf, padded on left (w > 0) or right (w < 0 or f.minus). -func (f *fmt) pad(b []byte) { - if !f.widPresent || f.wid == 0 { - f.buf.Write(b) - return - } - 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) - } -} - -// padString appends s to buf, padded on left (w > 0) or right (w < 0 or f.minus). -func (f *fmt) padString(s string) { - if !f.widPresent || f.wid == 0 { - f.buf.WriteString(s) - return - } - padding, left, right := f.computePadding(utf8.RuneCountInString(s)) - if left > 0 { - f.writePadding(left, padding) - } - f.buf.WriteString(s) - if right > 0 { - f.writePadding(right, padding) - } -} - -var ( - trueBytes = []byte("true") - falseBytes = []byte("false") -) - -// fmt_boolean formats a boolean. -func (f *fmt) fmt_boolean(v bool) { - if v { - f.pad(trueBytes) - } else { - f.pad(falseBytes) - } -} - -// integer; interprets prec but not wid. Once formatted, result is sent to pad() -// and then flags are cleared. -func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { - // precision of 0 and value of 0 means "print nothing" - if f.precPresent && f.prec == 0 && a == 0 { - return - } - - var buf []byte = f.intbuf[0:] - if f.widPresent { - width := f.wid - if base == 16 && f.sharp { - // Also adds "0x". - width += 2 - } - if width > nByte { - // We're going to need a bigger boat. - buf = make([]byte, width) - } - } - - 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(buf) - ua := uint64(a) - for ua >= base { - i-- - buf[i] = digits[ua%base] - ua /= base - } - i-- - buf[i] = digits[ua] - for i > 0 && prec > len(buf)-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 <= utf8.MaxRune && strconv.IsPrint(rune(a)) { - runeWidth := utf8.RuneLen(rune(a)) - width := 1 + 1 + runeWidth + 1 // space, quote, rune, quote - copy(buf[i-width:], buf[i:]) // guaranteed to have enough room. - i -= width - // Now put " 'x'" at the end. - j := len(buf) - width - buf[j] = ' ' - j++ - buf[j] = '\'' - j++ - utf8.EncodeRune(buf[j:], rune(a)) - j += runeWidth - buf[j] = '\'' - } - - 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_sbx formats a string or byte slice as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sbx(s string, b []byte, digits string) { - n := len(b) - if b == nil { - n = len(s) - } - x := digits[10] - 'a' + 'x' - // TODO: Avoid buffer by pre-padding. - var buf []byte - for i := 0; i < n; i++ { - if i > 0 && f.space { - buf = append(buf, ' ') - } - if f.sharp { - buf = append(buf, '0', x) - } - var c byte - if b == nil { - c = s[i] - } else { - c = b[i] - } - buf = append(buf, digits[c>>4], digits[c&0xF]) - } - f.pad(buf) -} - -// fmt_sx formats a string as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sx(s, digits string) { - f.fmt_sbx(s, nil, digits) -} - -// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_bx(b []byte, digits string) { - f.fmt_sbx("", b, digits) -} - -// 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 []byte - if f.plus { - quoted = strconv.AppendQuoteRuneToASCII(f.intbuf[0:0], rune(c)) - } else { - quoted = strconv.AppendQuoteRune(f.intbuf[0:0], rune(c)) - } - f.pad(quoted) -} - -// floating-point - -func doPrec(f *fmt, def int) int { - if f.precPresent { - return f.prec - } - return def -} - -// formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...). -func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { - // Format number, reserving space for leading + sign if needed. - num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) - if num[1] == '-' || num[1] == '+' { - num = num[1:] - } else { - num[0] = '+' - } - // Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros. - if math.IsInf(v, 0) { - if f.zero { - defer func() { f.zero = true }() - f.zero = false - } - } - // num is now a signed version of the number. - // If we're zero padding, want the sign before the leading zeros. - // Achieve this by writing the sign out and then padding the unsigned number. - if f.zero && f.widPresent && f.wid > len(num) { - if f.space && v >= 0 { - f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space. - f.wid-- - } else if f.plus || v < 0 { - f.buf.WriteByte(num[0]) - f.wid-- - } - f.pad(num[1:]) - return - } - // f.space says to replace a leading + with a space. - if f.space && num[0] == '+' { - num[0] = ' ' - f.pad(num) - return - } - // Now we know the sign is attached directly to the number, if present at all. - // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf). - if f.plus || num[0] == '-' || math.IsInf(v, 0) { - f.pad(num) - return - } - // No sign to show and the number is positive; just print the unsigned number. - f.pad(num[1:]) -} - -// fmt_e64 formats a float64 in the form -1.23e+12. -func (f *fmt) fmt_e64(v float64) { f.formatFloat(v, 'e', doPrec(f, 6), 64) } - -// fmt_E64 formats a float64 in the form -1.23E+12. -func (f *fmt) fmt_E64(v float64) { f.formatFloat(v, 'E', doPrec(f, 6), 64) } - -// fmt_f64 formats a float64 in the form -1.23. -func (f *fmt) fmt_f64(v float64) { f.formatFloat(v, 'f', doPrec(f, 6), 64) } - -// fmt_g64 formats a float64 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g64(v float64) { f.formatFloat(v, 'g', doPrec(f, -1), 64) } - -// fmt_G64 formats a float64 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G64(v float64) { f.formatFloat(v, 'G', doPrec(f, -1), 64) } - -// fmt_fb64 formats a float64 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb64(v float64) { f.formatFloat(v, 'b', 0, 64) } - -// float32 -// cannot defer to float64 versions -// because it will get rounding wrong in corner cases. - -// fmt_e32 formats a float32 in the form -1.23e+12. -func (f *fmt) fmt_e32(v float32) { f.formatFloat(float64(v), 'e', doPrec(f, 6), 32) } - -// fmt_E32 formats a float32 in the form -1.23E+12. -func (f *fmt) fmt_E32(v float32) { f.formatFloat(float64(v), 'E', doPrec(f, 6), 32) } - -// fmt_f32 formats a float32 in the form -1.23. -func (f *fmt) fmt_f32(v float32) { f.formatFloat(float64(v), 'f', doPrec(f, 6), 32) } - -// fmt_g32 formats a float32 in the 'f' or 'e' form according to size. -func (f *fmt) fmt_g32(v float32) { f.formatFloat(float64(v), 'g', doPrec(f, -1), 32) } - -// fmt_G32 formats a float32 in the 'f' or 'E' form according to size. -func (f *fmt) fmt_G32(v float32) { f.formatFloat(float64(v), 'G', doPrec(f, -1), 32) } - -// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2). -func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) } - -// fmt_c64 formats a complex64 according to the verb. -func (f *fmt) fmt_c64(v complex64, verb rune) { - f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb) -} - -// fmt_c128 formats a complex128 according to the verb. -func (f *fmt) fmt_c128(v complex128, verb rune) { - f.fmt_complex(real(v), imag(v), 64, verb) -} - -// fmt_complex formats a complex number as (r+ji). -func (f *fmt) fmt_complex(r, j float64, size int, verb rune) { - f.buf.WriteByte('(') - oldPlus := f.plus - oldSpace := f.space - oldWid := f.wid - for i := 0; ; i++ { - switch verb { - case 'b': - f.formatFloat(r, 'b', 0, size) - case 'e': - f.formatFloat(r, 'e', doPrec(f, 6), size) - case 'E': - f.formatFloat(r, 'E', doPrec(f, 6), size) - case 'f', 'F': - f.formatFloat(r, 'f', doPrec(f, 6), size) - case 'g': - f.formatFloat(r, 'g', doPrec(f, -1), size) - case 'G': - f.formatFloat(r, 'G', doPrec(f, -1), size) - } - if i != 0 { - break - } - // Imaginary part always has a sign. - f.plus = true - f.space = false - f.wid = oldWid - r = j - } - f.space = oldSpace - f.plus = oldPlus - f.wid = oldWid - f.buf.Write(irparenBytes) -} diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go deleted file mode 100644 index 302661f4c..000000000 --- a/src/pkg/fmt/print.go +++ /dev/null @@ -1,1199 +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 ( - "errors" - "io" - "os" - "reflect" - "sync" - "unicode/utf8" -) - -// Some constants in the form of bytes, to avoid string overhead. -// Needlessly fastidious, I suppose. -var ( - commaSpaceBytes = []byte(", ") - nilAngleBytes = []byte("<nil>") - nilParenBytes = []byte("(nil)") - nilBytes = []byte("nil") - mapBytes = []byte("map[") - percentBangBytes = []byte("%!") - missingBytes = []byte("(MISSING)") - badIndexBytes = []byte("(BADINDEX)") - panicBytes = []byte("(PANIC=") - extraBytes = []byte("%!(EXTRA ") - irparenBytes = []byte("i)") - bytesBytes = []byte("[]byte{") - badWidthBytes = []byte("%!(BADWIDTH)") - badPrecBytes = []byte("%!(BADPREC)") - noVerbBytes = []byte("%!(NOVERB)") -) - -// 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 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 reports 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 Sprint(f) or Fprint(f) etc. -// to generate its output. -type Formatter interface { - Format(f State, c rune) -} - -// 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 any format that accepts a string 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 -} - -// Use simple []byte instead of bytes.Buffer to avoid large dependency. -type buffer []byte - -func (b *buffer) Write(p []byte) (n int, err error) { - *b = append(*b, p...) - return len(p), nil -} - -func (b *buffer) WriteString(s string) (n int, err error) { - *b = append(*b, s...) - return len(s), nil -} - -func (b *buffer) WriteByte(c byte) error { - *b = append(*b, c) - return nil -} - -func (bp *buffer) WriteRune(r rune) error { - if r < utf8.RuneSelf { - *bp = append(*bp, byte(r)) - return nil - } - - b := *bp - n := len(b) - for n+utf8.UTFMax > cap(b) { - b = append(b, 0) - } - w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r) - *bp = b[:n+w] - return nil -} - -type pp struct { - n int - panicking bool - erroring bool // printing an error condition - buf buffer - // arg holds the current item, as an interface{}. - arg interface{} - // value holds the current item, as a reflect.Value, and will be - // the zero Value if the item has not been reflected. - value reflect.Value - // reordered records whether the format string used argument reordering. - reordered bool - // goodArgNum records whether the most recent reordering directive was valid. - goodArgNum bool - runeBuf [utf8.UTFMax]byte - fmt fmt -} - -var ppFree = sync.Pool{ - New: func() interface{} { return new(pp) }, -} - -// newPrinter allocates a new pp struct or grab a cached one. -func newPrinter() *pp { - p := ppFree.Get().(*pp) - p.panicking = false - p.erroring = false - p.fmt.init(&p.buf) - return p -} - -// free saves used pp structs in ppFree; avoids an allocation per invocation. -func (p *pp) free() { - // Don't hold on to pp structs with large buffers. - if cap(p.buf) > 1024 { - return - } - p.buf = p.buf[:0] - p.arg = nil - p.value = reflect.Value{} - 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 rune) { - p.buf.WriteRune(c) -} - -// Implement Write so we can call Fprintf on a pp (through State), for -// recursive use in custom verbs. -func (p *pp) Write(b []byte) (ret int, err error) { - return p.buf.Write(b) -} - -// 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 error) { - p := newPrinter() - p.doPrintf(format, a) - n, err = w.Write(p.buf) - p.free() - return -} - -// 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 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 := string(p.buf) - p.free() - return s -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -func Errorf(format string, a ...interface{}) error { - return errors.New(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 error) { - p := newPrinter() - p.doPrint(a, false, false) - n, err = w.Write(p.buf) - p.free() - return -} - -// 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 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 := string(p.buf) - 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 error) { - p := newPrinter() - p.doPrint(a, true, true) - n, err = w.Write(p.buf) - p.free() - return -} - -// 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 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 := string(p.buf) - p.free() - return s -} - -// getField gets the i'th field of the struct value. -// If the field is 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 val.Kind() == reflect.Interface && !val.IsNil() { - val = val.Elem() - } - return val -} - -// parsenum converts ASCII to integer. num is 0 (and isnum 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 rune) { - p.erroring = true - p.add('%') - p.add('!') - p.add(verb) - p.add('(') - switch { - case p.arg != nil: - p.buf.WriteString(reflect.TypeOf(p.arg).String()) - p.add('=') - p.printArg(p.arg, 'v', false, false, 0) - case p.value.IsValid(): - p.buf.WriteString(p.value.Type().String()) - p.add('=') - p.printValue(p.value, 'v', false, false, 0) - default: - p.buf.Write(nilAngleBytes) - } - p.add(')') - p.erroring = false -} - -func (p *pp) fmtBool(v bool, verb rune) { - switch verb { - case 't', 'v': - p.fmt.fmt_boolean(v) - default: - p.badVerb(verb) - } -} - -// fmtC formats a rune for the 'c' format. -func (p *pp) fmtC(c int64) { - r := rune(c) // Check for overflow. - if int64(r) != c { - r = utf8.RuneError - } - w := utf8.EncodeRune(p.runeBuf[0:utf8.UTFMax], r) - p.fmt.pad(p.runeBuf[0:w]) -} - -func (p *pp) fmtInt64(v int64, verb rune) { - switch verb { - case 'b': - p.fmt.integer(v, 2, signed, ldigits) - case 'c': - p.fmtC(v) - case 'd', 'v': - p.fmt.integer(v, 10, signed, ldigits) - case 'o': - p.fmt.integer(v, 8, signed, ldigits) - case 'q': - if 0 <= v && v <= utf8.MaxRune { - p.fmt.fmt_qc(v) - } else { - p.badVerb(verb) - } - case 'x': - p.fmt.integer(v, 16, signed, ldigits) - case 'U': - p.fmtUnicode(v) - case 'X': - p.fmt.integer(v, 16, signed, udigits) - default: - p.badVerb(verb) - } -} - -// fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or -// not, as requested, by temporarily setting the sharp flag. -func (p *pp) fmt0x64(v uint64, leading0x bool) { - sharp := p.fmt.sharp - p.fmt.sharp = leading0x - p.fmt.integer(int64(v), 16, unsigned, ldigits) - p.fmt.sharp = sharp -} - -// fmtUnicode formats a uint64 in U+1234 form by -// temporarily turning on the unicode flag and tweaking the precision. -func (p *pp) fmtUnicode(v int64) { - precPresent := p.fmt.precPresent - sharp := p.fmt.sharp - p.fmt.sharp = false - prec := p.fmt.prec - if !precPresent { - // If prec is already set, leave it alone; otherwise 4 is minimum. - p.fmt.prec = 4 - p.fmt.precPresent = true - } - p.fmt.unicode = true // turn on U+ - p.fmt.uniQuote = sharp - p.fmt.integer(int64(v), 16, unsigned, udigits) - p.fmt.unicode = false - p.fmt.uniQuote = false - p.fmt.prec = prec - p.fmt.precPresent = precPresent - p.fmt.sharp = sharp -} - -func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) { - 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 <= utf8.MaxRune { - p.fmt.fmt_qc(int64(v)) - } else { - p.badVerb(verb) - } - case 'x': - p.fmt.integer(int64(v), 16, unsigned, ldigits) - case 'X': - p.fmt.integer(int64(v), 16, unsigned, udigits) - case 'U': - p.fmtUnicode(int64(v)) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtFloat32(v float32, verb rune) { - switch verb { - case 'b': - p.fmt.fmt_fb32(v) - case 'e': - p.fmt.fmt_e32(v) - case 'E': - p.fmt.fmt_E32(v) - case 'f', 'F': - p.fmt.fmt_f32(v) - case 'g', 'v': - p.fmt.fmt_g32(v) - case 'G': - p.fmt.fmt_G32(v) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtFloat64(v float64, verb rune) { - switch verb { - case 'b': - p.fmt.fmt_fb64(v) - case 'e': - p.fmt.fmt_e64(v) - case 'E': - p.fmt.fmt_E64(v) - case 'f', 'F': - p.fmt.fmt_f64(v) - case 'g', 'v': - p.fmt.fmt_g64(v) - case 'G': - p.fmt.fmt_G64(v) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtComplex64(v complex64, verb rune) { - switch verb { - case 'b', 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c64(v, verb) - case 'v': - p.fmt.fmt_c64(v, 'g') - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtComplex128(v complex128, verb rune) { - switch verb { - case 'b', 'e', 'E', 'f', 'F', 'g', 'G': - p.fmt.fmt_c128(v, verb) - case 'v': - p.fmt.fmt_c128(v, 'g') - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtString(v string, verb rune, goSyntax bool) { - 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, ldigits) - case 'X': - p.fmt.fmt_sx(v, udigits) - case 'q': - p.fmt.fmt_q(v) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) { - if verb == 'v' || verb == 'd' { - if goSyntax { - if v == nil { - if typ == nil { - p.buf.WriteString("[]byte(nil)") - } else { - p.buf.WriteString(typ.String()) - p.buf.Write(nilParenBytes) - } - return - } - if typ == nil { - p.buf.Write(bytesBytes) - } else { - p.buf.WriteString(typ.String()) - p.buf.WriteByte('{') - } - } else { - p.buf.WriteByte('[') - } - for i, c := range v { - if i > 0 { - if goSyntax { - p.buf.Write(commaSpaceBytes) - } else { - p.buf.WriteByte(' ') - } - } - p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - return - } - switch verb { - case 's': - p.fmt.fmt_s(string(v)) - case 'x': - p.fmt.fmt_bx(v, ldigits) - case 'X': - p.fmt.fmt_bx(v, udigits) - case 'q': - p.fmt.fmt_q(string(v)) - default: - p.badVerb(verb) - } -} - -func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { - use0x64 := true - switch verb { - case 'p', 'v': - // ok - case 'b', 'd', 'o', 'x', 'X': - use0x64 = false - // ok - default: - p.badVerb(verb) - return - } - - var u uintptr - switch value.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - u = value.Pointer() - default: - p.badVerb(verb) - return - } - - if goSyntax { - p.add('(') - p.buf.WriteString(value.Type().String()) - p.add(')') - p.add('(') - if u == 0 { - p.buf.Write(nilBytes) - } else { - p.fmt0x64(uint64(u), true) - } - p.add(')') - } else if verb == 'v' && u == 0 { - p.buf.Write(nilAngleBytes) - } else { - if use0x64 { - p.fmt0x64(uint64(u), !p.fmt.sharp) - } else { - p.fmtUint64(uint64(u), verb, false) - } - } -} - -var ( - intBits = reflect.TypeOf(0).Bits() - uintptrBits = reflect.TypeOf(uintptr(0)).Bits() -) - -func (p *pp) catchPanic(arg interface{}, verb rune) { - if err := recover(); err != nil { - // If it's a nil pointer, just say "<nil>". The likeliest causes are a - // Stringer that fails to guard against nil or a nil pointer for a - // value receiver, and in either case, "<nil>" is a nice result. - if v := reflect.ValueOf(arg); v.Kind() == reflect.Ptr && v.IsNil() { - p.buf.Write(nilAngleBytes) - 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 printArg cannot succeed. - panic(err) - } - p.buf.Write(percentBangBytes) - p.add(verb) - p.buf.Write(panicBytes) - p.panicking = true - p.printArg(err, 'v', false, false, 0) - p.panicking = false - p.buf.WriteByte(')') - } -} - -func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) { - if p.erroring { - return - } - // Is it a Formatter? - if formatter, ok := p.arg.(Formatter); ok { - handled = true - wasString = false - defer p.catchPanic(p.arg, verb) - formatter.Format(p, verb) - return - } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } - - // If we're doing Go syntax and the argument knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false - if stringer, ok := p.arg.(GoStringer); ok { - wasString = false - handled = true - defer p.catchPanic(p.arg, verb) - // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false) - return - } - } else { - // If a string is acceptable according to the format, see if - // the value satisfies one of the string-valued interfaces. - // Println etc. set verb to %v, which is "stringable". - switch verb { - case 'v', 's', 'x', 'X', 'q': - // Is it an error or Stringer? - // The duplication in the bodies is necessary: - // setting wasString and handled, and deferring catchPanic, - // must happen before calling the method. - switch v := p.arg.(type) { - case error: - wasString = false - handled = true - defer p.catchPanic(p.arg, verb) - p.printArg(v.Error(), verb, plus, false, depth) - return - - case Stringer: - wasString = false - handled = true - defer p.catchPanic(p.arg, verb) - p.printArg(v.String(), verb, plus, false, depth) - return - } - } - } - handled = false - return -} - -func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) { - p.arg = arg - p.value = reflect.Value{} - - if arg == nil { - if verb == 'T' || verb == 'v' { - p.fmt.pad(nilAngleBytes) - } else { - p.badVerb(verb) - } - return false - } - - // Special processing considerations. - // %T (the value's type) and %p (its address) are special; we always do them first. - switch verb { - case 'T': - p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0) - return false - case 'p': - p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax) - return false - } - - // Clear flags for base formatters. - // handleMethods needs them, so we must restore them later. - // We could call handleMethods here and avoid this work, but - // handleMethods is expensive enough to be worth delaying. - oldPlus := p.fmt.plus - oldSharp := p.fmt.sharp - if plus { - p.fmt.plus = false - } - if goSyntax { - p.fmt.sharp = false - } - - // Some types can be done without reflection. - switch f := arg.(type) { - case bool: - p.fmtBool(f, verb) - case float32: - p.fmtFloat32(f, verb) - case float64: - p.fmtFloat64(f, verb) - case complex64: - p.fmtComplex64(f, verb) - case complex128: - p.fmtComplex128(f, verb) - case int: - p.fmtInt64(int64(f), verb) - case int8: - p.fmtInt64(int64(f), verb) - case int16: - p.fmtInt64(int64(f), verb) - case int32: - p.fmtInt64(int64(f), verb) - case int64: - p.fmtInt64(f, verb) - case uint: - p.fmtUint64(uint64(f), verb, goSyntax) - case uint8: - p.fmtUint64(uint64(f), verb, goSyntax) - case uint16: - p.fmtUint64(uint64(f), verb, goSyntax) - case uint32: - p.fmtUint64(uint64(f), verb, goSyntax) - case uint64: - p.fmtUint64(f, verb, goSyntax) - case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax) - case string: - p.fmtString(f, verb, goSyntax) - wasString = verb == 's' || verb == 'v' - case []byte: - p.fmtBytes(f, verb, goSyntax, nil, depth) - wasString = verb == 's' - default: - // Restore flags in case handleMethods finds a Formatter. - p.fmt.plus = oldPlus - p.fmt.sharp = oldSharp - // If the type is not simple, it might have methods. - if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return isString - } - // Need to use reflection - return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth) - } - p.arg = nil - return -} - -// printValue is like printArg but starts with a reflect value, not an interface{} value. -func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) { - if !value.IsValid() { - if verb == 'T' || verb == 'v' { - p.buf.Write(nilAngleBytes) - } else { - p.badVerb(verb) - } - return false - } - - // Special processing considerations. - // %T (the value's type) and %p (its address) are special; we always do them first. - switch verb { - case 'T': - p.printArg(value.Type().String(), 's', false, false, 0) - return false - case 'p': - p.fmtPointer(value, verb, goSyntax) - return false - } - - // Handle values with special methods. - // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us. - p.arg = nil // Make sure it's cleared, for safety. - if value.CanInterface() { - p.arg = value.Interface() - } - if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return isString - } - - return p.printReflectValue(value, verb, plus, goSyntax, depth) -} - -// printReflectValue is the fallback for both printArg and printValue. -// It uses reflect to print the value. -func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) { - oldValue := p.value - p.value = value -BigSwitch: - switch f := value; f.Kind() { - case reflect.Bool: - p.fmtBool(f.Bool(), verb) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - p.fmtInt64(f.Int(), verb) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(f.Uint(), verb, goSyntax) - case reflect.Float32, reflect.Float64: - if f.Type().Size() == 4 { - p.fmtFloat32(float32(f.Float()), verb) - } else { - p.fmtFloat64(f.Float(), verb) - } - case reflect.Complex64, reflect.Complex128: - if f.Type().Size() == 8 { - p.fmtComplex64(complex64(f.Complex()), verb) - } else { - p.fmtComplex128(f.Complex(), verb) - } - case reflect.String: - p.fmtString(f.String(), verb, goSyntax) - case reflect.Map: - if goSyntax { - p.buf.WriteString(f.Type().String()) - if f.IsNil() { - p.buf.WriteString("(nil)") - break - } - 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.printValue(key, verb, plus, goSyntax, depth+1) - p.buf.WriteByte(':') - p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1) - } - if goSyntax { - p.buf.WriteByte('}') - } else { - p.buf.WriteByte(']') - } - case reflect.Struct: - if goSyntax { - p.buf.WriteString(value.Type().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.printValue(getField(v, i), verb, plus, goSyntax, depth+1) - } - p.buf.WriteByte('}') - case reflect.Interface: - value := f.Elem() - if !value.IsValid() { - if goSyntax { - p.buf.WriteString(f.Type().String()) - p.buf.Write(nilParenBytes) - } else { - p.buf.Write(nilAngleBytes) - } - } else { - wasString = p.printValue(value, verb, plus, goSyntax, depth+1) - } - case reflect.Array, reflect.Slice: - // Byte slices are special. - if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 { - var bytes []byte - if f.Kind() == reflect.Slice { - bytes = f.Bytes() - } else if f.CanAddr() { - bytes = f.Slice(0, f.Len()).Bytes() - } else { - // We have an array, but we cannot Slice() a non-addressable array, - // so we build a slice by hand. This is a rare case but it would be nice - // if reflection could help a little more. - bytes = make([]byte, f.Len()) - for i := range bytes { - bytes[i] = byte(f.Index(i).Uint()) - } - } - p.fmtBytes(bytes, verb, goSyntax, typ, depth) - wasString = verb == 's' - break - } - if goSyntax { - p.buf.WriteString(value.Type().String()) - if f.Kind() == reflect.Slice && f.IsNil() { - p.buf.WriteString("(nil)") - break - } - 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.printValue(f.Index(i), 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.printValue(a, verb, plus, goSyntax, depth+1) - break BigSwitch - case reflect.Struct: - p.buf.WriteByte('&') - p.printValue(a, verb, plus, goSyntax, depth+1) - break BigSwitch - } - } - fallthrough - case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(value, verb, goSyntax) - default: - p.unknownType(f) - } - p.value = oldValue - return wasString -} - -// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has type int. -func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) { - newArgNum = argNum - if argNum < len(a) { - num, isInt = a[argNum].(int) - newArgNum = argNum + 1 - } - return -} - -// parseArgNumber returns the value of the bracketed number, minus 1 -// (explicit argument numbers are one-indexed but we want zero-indexed). -// The opening bracket is known to be present at format[0]. -// The returned values are the index, the number of bytes to consume -// up to the closing paren, if present, and whether the number parsed -// ok. The bytes to consume will be 1 if no closing paren is present. -func parseArgNumber(format string) (index int, wid int, ok bool) { - // Find closing bracket. - for i := 1; i < len(format); i++ { - if format[i] == ']' { - width, ok, newi := parsenum(format, 1, i) - if !ok || newi != i { - return 0, i + 1, false - } - return width - 1, i + 1, true // arg numbers are one-indexed and skip paren. - } - } - return 0, 1, false -} - -// argNumber returns the next argument to evaluate, which is either the value of the passed-in -// argNum or the value of the bracketed integer that begins format[i:]. It also returns -// the new value of i, that is, the index of the next byte of the format to process. -func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) { - if len(format) <= i || format[i] != '[' { - return argNum, i, false - } - p.reordered = true - index, wid, ok := parseArgNumber(format[i:]) - if ok && 0 <= index && index < numArgs { - return index, i + wid, true - } - p.goodArgNum = false - return argNum, i + wid, true -} - -func (p *pp) doPrintf(format string, a []interface{}) { - end := len(format) - argNum := 0 // we process one argument per non-trivial format - afterIndex := false // previous item in format was an index like [3]. - p.reordered = false - for i := 0; i < end; { - p.goodArgNum = true - 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++ - - // Do we have flags? - 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 an explicit argument index? - argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) - - // Do we have width? - if i < end && format[i] == '*' { - i++ - p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum) - if !p.fmt.widPresent { - p.buf.Write(badWidthBytes) - } - afterIndex = false - } else { - p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end) - if afterIndex && p.fmt.widPresent { // "%[3]2d" - p.goodArgNum = false - } - } - - // Do we have precision? - if i+1 < end && format[i] == '.' { - i++ - if afterIndex { // "%[3].2d" - p.goodArgNum = false - } - argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) - if format[i] == '*' { - i++ - p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum) - if !p.fmt.precPresent { - p.buf.Write(badPrecBytes) - } - afterIndex = false - } else { - p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end) - if !p.fmt.precPresent { - p.fmt.prec = 0 - p.fmt.precPresent = true - } - } - } - - if !afterIndex { - argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a)) - } - - 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 !p.goodArgNum { - p.buf.Write(percentBangBytes) - p.add(c) - p.buf.Write(badIndexBytes) - continue - } else if argNum >= len(a) { // out of operands - p.buf.Write(percentBangBytes) - p.add(c) - p.buf.Write(missingBytes) - continue - } - arg := a[argNum] - argNum++ - - goSyntax := c == 'v' && p.fmt.sharp - plus := c == 'v' && p.fmt.plus - p.printArg(arg, c, plus, goSyntax, 0) - } - - // Check for extra arguments unless the call accessed the arguments - // out of order, in which case it's too expensive to detect if they've all - // been used and arguably OK if they're not. - if !p.reordered && argNum < len(a) { - p.buf.Write(extraBytes) - for ; argNum < len(a); argNum++ { - arg := a[argNum] - if arg != nil { - p.buf.WriteString(reflect.TypeOf(arg).String()) - p.buf.WriteByte('=') - } - p.printArg(arg, 'v', false, false, 0) - if argNum+1 < len(a) { - p.buf.Write(commaSpaceBytes) - } - } - p.buf.WriteByte(')') - } -} - -func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { - prevString := false - for argNum := 0; argNum < len(a); argNum++ { - p.fmt.clearflags() - // always add spaces if we're doing Println - arg := a[argNum] - if argNum > 0 { - isString := arg != nil && reflect.TypeOf(arg).Kind() == reflect.String - if addspace || !isString && !prevString { - p.buf.WriteByte(' ') - } - } - prevString = p.printArg(arg, '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 8a337e479..000000000 --- a/src/pkg/fmt/scan.go +++ /dev/null @@ -1,1168 +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 ( - "errors" - "io" - "math" - "os" - "reflect" - "strconv" - "sync" - "unicode/utf8" -) - -// runeUnreader is the interface to something that can unread runes. -// If the object provided to Scan does not satisfy this interface, -// a local buffer will be used to back up the input, but its contents -// will be lost when Scan returns. -type runeUnreader interface { - UnreadRune() error -} - -// ScanState represents the scanner state passed to custom scanners. -// Scanners may do rune-at-a-time scanning or ask the ScanState -// to discover the next space-delimited token. -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() (r rune, size int, err error) - // UnreadRune causes the next call to ReadRune to return the same rune. - UnreadRune() 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(rune) bool) (token []byte, err 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 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 rune) error -} - -// Scan scans text read from standard input, storing successive -// space-separated values into successive arguments. Newlines count -// as space. It returns the number of items successfully scanned. -// If that is less than the number of arguments, err will report why. -func Scan(a ...interface{}) (n int, err error) { - return Fscan(os.Stdin, a...) -} - -// 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 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 error) { - return Fscanf(os.Stdin, format, a...) -} - -type stringReader string - -func (r *stringReader) Read(b []byte) (n int, err error) { - n = copy(b, *r) - *r = (*r)[n:] - if n == 0 { - err = io.EOF - } - return -} - -// 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 error) { - return Fscan((*stringReader)(&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 error) { - return Fscanln((*stringReader)(&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 error) { - return Fscanf((*stringReader)(&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 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 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 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 error -} - -const eof = -1 - -// ss is the internal implementation of ScanState. -type ss struct { - rr io.RuneReader // where to read input - buf buffer // token accumulator - peekRune rune // one-rune lookahead - prevRune rune // last rune returned by ReadRune - count int // runes consumed so far. - atEOF bool // already read EOF - 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 - argLimit int // max value of ss.count for this arg; argLimit <= limit - limit int // max value of ss.count. - maxWid int // width of this arg. -} - -// 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 error) { - return 0, errors.New("ScanState's Read should not be called. Use ReadRune") -} - -func (s *ss) ReadRune() (r rune, size int, err error) { - if s.peekRune >= 0 { - s.count++ - r = s.peekRune - size = utf8.RuneLen(r) - s.prevRune = r - s.peekRune = -1 - return - } - if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.argLimit { - err = io.EOF - return - } - - r, size, err = s.rr.ReadRune() - if err == nil { - s.count++ - s.prevRune = r - } else if err == io.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() (r rune) { - r, _, err := s.ReadRune() - if err != nil { - if err == io.EOF { - return eof - } - s.error(err) - } - return -} - -// mustReadRune turns io.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() (r rune) { - r = s.getRune() - if r == eof { - s.error(io.ErrUnexpectedEOF) - } - return -} - -func (s *ss) UnreadRune() 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 error) { - panic(scanError{err}) -} - -func (s *ss) errorString(err string) { - panic(scanError{errors.New(err)}) -} - -func (s *ss) Token(skipSpace bool, f func(rune) bool) (tok []byte, err 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 = s.buf[:0] - tok = s.token(skipSpace, f) - return -} - -// space is a copy of the unicode.White_Space ranges, -// to avoid depending on package unicode. -var space = [][2]uint16{ - {0x0009, 0x000d}, - {0x0020, 0x0020}, - {0x0085, 0x0085}, - {0x00a0, 0x00a0}, - {0x1680, 0x1680}, - {0x2000, 0x200a}, - {0x2028, 0x2029}, - {0x202f, 0x202f}, - {0x205f, 0x205f}, - {0x3000, 0x3000}, -} - -func isSpace(r rune) bool { - if r >= 1<<16 { - return false - } - rx := uint16(r) - for _, rng := range space { - if rx < rng[0] { - return false - } - if rx <= rng[1] { - return true - } - } - return false -} - -// notSpace is the default scanning function used in Token. -func notSpace(r rune) bool { - return !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 error) { - if r.pending > 0 { - b = r.pendBuf[0] - copy(r.pendBuf[0:], r.pendBuf[1:]) - r.pending-- - return - } - n, err := io.ReadFull(r.reader, r.pendBuf[0:1]) - if n != 1 { - return 0, err - } - return r.pendBuf[0], err -} - -// unread saves the bytes for the next read. -func (r *readRune) unread(buf []byte) { - copy(r.pendBuf[r.pending:], buf) - r.pending += len(buf) -} - -// ReadRune returns the next UTF-8 encoded code point from the -// io.Reader inside r. -func (r *readRune) ReadRune() (rr rune, size int, err error) { - 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 - rr = rune(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 == io.EOF { - err = nil - break - } - return - } - } - rr, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) - } - return -} - -var ssFree = sync.Pool{ - New: func() interface{} { return new(ss) }, -} - -// newScanState allocates 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.argLimit - 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.argLimit = hugeWid - s.maxWid = hugeWid - s.validSave = true - s.count = 0 - return -} - -// free saves 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) > 1024 { - return - } - s.buf = s.buf[:0] - s.rr = nil - ssFree.Put(s) -} - -// skipSpace skips spaces and maybe newlines. -func (s *ss) skipSpace(stopAtNewline bool) { - for { - r := s.getRune() - if r == eof { - return - } - if r == '\r' && s.peek("\n") { - continue - } - if r == '\n' { - if stopAtNewline { - break - } - if s.nlIsSpace { - continue - } - s.errorString("unexpected newline") - return - } - if !isSpace(r) { - 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(rune) bool) []byte { - if skipSpace { - s.skipSpace(false) - } - // read until white space or newline - for { - r := s.getRune() - if r == eof { - break - } - if !f(r) { - s.UnreadRune() - break - } - s.buf.WriteRune(r) - } - return s.buf -} - -var complexError = errors.New("syntax error scanning complex number") -var boolError = errors.New("syntax error scanning boolean") - -func indexRune(s string, r rune) int { - for i, c := range s { - if c == r { - return i - } - } - return -1 -} - -// 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 { - r := s.getRune() - if r == eof { - return false - } - if indexRune(ok, r) >= 0 { - if accept { - s.buf.WriteRune(r) - } - return true - } - if r != 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 { - r := s.getRune() - if r != eof { - s.UnreadRune() - } - return indexRune(ok, r) >= 0 -} - -func (s *ss) notEOF() { - // Guarantee there is data to be read. - if r := s.getRune(); r == eof { - panic(io.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 rune, 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 rune) 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("aA") && (!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 rune) (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 { - if !haveDigits { - s.notEOF() - if !s.accept(digits) { - s.errorString("expected integer") - } - } - for s.accept(digits) { - } - return string(s.buf) -} - -// scanRune returns the next rune value in the input. -func (s *ss) scanRune(bitSize int) int64 { - s.notEOF() - r := int64(s.getRune()) - n := uint(bitSize) - x := (r << (64 - n)) >> (64 - n) - if x != r { - s.errorString("overflow on character value " + string(r)) - } - return r -} - -// 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 rune, 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.ParseInt(tok, base, 64) - 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 rune, 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.ParseUint(tok, base, 64) - 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 = s.buf[:0] - // NaN? - if s.accept("nN") && s.accept("aA") && s.accept("nN") { - return string(s.buf) - } - // leading sign? - s.accept(sign) - // Inf? - if s.accept("iI") && s.accept("nN") && s.accept("fF") { - return string(s.buf) - } - // 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 string(s.buf) -} - -// 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 = s.buf[:0] - // Must now have a sign. - if !s.accept("+-") { - s.error(complexError) - } - // Sign is now in buffer - imagSign := string(s.buf) - 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 := indexRune(str, 'p'); p >= 0 { - // Atof doesn't handle power-of-2 exponents, - // but they're easy to evaluate. - f, err := strconv.ParseFloat(str[:p], n) - if err != nil { - // Put full string into error. - if e, ok := err.(*strconv.NumError); ok { - e.Num = str - } - s.error(err) - } - m, 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, m) - } - f, err := strconv.ParseFloat(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 rune, 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 rune) (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 { - r := s.mustReadRune() - if r == quote { - break - } - s.buf.WriteRune(r) - } - return string(s.buf) - case '"': - // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) - for { - r := s.mustReadRune() - s.buf.WriteRune(r) - if r == '\\' { - // 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. - s.buf.WriteRune(s.mustReadRune()) - } else if r == '"' { - break - } - } - result, err := strconv.Unquote(string(s.buf)) - 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(d rune) int { - digit := int(d) - 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("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 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 len(s.buf) == 0 { - s.errorString("no hex data for %x string") - return "" - } - return string(s.buf) -} - -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 rune, arg interface{}) { - s.buf = s.buf[:0] - var err error - // If the parameter has its own Scan method, use that. - if v, ok := arg.(Scanner); ok { - err = v.Scan(s, verb) - if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - s.error(err) - } - return - } - - switch v := arg.(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("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("can't scan 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("can't scan type: " + val.Type().String()) - } - } -} - -// errorHandler turns local panics into error returns. -func errorHandler(errp *error) { - if e := recover(); e != nil { - if se, ok := e.(scanError); ok { // catch local error - *errp = se.err - } else if eof, ok := e.(error); ok && eof == io.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 error) { - defer errorHandler(&err) - for _, arg := range a { - s.scanOne('v', arg) - numProcessed++ - } - // Check for newline if required. - if !s.nlIsSpace { - for { - r := s.getRune() - if r == '\n' || r == eof { - break - } - if !isSpace(r) { - s.errorString("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 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 || inputc == '\n' { - // If we've reached a newline, stop now; don't read ahead. - return - } - if !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 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.argLimit = s.limit - if f := s.count + s.maxWid; f < s.argLimit { - s.argLimit = 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 - } - arg := a[numProcessed] - - s.scanOne(c, arg) - numProcessed++ - s.argLimit = 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 d903f0c3f..000000000 --- a/src/pkg/fmt/scan_test.go +++ /dev/null @@ -1,960 +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" - "errors" - . "fmt" - "io" - "math" - "reflect" - "regexp" - "strings" - "testing" - "unicode/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 - bytesVal []byte - runeVal rune - 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 rune) error { - tok, err := state.Token(true, func(r rune) bool { return r == verb }) - if err != nil { - return err - } - s := string(tok) - if !regexp.MustCompile("^" + string(verb) + "+$").MatchString(s) { - return errors.New("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 rune) 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 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"}, - - // Carriage-return followed by newline. (We treat \r\n as \n always.) - {"hello\r\n", &stringVal, "hello"}, - {"27\r\n", &uint8Val, uint8(27)}, - - // 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", &runeVal, 'a'}, - {"%c", "\u5072\n", &runeVal, '\u5072'}, - {"%c", "\u1234\n", &runeVal, '\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" - {"%v", "0", &intVal, 0}, // was: "EOF"; 0 was taken as base prefix and not counted. - {"%v", "0", &uintVal, uint(0)}, // was: "EOF"; 0 was taken as base prefix and not counted. -} - -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 truth bool -var i, j, k int -var f float64 -var s, t string -var c complex128 -var x, y Xs -var z IntString -var r1, r2, r3 rune - -var multiTests = []ScanfMultiTest{ - {"", "", []interface{}{}, []interface{}{}, ""}, - {"%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(&r1, &r2, &r3), 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(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""}, - - // Fixed bugs - {"%v%v", "FALSE23", args(&truth, &i), args(false, 23), ""}, -} - -func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) { - 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.Error()) { - 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.Error(), 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.Error(), "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.Error(), "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.Error(), "newline") < 0 { - t.Errorf("expected newline error scanning string with extra newline, got: %s", err) - } -} - -// eofCounter is a 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 error) { - n, err = ec.reader.Read(b) - if n == 0 { - ec.eofCount++ - } - return -} - -// TestEOF verifies 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) - } -} - -// TestEOFAtEndOfInput verifies 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 != io.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 != io.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 != io.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 != io.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 != io.EOF { - t.Errorf("#%d: %s %T not eof on trailing blanks: %s", i, test.format, test.v, err) - } - } -} - -// TestUnreadRuneWithBufio verifies 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 - -// Scan attempts to read two lines into the object. Scanln should prevent this -// because it stops at newline; Scan and Scanf should be fine. -func (t *TwoLines) Scan(state ScanState, verb rune) error { - chars := make([]rune, 0, 100) - 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) - } -} - -// simpleReader is a strings.Reader that implements only Read, not ReadRune. -// Good for testing readahead. -type simpleReader struct { - sr *strings.Reader -} - -func (s *simpleReader) Read(b []byte) (n int, err error) { - return s.sr.Read(b) -} - -// TestLineByLineFscanf tests that Fscanf does not read past newline. Issue -// 3481. -func TestLineByLineFscanf(t *testing.T) { - r := &simpleReader{strings.NewReader("1\n2\n")} - var i, j int - n, err := Fscanf(r, "%v\n", &i) - if n != 1 || err != nil { - t.Fatalf("first read: %d %q", n, err) - } - n, err = Fscanf(r, "%v\n", &j) - if n != 1 || err != nil { - t.Fatalf("second read: %d %q", n, err) - } - if i != 1 || j != 2 { - t.Errorf("wrong values; wanted 1 2 got %d %d", i, j) - } -} - -// RecursiveInt accepts a 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 rune) (err error) { - _, err = Fscan(state, &r.i) - if err != nil { - return - } - next := new(RecursiveInt) - _, err = Fscanf(state, ".%v", next) - if err != nil { - if err == io.ErrUnexpectedEOF { - err = nil - } - return - } - r.next = next - return -} - -// scanInts performs 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 error) { - r.next = nil - _, err = Fscan(b, &r.i) - if err != nil { - return - } - c, _, err := b.ReadRune() - if err != nil { - if err == io.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 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) 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\"") -} |