diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-01-14 00:05:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-01-14 00:05:42 +0000 |
commit | c2047754c300b68c05d65faa8dc2925fe67b71b4 (patch) | |
tree | e183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/fmt | |
parent | 829afb8f05602bb31c9c597b24df7377fed4f059 (diff) | |
download | gcc-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.go | 70 | ||||
-rw-r--r-- | libgo/go/fmt/export_test.go | 1 | ||||
-rw-r--r-- | libgo/go/fmt/fmt_test.go | 55 | ||||
-rw-r--r-- | libgo/go/fmt/format.go | 2 | ||||
-rw-r--r-- | libgo/go/fmt/print.go | 31 | ||||
-rw-r--r-- | libgo/go/fmt/scan.go | 96 | ||||
-rw-r--r-- | libgo/go/fmt/scan_test.go | 143 |
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) } |