1
0
mirror of https://github.com/golang/go synced 2024-09-25 01:20:13 -06:00

fmt.Scan: scan []byte arguments

R=rsc
CC=golang-dev
https://golang.org/cl/1486041
This commit is contained in:
Rob Pike 2010-06-02 16:28:01 -07:00
parent 041d978d84
commit 6106c63abc
3 changed files with 34 additions and 7 deletions

View File

@ -119,7 +119,6 @@
package fmt
// BUG: format precision and flags are not yet implemented for scanning.
// BUG: %sqx are not yet implemented for scanning byte slices.
import (
"bytes"

View File

@ -649,6 +649,10 @@ func (s *ss) scanOne(verb int, field interface{}) {
}
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)
@ -683,6 +687,17 @@ func (s *ss) scanOne(verb int, field interface{}) {
v.Set(uintptr(s.scanUint(verb, uintptrBits)))
case *reflect.StringValue:
v.Set(s.convertString(verb))
case *reflect.SliceValue:
// For now, can only handle (renamed) []byte.
typ := v.Type().(*reflect.SliceType)
if _, ok := typ.Elem().(*reflect.Uint8Type); !ok {
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.Uint8Value).Set(str[i])
}
case *reflect.FloatValue:
v.Set(float(s.convertFloat(s.token())))
case *reflect.Float32Value:
@ -696,6 +711,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
case *reflect.Complex128Value:
v.Set(s.scanComplex(verb, (*ss).convertFloat64))
default:
CantHandle:
s.errorString("Scan: can't handle type: " + val.Type().String())
}
}
@ -738,12 +754,12 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err os.Error) {
return
}
// advance determines whether the next characters in the input matches
// 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 routines also
// handles the %% case. If the return value is zero, either the format
// is sitting on a % or the input is empty.
// 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.
func (s *ss) advance(format string) (i int) {
for i < len(format) {
fmtc, w := utf8.DecodeRuneInString(format[i:])
@ -797,9 +813,9 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err os.E
i += w
continue
}
// Either we have a percent character or we ran out of input.
// Either we failed to advance, we have a percent character, or we ran out of input.
if format[i] != '%' {
// Out of format. Have we run out of input?
// Can't advance format. Do we have arguments still to process?
if i < len(a) {
s.errorString("too many arguments for format")
}

View File

@ -40,6 +40,7 @@ type (
renamedUint64 uint64
renamedUintptr uintptr
renamedString string
renamedBytes []byte
renamedFloat float
renamedFloat32 float32
renamedFloat64 float64
@ -64,6 +65,7 @@ var (
float32Val float32
float64Val float64
stringVal string
bytesVal []byte
complexVal complex
complex64Val complex64
complex128Val complex128
@ -80,6 +82,7 @@ var (
renamedUint64Val renamedUint64
renamedUintptrVal renamedUintptr
renamedStringVal renamedString
renamedBytesVal renamedBytes
renamedFloatVal renamedFloat
renamedFloat32Val renamedFloat32
renamedFloat64Val renamedFloat64
@ -140,6 +143,7 @@ var scanTests = []ScanTest{
ScanTest{"2.3e1\n", &float32Val, float32(2.3e1)},
ScanTest{"2.3e2\n", &float64Val, float64(2.3e2)},
ScanTest{"2.35\n", &stringVal, "2.35"},
ScanTest{"2345678\n", &bytesVal, []byte("2345678")},
ScanTest{"(3.4e1-2i)\n", &complexVal, 3.4e1 - 2i},
ScanTest{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
ScanTest{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
@ -162,6 +166,7 @@ var scanTests = []ScanTest{
ScanTest{"112\n", &renamedUint64Val, renamedUint64(112)},
ScanTest{"113\n", &renamedUintptrVal, renamedUintptr(113)},
ScanTest{"114\n", &renamedStringVal, renamedString("114")},
ScanTest{"115\n", &renamedBytesVal, renamedBytes([]byte("115"))},
// Custom scanner.
ScanTest{" xxx ", &xVal, Xs("xxx")},
@ -196,6 +201,12 @@ var scanfTests = []ScanfTest{
ScanfTest{"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
ScanfTest{"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
// Byte slices
ScanfTest{"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
ScanfTest{"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
ScanfTest{"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
ScanfTest{"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
// Renamed types
ScanfTest{"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
ScanfTest{"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
@ -213,6 +224,7 @@ var scanfTests = []ScanfTest{
ScanfTest{"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
ScanfTest{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
ScanfTest{"%s", "114\n", &renamedStringVal, renamedString("114")},
ScanfTest{"%q", "\"1155\"\n", &renamedBytesVal, renamedBytes([]byte("1155"))},
ScanfTest{"%g", "115.1\n", &renamedFloatVal, renamedFloat(115.1)},
ScanfTest{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
ScanfTest{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},