aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/fmt
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-01-14 00:05:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-01-14 00:05:42 +0000
commitc2047754c300b68c05d65faa8dc2925fe67b71b4 (patch)
treee183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/fmt
parent829afb8f05602bb31c9c597b24df7377fed4f059 (diff)
downloadgcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.zip
gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.gz
gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.bz2
libgo: update to Go 1.8 release candidate 1
Compiler changes: * Change map assignment to use mapassign and assign value directly. * Change string iteration to use decoderune, faster for ASCII strings. * Change makeslice to take int, and use makeslice64 for larger values. * Add new noverflow field to hmap struct used for maps. Unresolved problems, to be fixed later: * Commented out test in go/types/sizes_test.go that doesn't compile. * Commented out reflect.TestStructOf test for padding after zero-sized field. Reviewed-on: https://go-review.googlesource.com/35231 gotools/: Updates for Go 1.8rc1. * Makefile.am (go_cmd_go_files): Add bug.go. (s-zdefaultcc): Write defaultPkgConfig. * Makefile.in: Rebuild. From-SVN: r244456
Diffstat (limited to 'libgo/go/fmt')
-rw-r--r--libgo/go/fmt/doc.go70
-rw-r--r--libgo/go/fmt/export_test.go1
-rw-r--r--libgo/go/fmt/fmt_test.go55
-rw-r--r--libgo/go/fmt/format.go2
-rw-r--r--libgo/go/fmt/print.go31
-rw-r--r--libgo/go/fmt/scan.go96
-rw-r--r--libgo/go/fmt/scan_test.go143
7 files changed, 303 insertions, 95 deletions
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index c312914..a2faecb 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -48,13 +48,10 @@
Pointer:
%p base 16 notation, with leading 0x
- There is no 'u' flag. Integers are printed unsigned if they have unsigned type.
- Similarly, there is no need to specify the size of the operand (int8, int64).
-
The default format for %v is:
bool: %t
int, int8 etc.: %d
- uint, uint8 etc.: %d, %x if printed with %#v
+ uint, uint8 etc.: %d, %#x if printed with %#v
float32, complex64, etc: %g
string: %s
chan: %p
@@ -177,6 +174,9 @@
that type has a String method. Such pathologies are rare, however,
and the package does not protect against them.
+ When printing a struct, fmt cannot and therefore does not invoke
+ formatting methods such as Error or String on unexported fields.
+
Explicit argument indexes:
In Printf, Sprintf, and Fprintf, the default behavior is for each
@@ -247,31 +247,42 @@
Scanln, Fscanln and Sscanln stop scanning at a newline and
require that the items be followed by a newline or EOF.
- Scanf, Fscanf and Sscanf require that (after skipping spaces)
- newlines in the format are matched by newlines in the input
- and vice versa. This behavior differs from the corresponding
- routines in C, which uniformly treat newlines as spaces.
-
- When scanning with Scanf, Fscanf, and Sscanf, 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.
-
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.
+ format string, analogous to that of Printf. In the text that
+ follows, 'space' means any Unicode whitespace character
+ except newline.
+
+ In the format string, a verb introduced by the % character
+ consumes and parses input; these verbs are described in more
+ detail below. A character other than %, space, or newline in
+ the format consumes exactly that input character, which must
+ be present. A newline with zero or more spaces before it in
+ the format string consumes zero or more spaces in the input
+ followed by a single newline or the end of the input. A space
+ following a newline in the format string consumes zero or more
+ spaces in the input. Otherwise, any run of one or more spaces
+ in the format string consumes as many spaces as possible in
+ the input. Unless the run of spaces in the format string
+ appears adjacent to a newline, the run must consume at least
+ one space from the input or find the end of the input.
+
+ The handling of spaces and newlines differs from that of C's
+ scanf family: in C, newlines are treated as any other space,
+ and it is never an error when a run of spaces in the format
+ string finds no spaces to consume in the input.
+
+ The verbs behave analogously to those 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 Printf verbs %p and %T and the flags # and + are not implemented,
+ and the verbs %e %E %f %F %g and %G are all equivalent and scan any
+ floating-point or complex value.
+
+ Input processed by verbs is implicitly space-delimited: the
+ implementation of every verb except %c starts by discarding
+ leading spaces from the remaining input, and the %s verb
+ (and %v reading into a string) stops consuming input at the first
+ space or newline character.
The familiar base-setting prefixes 0 (octal) and 0x
(hexadecimal) are accepted when scanning integers without
@@ -300,6 +311,9 @@
All arguments to be scanned must be either pointers to basic
types or implementations of the Scanner interface.
+ Like Scanf and Fscanf, Sscanf need not consume its entire input.
+ There is no way to recover how much of the input string Sscanf used.
+
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
diff --git a/libgo/go/fmt/export_test.go b/libgo/go/fmt/export_test.go
index 12d5a11..14163a2 100644
--- a/libgo/go/fmt/export_test.go
+++ b/libgo/go/fmt/export_test.go
@@ -5,3 +5,4 @@
package fmt
var IsSpace = isSpace
+var Parsenum = parsenum
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index b658236..ce00456 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -605,7 +605,10 @@ var fmtTests = []struct {
{"%x", I(23), `3c32333e`},
{"%#x", I(23), `0x3c32333e`},
{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
- {"%d", I(23), `23`}, // Stringer applies only to string formats.
+ // Stringer applies only to string formats.
+ {"%d", I(23), `23`},
+ // Stringer applies to the extracted value.
+ {"%s", reflect.ValueOf(I(23)), `<23>`},
// go syntax
{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
@@ -1560,18 +1563,23 @@ func TestWidthAndPrecision(t *testing.T) {
}
}
-// Panic is a type that panics in String.
-type Panic struct {
+// PanicS is a type that panics in String.
+type PanicS struct {
message interface{}
}
// Value receiver.
-func (p Panic) GoString() string {
+func (p PanicS) String() string {
panic(p.message)
}
+// PanicGo is a type that panics in GoString.
+type PanicGo struct {
+ message interface{}
+}
+
// Value receiver.
-func (p Panic) String() string {
+func (p PanicGo) GoString() string {
panic(p.message)
}
@@ -1591,13 +1599,15 @@ var panictests = []struct {
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)"},
+ {"%s", (*PanicS)(nil), "<nil>"}, // nil pointer special case
+ {"%s", PanicS{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+ {"%s", PanicS{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)"},
+ {"%#v", (*PanicGo)(nil), "<nil>"}, // nil pointer special case
+ {"%#v", PanicGo{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"},
+ {"%#v", PanicGo{3}, "%!v(PANIC=3)"},
+ // Issue 18282. catchPanic should not clear fmtFlags permanently.
+ {"%#v", []interface{}{PanicGo{3}, PanicGo{3}}, "[]interface {}{%!v(PANIC=3), %!v(PANIC=3)}"},
// Format
{"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
{"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
@@ -1739,3 +1749,26 @@ func TestFormatterFlags(t *testing.T) {
}
}
}
+
+func TestParsenum(t *testing.T) {
+ testCases := []struct {
+ s string
+ start, end int
+ num int
+ isnum bool
+ newi int
+ }{
+ {"a123", 0, 4, 0, false, 0},
+ {"1234", 1, 1, 0, false, 1},
+ {"123a", 0, 4, 123, true, 3},
+ {"12a3", 0, 4, 12, true, 2},
+ {"1234", 0, 4, 1234, true, 4},
+ {"1a234", 1, 3, 0, false, 1},
+ }
+ for _, tt := range testCases {
+ num, isnum, newi := Parsenum(tt.s, tt.start, tt.end)
+ if num != tt.num || isnum != tt.isnum || newi != tt.newi {
+ t.Errorf("parsenum(%q, %d, %d) = %d, %v, %d, want %d, %v, %d", tt.s, tt.start, tt.end, num, isnum, newi, tt.num, tt.isnum, tt.newi)
+ }
+ }
+}
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index 0236475..f770483 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -46,7 +46,7 @@ type fmt struct {
wid int // width
prec int // precision
- // intbuf is large enought to store %b of an int64 with a sign and
+ // intbuf is large enough to store %b of an int64 with a sign and
// avoids padding at the end of the struct on 32 bit architectures.
intbuf [68]byte
}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index f8c7316..a7ef2e5 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -535,7 +535,11 @@ func (p *pp) catchPanic(arg interface{}, verb rune) {
// Nested panics; the recursion in printArg cannot succeed.
panic(err)
}
- p.fmt.clearflags() // We are done, and for this output we want default behavior.
+
+ oldFlags := p.fmt.fmtFlags
+ // For this output we want default behavior.
+ p.fmt.clearflags()
+
p.buf.WriteString(percentBangString)
p.buf.WriteRune(verb)
p.buf.WriteString(panicString)
@@ -543,6 +547,8 @@ func (p *pp) catchPanic(arg interface{}, verb rune) {
p.printArg(err, 'v')
p.panicking = false
p.buf.WriteByte(')')
+
+ p.fmt.fmtFlags = oldFlags
}
}
@@ -659,6 +665,14 @@ func (p *pp) printArg(arg interface{}, verb rune) {
case []byte:
p.fmtBytes(f, verb, "[]byte")
case reflect.Value:
+ // Handle extractable values with special methods
+ // since printValue does not handle them at depth 0.
+ if f.IsValid() && f.CanInterface() {
+ p.arg = f.Interface()
+ if p.handleMethods(verb) {
+ return
+ }
+ }
p.printValue(f, verb, 0)
default:
// If the type is not simple, it might have methods.
@@ -805,16 +819,15 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
if f.Kind() == reflect.Slice && f.IsNil() {
p.buf.WriteString(nilParenString)
return
- } else {
- p.buf.WriteByte('{')
- for i := 0; i < f.Len(); i++ {
- if i > 0 {
- p.buf.WriteString(commaSpaceString)
- }
- p.printValue(f.Index(i), verb, depth+1)
+ }
+ p.buf.WriteByte('{')
+ for i := 0; i < f.Len(); i++ {
+ if i > 0 {
+ p.buf.WriteString(commaSpaceString)
}
- p.buf.WriteByte('}')
+ p.printValue(f.Index(i), verb, depth+1)
}
+ p.buf.WriteByte('}')
} else {
p.buf.WriteByte('[')
for i := 0; i < f.Len(); i++ {
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index fdf4197..cd7232c 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -1075,6 +1075,58 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
func (s *ss) advance(format string) (i int) {
for i < len(format) {
fmtc, w := utf8.DecodeRuneInString(format[i:])
+
+ // Space processing.
+ // In the rest of this comment "space" means spaces other than newline.
+ // Newline in the format matches input of zero or more spaces and then newline or end-of-input.
+ // Spaces in the format before the newline are collapsed into the newline.
+ // Spaces in the format after the newline match zero or more spaces after the corresponding input newline.
+ // Other spaces in the format match input of one or more spaces or end-of-input.
+ if isSpace(fmtc) {
+ newlines := 0
+ trailingSpace := false
+ for isSpace(fmtc) && i < len(format) {
+ if fmtc == '\n' {
+ newlines++
+ trailingSpace = false
+ } else {
+ trailingSpace = true
+ }
+ i += w
+ fmtc, w = utf8.DecodeRuneInString(format[i:])
+ }
+ for j := 0; j < newlines; j++ {
+ inputc := s.getRune()
+ for isSpace(inputc) && inputc != '\n' {
+ inputc = s.getRune()
+ }
+ if inputc != '\n' && inputc != eof {
+ s.errorString("newline in format does not match input")
+ }
+ }
+ if trailingSpace {
+ inputc := s.getRune()
+ if newlines == 0 {
+ // If the trailing space stood alone (did not follow a newline),
+ // it must find at least one space to consume.
+ if !isSpace(inputc) && inputc != eof {
+ s.errorString("expected space in input to match format")
+ }
+ if inputc == '\n' {
+ s.errorString("newline in input does not match format")
+ }
+ }
+ for isSpace(inputc) && inputc != '\n' {
+ inputc = s.getRune()
+ }
+ if inputc != eof {
+ s.UnreadRune()
+ }
+ }
+ continue
+ }
+
+ // Verbs.
if fmtc == '%' {
// % at end of string is an error.
if i+w == len(format) {
@@ -1087,48 +1139,8 @@ func (s *ss) advance(format string) (i int) {
}
i += w // skip the first %
}
- sawSpace := false
- wasNewline := false
- // Skip spaces in format but absorb at most one newline.
- for isSpace(fmtc) && i < len(format) {
- if fmtc == '\n' {
- if wasNewline { // Already saw one; stop here.
- break
- }
- wasNewline = true
- }
- sawSpace = true
- i += w
- fmtc, w = utf8.DecodeRuneInString(format[i:])
- }
- if sawSpace {
- // There was space in the format, so there should be space
- // in the input.
- inputc := s.getRune()
- if inputc == eof {
- return
- }
- if !isSpace(inputc) {
- // Space in format but not in input.
- s.errorString("expected space in input to match format")
- }
- // Skip spaces but stop at newline.
- for inputc != '\n' && isSpace(inputc) {
- inputc = s.getRune()
- }
- if inputc == '\n' {
- if !wasNewline {
- s.errorString("newline in input does not match format")
- }
- // We've reached a newline, stop now; don't read further.
- return
- }
- s.UnreadRune()
- if wasNewline {
- s.errorString("newline in format does not match input")
- }
- continue
- }
+
+ // Literals.
inputc := s.mustReadRune()
if fmtc != inputc {
s.UnreadRune()
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index e36b62e..d7019d9 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -291,6 +291,97 @@ var scanfTests = []ScanfTest{
{"%c", " ", &uintVal, uint(' ')}, // %c must accept a blank.
{"%c", "\t", &uintVal, uint('\t')}, // %c must accept any space.
{"%c", "\n", &uintVal, uint('\n')}, // %c must accept any space.
+
+ // space handling
+ {"%d", "27", &intVal, 27},
+ {"%d", "27 ", &intVal, 27},
+ {"%d", " 27", &intVal, 27},
+ {"%d", " 27 ", &intVal, 27},
+
+ {"X%d", "X27", &intVal, 27},
+ {"X%d", "X27 ", &intVal, 27},
+ {"X%d", "X 27", &intVal, 27},
+ {"X%d", "X 27 ", &intVal, 27},
+
+ {"X %d", "X27", &intVal, nil}, // expected space in input to match format
+ {"X %d", "X27 ", &intVal, nil}, // expected space in input to match format
+ {"X %d", "X 27", &intVal, 27},
+ {"X %d", "X 27 ", &intVal, 27},
+
+ {"%dX", "27X", &intVal, 27},
+ {"%dX", "27 X", &intVal, nil}, // input does not match format
+ {"%dX", " 27X", &intVal, 27},
+ {"%dX", " 27 X", &intVal, nil}, // input does not match format
+
+ {"%d X", "27X", &intVal, nil}, // expected space in input to match format
+ {"%d X", "27 X", &intVal, 27},
+ {"%d X", " 27X", &intVal, nil}, // expected space in input to match format
+ {"%d X", " 27 X", &intVal, 27},
+
+ {"X %d X", "X27X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X27 X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X 27X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X 27 X", &intVal, 27},
+
+ {"X %s X", "X27X", &stringVal, nil}, // expected space in input to match format
+ {"X %s X", "X27 X", &stringVal, nil}, // expected space in input to match format
+ {"X %s X", "X 27X", &stringVal, nil}, // unexpected EOF
+ {"X %s X", "X 27 X", &stringVal, "27"},
+
+ {"X%sX", "X27X", &stringVal, nil}, // unexpected EOF
+ {"X%sX", "X27 X", &stringVal, nil}, // input does not match format
+ {"X%sX", "X 27X", &stringVal, nil}, // unexpected EOF
+ {"X%sX", "X 27 X", &stringVal, nil}, // input does not match format
+
+ {"X%s", "X27", &stringVal, "27"},
+ {"X%s", "X27 ", &stringVal, "27"},
+ {"X%s", "X 27", &stringVal, "27"},
+ {"X%s", "X 27 ", &stringVal, "27"},
+
+ {"X%dX", "X27X", &intVal, 27},
+ {"X%dX", "X27 X", &intVal, nil}, // input does not match format
+ {"X%dX", "X 27X", &intVal, 27},
+ {"X%dX", "X 27 X", &intVal, nil}, // input does not match format
+
+ {"X%dX", "X27X", &intVal, 27},
+ {"X%dX", "X27X ", &intVal, 27},
+ {"X%dX", " X27X", &intVal, nil}, // input does not match format
+ {"X%dX", " X27X ", &intVal, nil}, // input does not match format
+
+ {"X%dX\n", "X27X", &intVal, 27},
+ {"X%dX \n", "X27X ", &intVal, 27},
+ {"X%dX\n", "X27X\n", &intVal, 27},
+ {"X%dX\n", "X27X \n", &intVal, 27},
+
+ {"X%dX \n", "X27X", &intVal, 27},
+ {"X%dX \n", "X27X ", &intVal, 27},
+ {"X%dX \n", "X27X\n", &intVal, 27},
+ {"X%dX \n", "X27X \n", &intVal, 27},
+
+ {"X%c", "X\n", &runeVal, '\n'},
+ {"X%c", "X \n", &runeVal, ' '},
+ {"X %c", "X!", &runeVal, nil}, // expected space in input to match format
+ {"X %c", "X\n", &runeVal, nil}, // newline in input does not match format
+ {"X %c", "X !", &runeVal, '!'},
+ {"X %c", "X \n", &runeVal, '\n'},
+
+ {" X%dX", "X27X", &intVal, nil}, // expected space in input to match format
+ {" X%dX", "X27X ", &intVal, nil}, // expected space in input to match format
+ {" X%dX", " X27X", &intVal, 27},
+ {" X%dX", " X27X ", &intVal, 27},
+
+ {"X%dX ", "X27X", &intVal, 27},
+ {"X%dX ", "X27X ", &intVal, 27},
+ {"X%dX ", " X27X", &intVal, nil}, // input does not match format
+ {"X%dX ", " X27X ", &intVal, nil}, // input does not match format
+
+ {" X%dX ", "X27X", &intVal, nil}, // expected space in input to match format
+ {" X%dX ", "X27X ", &intVal, nil}, // expected space in input to match format
+ {" X%dX ", " X27X", &intVal, 27},
+ {" X%dX ", " X27X ", &intVal, 27},
+
+ {"%d\nX", "27\nX", &intVal, 27},
+ {"%dX\n X", "27X\n X", &intVal, 27},
}
var overflowTests = []ScanTest{
@@ -416,11 +507,17 @@ 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)
+ if test.out != nil {
+ t.Errorf("Sscanf(%q, %q): unexpected error: %v", test.text, test.format, err)
+ }
+ continue
+ }
+ if test.out == nil {
+ t.Errorf("Sscanf(%q, %q): unexpected success", test.text, test.format)
continue
}
if n != 1 {
- t.Errorf("count error on entry (%q, %q): got %d", test.format, test.text, n)
+ t.Errorf("Sscanf(%q, %q): parsed %d field, want 1", test.text, test.format, n)
continue
}
// The incoming value may be a pointer
@@ -430,7 +527,7 @@ func TestScanf(t *testing.T) {
}
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)
+ t.Errorf("Sscanf(%q, %q): parsed value %T(%#v), want %T(%#v)", test.text, test.format, val, val, test.out, test.out)
}
}
}
@@ -1113,9 +1210,47 @@ func TestScanfNewlineMatchFormat(t *testing.T) {
{"space-newline in both", "1 \n2", "%d \n%d", 2, true},
{"extra space in format", "1\n2", "%d\n %d", 2, true},
{"two extra spaces in format", "1\n2", "%d \n %d", 2, true},
+ {"space vs newline 0000", "1\n2", "%d\n%d", 2, true},
+ {"space vs newline 0001", "1\n2", "%d\n %d", 2, true},
+ {"space vs newline 0010", "1\n2", "%d \n%d", 2, true},
+ {"space vs newline 0011", "1\n2", "%d \n %d", 2, true},
+ {"space vs newline 0100", "1\n 2", "%d\n%d", 2, true},
+ {"space vs newline 0101", "1\n 2", "%d\n%d ", 2, true},
+ {"space vs newline 0110", "1\n 2", "%d \n%d", 2, true},
+ {"space vs newline 0111", "1\n 2", "%d \n %d", 2, true},
+ {"space vs newline 1000", "1 \n2", "%d\n%d", 2, true},
+ {"space vs newline 1001", "1 \n2", "%d\n %d", 2, true},
+ {"space vs newline 1010", "1 \n2", "%d \n%d", 2, true},
+ {"space vs newline 1011", "1 \n2", "%d \n %d", 2, true},
+ {"space vs newline 1100", "1 \n 2", "%d\n%d", 2, true},
+ {"space vs newline 1101", "1 \n 2", "%d\n %d", 2, true},
+ {"space vs newline 1110", "1 \n 2", "%d \n%d", 2, true},
+ {"space vs newline 1111", "1 \n 2", "%d \n %d", 2, true},
+ {"space vs newline no-percent 0000", "1\n2", "1\n2", 0, true},
+ {"space vs newline no-percent 0001", "1\n2", "1\n 2", 0, true},
+ {"space vs newline no-percent 0010", "1\n2", "1 \n2", 0, true},
+ {"space vs newline no-percent 0011", "1\n2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 0100", "1\n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0101", "1\n 2", "1\n2 ", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0110", "1\n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0111", "1\n 2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 1000", "1 \n2", "1\n2", 0, true},
+ {"space vs newline no-percent 1001", "1 \n2", "1\n 2", 0, true},
+ {"space vs newline no-percent 1010", "1 \n2", "1 \n2", 0, true},
+ {"space vs newline no-percent 1011", "1 \n2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 1100", "1 \n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 1101", "1 \n 2", "1\n 2", 0, true},
+ {"space vs newline no-percent 1110", "1 \n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 1111", "1 \n 2", "1 \n 2", 0, true},
}
for _, test := range tests {
- n, err := Sscanf(test.text, test.format, &a, &b)
+ var n int
+ var err error
+ if strings.Contains(test.format, "%") {
+ n, err = Sscanf(test.text, test.format, &a, &b)
+ } else {
+ n, err = Sscanf(test.text, test.format)
+ }
if n != test.count {
t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n)
}