summaryrefslogtreecommitdiff
path: root/src/cmd/fix/testdata/reflect.scan.go.in
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/fix/testdata/reflect.scan.go.in')
-rw-r--r--src/cmd/fix/testdata/reflect.scan.go.in1082
1 files changed, 0 insertions, 1082 deletions
diff --git a/src/cmd/fix/testdata/reflect.scan.go.in b/src/cmd/fix/testdata/reflect.scan.go.in
deleted file mode 100644
index 51898181f..000000000
--- a/src/cmd/fix/testdata/reflect.scan.go.in
+++ /dev/null
@@ -1,1082 +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 (
- "bytes"
- "io"
- "math"
- "os"
- "reflect"
- "strconv"
- "strings"
- "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() os.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() (rune int, size int, err os.Error)
- // UnreadRune causes the next call to ReadRune to return the same rune.
- UnreadRune() os.Error
- // 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(int) bool) (token []byte, err os.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 os.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 int) os.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 os.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 os.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 os.Error) {
- return Fscanf(os.Stdin, format, a...)
-}
-
-// 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 os.Error) {
- return Fscan(strings.NewReader(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 os.Error) {
- return Fscanln(strings.NewReader(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 os.Error) {
- return Fscanf(strings.NewReader(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 os.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 os.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 os.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 os.Error
-}
-
-const eof = -1
-
-// ss is the internal implementation of ScanState.
-type ss struct {
- rr io.RuneReader // where to read input
- buf bytes.Buffer // token accumulator
- peekRune int // one-rune lookahead
- prevRune int // 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
- fieldLimit int // max value of ss.count for this field; fieldLimit <= limit
- limit int // max value of ss.count.
- maxWid int // width of this field.
-}
-
-// 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 os.Error) {
- return 0, os.NewError("ScanState's Read should not be called. Use ReadRune")
-}
-
-func (s *ss) ReadRune() (rune int, size int, err os.Error) {
- if s.peekRune >= 0 {
- s.count++
- rune = s.peekRune
- size = utf8.RuneLen(rune)
- s.prevRune = rune
- s.peekRune = -1
- return
- }
- if s.atEOF || s.nlIsEnd && s.prevRune == '\n' || s.count >= s.fieldLimit {
- err = os.EOF
- return
- }
-
- rune, size, err = s.rr.ReadRune()
- if err == nil {
- s.count++
- s.prevRune = rune
- } else if err == os.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() (rune int) {
- rune, _, err := s.ReadRune()
- if err != nil {
- if err == os.EOF {
- return eof
- }
- s.error(err)
- }
- return
-}
-
-// mustReadRune turns os.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() (rune int) {
- rune = s.getRune()
- if rune == eof {
- s.error(io.ErrUnexpectedEOF)
- }
- return
-}
-
-func (s *ss) UnreadRune() os.Error {
- if u, ok := s.rr.(runeUnreader); ok {
- u.UnreadRune()
- } else {
- s.peekRune = s.prevRune
- }
- s.count--
- return nil
-}
-
-func (s *ss) error(err os.Error) {
- panic(scanError{err})
-}
-
-func (s *ss) errorString(err string) {
- panic(scanError{os.NewError(err)})
-}
-
-func (s *ss) Token(skipSpace bool, f func(int) bool) (tok []byte, err os.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.Reset()
- tok = s.token(skipSpace, f)
- return
-}
-
-// notSpace is the default scanning function used in Token.
-func notSpace(r int) bool {
- return !unicode.IsSpace(r)
-}
-
-// 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 os.Error) {
- if r.pending > 0 {
- b = r.pendBuf[0]
- copy(r.pendBuf[0:], r.pendBuf[1:])
- r.pending--
- return
- }
- _, err = r.reader.Read(r.pendBuf[0:1])
- 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() (rune int, size int, err os.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
- rune = int(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 == os.EOF {
- err = nil
- break
- }
- return
- }
- }
- rune, size = utf8.DecodeRune(r.buf[0:n])
- if size < n { // an error
- r.unread(r.buf[size:n])
- }
- return
-}
-
-var ssFree = newCache(func() interface{} { return new(ss) })
-
-// Allocate 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.fieldLimit
- 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.fieldLimit = hugeWid
- s.maxWid = hugeWid
- s.validSave = true
- return
-}
-
-// Save 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.Bytes()) > 1024 {
- return
- }
- s.buf.Reset()
- s.rr = nil
- ssFree.put(s)
-}
-
-// skipSpace skips spaces and maybe newlines.
-func (s *ss) skipSpace(stopAtNewline bool) {
- for {
- rune := s.getRune()
- if rune == eof {
- return
- }
- if rune == '\n' {
- if stopAtNewline {
- break
- }
- if s.nlIsSpace {
- continue
- }
- s.errorString("unexpected newline")
- return
- }
- if !unicode.IsSpace(rune) {
- 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(int) bool) []byte {
- if skipSpace {
- s.skipSpace(false)
- }
- // read until white space or newline
- for {
- rune := s.getRune()
- if rune == eof {
- break
- }
- if !f(rune) {
- s.UnreadRune()
- break
- }
- s.buf.WriteRune(rune)
- }
- return s.buf.Bytes()
-}
-
-// typeError indicates that the type of the operand did not match the format
-func (s *ss) typeError(field interface{}, expected string) {
- s.errorString("expected field of type pointer to " + expected + "; found " + reflect.Typeof(field).String())
-}
-
-var complexError = os.NewError("syntax error scanning complex number")
-var boolError = os.NewError("syntax error scanning boolean")
-
-// 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 {
- rune := s.getRune()
- if rune == eof {
- return false
- }
- if strings.IndexRune(ok, rune) >= 0 {
- if accept {
- s.buf.WriteRune(rune)
- }
- return true
- }
- if rune != 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 {
- rune := s.getRune()
- if rune != eof {
- s.UnreadRune()
- }
- return strings.IndexRune(ok, rune) >= 0
-}
-
-// 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 int, 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 int) bool {
- if !s.okVerb(verb, "tv", "boolean") {
- return false
- }
- // Syntax-checking a boolean is annoying. We're not fastidious about case.
- switch s.mustReadRune() {
- 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("aL") && (!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 int) (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.accept(digits) {
- s.errorString("expected integer")
- }
- for s.accept(digits) {
- }
- return s.buf.String()
-}
-
-// scanRune returns the next rune value in the input.
-func (s *ss) scanRune(bitSize int) int64 {
- rune := int64(s.mustReadRune())
- n := uint(bitSize)
- x := (rune << (64 - n)) >> (64 - n)
- if x != rune {
- s.errorString("overflow on character value " + string(rune))
- }
- return rune
-}
-
-// 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 int, bitSize int) int64 {
- if verb == 'c' {
- return s.scanRune(bitSize)
- }
- s.skipSpace(false)
- 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.Btoi64(tok, base)
- 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 int, bitSize int) uint64 {
- if verb == 'c' {
- return uint64(s.scanRune(bitSize))
- }
- s.skipSpace(false)
- 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.Btoui64(tok, base)
- 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.Reset()
- // NaN?
- if s.accept("nN") && s.accept("aA") && s.accept("nN") {
- return s.buf.String()
- }
- // leading sign?
- s.accept(sign)
- // Inf?
- if s.accept("iI") && s.accept("nN") && s.accept("fF") {
- return s.buf.String()
- }
- // 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 s.buf.String()
-}
-
-// 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.Reset()
- // Must now have a sign.
- if !s.accept("+-") {
- s.error(complexError)
- }
- // Sign is now in buffer
- imagSign := s.buf.String()
- 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 := strings.Index(str, "p"); p >= 0 {
- // Atof doesn't handle power-of-2 exponents,
- // but they're easy to evaluate.
- f, err := strconv.AtofN(str[:p], n)
- if err != nil {
- // Put full string into error.
- if e, ok := err.(*strconv.NumError); ok {
- e.Num = str
- }
- s.error(err)
- }
- n, 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, n)
- }
- f, err := strconv.AtofN(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 int, n int) complex128 {
- if !s.okVerb(verb, floatVerbs, "complex") {
- return 0
- }
- s.skipSpace(false)
- 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 int) (str string) {
- if !s.okVerb(verb, "svqx", "string") {
- return ""
- }
- s.skipSpace(false)
- 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
- }
- // Empty strings other than with %q are not OK.
- if len(str) == 0 && verb != 'q' && s.maxWid > 0 {
- s.errorString("Scan: no data for string")
- }
- return
-}
-
-// quotedString returns the double- or back-quoted string represented by the next input characters.
-func (s *ss) quotedString() string {
- quote := s.mustReadRune()
- switch quote {
- case '`':
- // Back-quoted: Anything goes until EOF or back quote.
- for {
- rune := s.mustReadRune()
- if rune == quote {
- break
- }
- s.buf.WriteRune(rune)
- }
- return s.buf.String()
- case '"':
- // Double-quoted: Include the quotes and let strconv.Unquote do the backslash escapes.
- s.buf.WriteRune(quote)
- for {
- rune := s.mustReadRune()
- s.buf.WriteRune(rune)
- if rune == '\\' {
- // 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.
- rune := s.mustReadRune()
- s.buf.WriteRune(rune)
- } else if rune == '"' {
- break
- }
- }
- result, err := strconv.Unquote(s.buf.String())
- 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(digit int) int {
- 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("Scan: 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 unicode.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 {
- for {
- b, ok := s.hexByte()
- if !ok {
- break
- }
- s.buf.WriteByte(b)
- }
- if s.buf.Len() == 0 {
- s.errorString("Scan: no hex data for %x string")
- return ""
- }
- return s.buf.String()
-}
-
-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 int, field interface{}) {
- s.buf.Reset()
- var err os.Error
- // If the parameter has its own Scan method, use that.
- if v, ok := field.(Scanner); ok {
- err = v.Scan(s, verb)
- if err != nil {
- if err == os.EOF {
- err = io.ErrUnexpectedEOF
- }
- s.error(err)
- }
- return
- }
- switch v := field.(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)
- *v = float32(s.convertFloat(s.floatToken(), 32))
- }
- case *float64:
- if s.okVerb(verb, floatVerbs, "float64") {
- s.skipSpace(false)
- *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.NewValue(v)
- ptr, ok := val.(*reflect.PtrValue)
- if !ok {
- s.errorString("Scan: type not a pointer: " + val.Type().String())
- return
- }
- switch v := ptr.Elem().(type) {
- case *reflect.BoolValue:
- v.Set(s.scanBool(verb))
- case *reflect.IntValue:
- v.Set(s.scanInt(verb, v.Type().Bits()))
- case *reflect.UintValue:
- v.Set(s.scanUint(verb, v.Type().Bits()))
- case *reflect.StringValue:
- v.Set(s.convertString(verb))
- case *reflect.SliceValue:
- // For now, can only handle (renamed) []byte.
- typ := v.Type().(*reflect.SliceType)
- if typ.Elem().Kind() != reflect.Uint8 {
- goto CantHandle
- }
- str := s.convertString(verb)
- v.Set(reflect.MakeSlice(typ, len(str), len(str)))
- for i := 0; i < len(str); i++ {
- v.Elem(i).(*reflect.UintValue).Set(uint64(str[i]))
- }
- case *reflect.FloatValue:
- s.skipSpace(false)
- v.Set(s.convertFloat(s.floatToken(), v.Type().Bits()))
- case *reflect.ComplexValue:
- v.Set(s.scanComplex(verb, v.Type().Bits()))
- default:
- CantHandle:
- s.errorString("Scan: can't handle type: " + val.Type().String())
- }
- }
-}
-
-// errorHandler turns local panics into error returns. EOFs are benign.
-func errorHandler(errp *os.Error) {
- if e := recover(); e != nil {
- if se, ok := e.(scanError); ok { // catch local error
- if se.err != os.EOF {
- *errp = se.err
- }
- } else {
- panic(e)
- }
- }
-}
-
-// doScan does the real work for scanning without a format string.
-func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) {
- defer errorHandler(&err)
- for _, field := range a {
- s.scanOne('v', field)
- numProcessed++
- }
- // Check for newline if required.
- if !s.nlIsSpace {
- for {
- rune := s.getRune()
- if rune == '\n' || rune == eof {
- break
- }
- if !unicode.IsSpace(rune) {
- s.errorString("Scan: 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 unicode.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 {
- return
- }
- if !unicode.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 os.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.fieldLimit = s.limit
- if f := s.count + s.maxWid; f < s.fieldLimit {
- s.fieldLimit = 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
- }
- field := a[numProcessed]
-
- s.scanOne(c, field)
- numProcessed++
- s.fieldLimit = s.limit
- }
- if numProcessed < len(a) {
- s.errorString("too many operands")
- }
- return
-}