aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/fmt/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/fmt/scan.go')
-rw-r--r--libgo/go/fmt/scan.go152
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")
}