diff options
Diffstat (limited to 'libgo/go/fmt/scan.go')
-rw-r--r-- | libgo/go/fmt/scan.go | 152 |
1 files changed, 75 insertions, 77 deletions
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index 4618ed4..fdf4197 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -15,14 +15,6 @@ import ( "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. @@ -41,7 +33,7 @@ type ScanState interface { // 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 appropriately for the operation being + // characters. Newlines are treated appropriately for the operation being // performed; see the package documentation for more information. // 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 @@ -58,15 +50,15 @@ type ScanState interface { // 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 +// 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. +// 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...) @@ -80,7 +72,7 @@ func Scanln(a ...interface{}) (n int, err error) { // 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. +// the format. It returns the number of items successfully scanned. // If that is less than the number of arguments, err will report why. // Newlines in the input must match newlines in the format. // The one exception: the verb %c always scans the next rune in the @@ -101,8 +93,8 @@ func (r *stringReader) Read(b []byte) (n int, err error) { } // 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 +// 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...) @@ -115,7 +107,7 @@ func Sscanln(str string, a ...interface{}) (n int, err error) { } // Sscanf scans the argument string, storing successive space-separated -// values into successive arguments as determined by the format. It +// values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. func Sscanf(str string, format string, a ...interface{}) (n int, err error) { @@ -123,8 +115,8 @@ func Sscanf(str string, format string, a ...interface{}) (n int, err error) { } // 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 +// 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) @@ -143,7 +135,7 @@ func Fscanln(r io.Reader, a ...interface{}) (n int, err error) { } // Fscanf scans text read from r, storing successive space-separated -// values into successive arguments as determined by the format. It +// values into successive arguments as determined by the format. It // returns the number of items successfully parsed. // Newlines in the input must match newlines in the format. func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) { @@ -163,12 +155,10 @@ 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 + rs io.RuneScanner // where to read input + buf buffer // token accumulator + count int // runes consumed so far. + atEOF bool // already read EOF ssave } @@ -191,23 +181,17 @@ func (s *ss) Read(buf []byte) (n int, err error) { } 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 { + if s.atEOF || s.count >= s.argLimit { err = io.EOF return } - r, size, err = s.rr.ReadRune() + r, size, err = s.rs.ReadRune() if err == nil { s.count++ - s.prevRune = r + if s.nlIsEnd && r == '\n' { + s.atEOF = true + } } else if err == io.EOF { s.atEOF = true } @@ -246,12 +230,8 @@ func (s *ss) mustReadRune() (r rune) { } func (s *ss) UnreadRune() error { - if u, ok := s.rr.(runeUnreader); ok { - u.UnreadRune() - } else { - s.peekRune = s.prevRune - } - s.prevRune = -1 + s.rs.UnreadRune() + s.atEOF = false s.count-- return nil } @@ -326,13 +306,14 @@ func (s *ss) SkipSpace() { } // 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. +// from an io.Reader. It is used if the Reader given to the scanner does +// not already implement io.RuneScanner. 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 + 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 + peekRune rune // if >=0 next rune; when <0 is ^(previous Rune) } // readByte returns the next byte from the input, which may be @@ -344,33 +325,35 @@ func (r *readRune) readByte() (b byte, err error) { r.pending-- return } - n, err := io.ReadFull(r.reader, r.pendBuf[0:1]) + n, err := io.ReadFull(r.reader, r.pendBuf[: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) { + if r.peekRune >= 0 { + rr = r.peekRune + r.peekRune = ^r.peekRune + size = utf8.RuneLen(rr) + return + } r.buf[0], err = r.readByte() if err != nil { - return 0, 0, err + return } if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case rr = rune(r.buf[0]) size = 1 // Known to be 1. + // Flip the bits of the rune so it's available to UnreadRune. + r.peekRune = ^rr return } var n int - for n = 1; !utf8.FullRune(r.buf[0:n]); n++ { + for n = 1; !utf8.FullRune(r.buf[:n]); n++ { r.buf[n], err = r.readByte() if err != nil { if err == io.EOF { @@ -380,13 +363,25 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) { return } } - rr, size = utf8.DecodeRune(r.buf[0:n]) - if size < n { // an error - r.unread(r.buf[size:n]) + rr, size = utf8.DecodeRune(r.buf[:n]) + if size < n { // an error, save the bytes for the next read + copy(r.pendBuf[r.pending:], r.buf[size:n]) + r.pending += n - size } + // Flip the bits of the rune so it's available to UnreadRune. + r.peekRune = ^rr return } +func (r *readRune) UnreadRune() error { + if r.peekRune >= 0 { + return errors.New("fmt: scanning called UnreadRune with no rune available") + } + // Reverse bit flip of previously read rune to obtain valid >=0 state. + r.peekRune = ^r.peekRune + return nil +} + var ssFree = sync.Pool{ New: func() interface{} { return new(ss) }, } @@ -394,15 +389,13 @@ var ssFree = sync.Pool{ // newScanState allocates a new ss struct or grab a cached one. func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { s = ssFree.Get().(*ss) - if rr, ok := r.(io.RuneReader); ok { - s.rr = rr + if rs, ok := r.(io.RuneScanner); ok { + s.rs = rs } else { - s.rr = &readRune{reader: r} + s.rs = &readRune{reader: r, peekRune: -1} } s.nlIsSpace = nlIsSpace s.nlIsEnd = nlIsEnd - s.prevRune = -1 - s.peekRune = -1 s.atEOF = false s.limit = hugeWid s.argLimit = hugeWid @@ -424,7 +417,7 @@ func (s *ss) free(old ssave) { return } s.buf = s.buf[:0] - s.rr = nil + s.rs = nil ssFree.Put(s) } @@ -455,8 +448,8 @@ func (s *ss) skipSpace(stopAtNewline bool) { } } -// token returns the next space-delimited string from the input. It -// skips white space. For Scanln, it stops at newlines. For Scan, +// 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 { @@ -525,7 +518,7 @@ func (s *ss) notEOF() { s.UnreadRune() } -// accept checks the next rune in the input. If it's a byte (sic) in the string, it puts it in the +// 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) @@ -549,7 +542,7 @@ func (s *ss) scanBool(verb rune) bool { if !s.okVerb(verb, "tv", "boolean") { return false } - // Syntax-checking a boolean is annoying. We're not fastidious about case. + // Syntax-checking a boolean is annoying. We're not fastidious about case. switch s.getRune() { case '0': return false @@ -643,7 +636,7 @@ func (s *ss) scanBasePrefix() (base int, digits string, found bool) { } // scanInt returns the value of the integer represented by the next -// token, checking for overflow. Any error is stored in s.err. +// 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) @@ -676,7 +669,7 @@ func (s *ss) scanInt(verb rune, bitSize int) int64 { } // scanUint returns the value of the unsigned integer represented -// by the next token, checking for overflow. Any error is stored in s.err. +// 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)) @@ -846,7 +839,7 @@ func (s *ss) quotedString() string { return string(s.buf) case '"': // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes. - s.buf.WriteRune(quote) + s.buf.WriteByte('"') for { r := s.mustReadRune() s.buf.WriteRune(r) @@ -922,9 +915,14 @@ func (s *ss) hexString() string { return string(s.buf) } -const floatVerbs = "beEfFgGv" +const ( + floatVerbs = "beEfFgGv" -const hugeWid = 1 << 30 + hugeWid = 1 << 30 + + intBits = 32 << (^uint(0) >> 63) + uintptrBits = 32 << (^uintptr(0) >> 63) +) // scanOne scans a single value, deriving the scanner from the type of the argument. func (s *ss) scanOne(verb rune, arg interface{}) { @@ -1142,7 +1140,7 @@ func (s *ss) advance(format string) (i int) { } // doScanf does the real work when scanning with a format string. -// At the moment, it handles only pointers to basic types. +// 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 @@ -1155,7 +1153,7 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro } // 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? + // Can't advance format. Why not? if w < 0 { s.errorString("input does not match format") } |