summaryrefslogtreecommitdiff
path: root/src/pkg/fmt
diff options
context:
space:
mode:
authorTianon Gravi <admwiggin@gmail.com>2015-01-15 11:54:00 -0700
committerTianon Gravi <admwiggin@gmail.com>2015-01-15 11:54:00 -0700
commitf154da9e12608589e8d5f0508f908a0c3e88a1bb (patch)
treef8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/fmt
parent8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff)
downloadgolang-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.go272
-rw-r--r--src/pkg/fmt/export_test.go7
-rw-r--r--src/pkg/fmt/fmt_test.go1147
-rw-r--r--src/pkg/fmt/format.go492
-rw-r--r--src/pkg/fmt/print.go1199
-rw-r--r--src/pkg/fmt/scan.go1168
-rw-r--r--src/pkg/fmt/scan_test.go960
-rw-r--r--src/pkg/fmt/stringer_test.go61
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\"")
-}