mirror of
https://github.com/golang/go
synced 2024-11-12 07:10:22 -07:00
fmt.Scan: scan []byte arguments
R=rsc CC=golang-dev https://golang.org/cl/1486041
This commit is contained in:
parent
041d978d84
commit
6106c63abc
@ -119,7 +119,6 @@
|
|||||||
package fmt
|
package fmt
|
||||||
|
|
||||||
// BUG: format precision and flags are not yet implemented for scanning.
|
// BUG: format precision and flags are not yet implemented for scanning.
|
||||||
// BUG: %sqx are not yet implemented for scanning byte slices.
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -649,6 +649,10 @@ func (s *ss) scanOne(verb int, field interface{}) {
|
|||||||
}
|
}
|
||||||
case *string:
|
case *string:
|
||||||
*v = s.convertString(verb)
|
*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:
|
default:
|
||||||
val := reflect.NewValue(v)
|
val := reflect.NewValue(v)
|
||||||
ptr, ok := val.(*reflect.PtrValue)
|
ptr, ok := val.(*reflect.PtrValue)
|
||||||
@ -683,6 +687,17 @@ func (s *ss) scanOne(verb int, field interface{}) {
|
|||||||
v.Set(uintptr(s.scanUint(verb, uintptrBits)))
|
v.Set(uintptr(s.scanUint(verb, uintptrBits)))
|
||||||
case *reflect.StringValue:
|
case *reflect.StringValue:
|
||||||
v.Set(s.convertString(verb))
|
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:
|
case *reflect.FloatValue:
|
||||||
v.Set(float(s.convertFloat(s.token())))
|
v.Set(float(s.convertFloat(s.token())))
|
||||||
case *reflect.Float32Value:
|
case *reflect.Float32Value:
|
||||||
@ -696,6 +711,7 @@ func (s *ss) scanOne(verb int, field interface{}) {
|
|||||||
case *reflect.Complex128Value:
|
case *reflect.Complex128Value:
|
||||||
v.Set(s.scanComplex(verb, (*ss).convertFloat64))
|
v.Set(s.scanComplex(verb, (*ss).convertFloat64))
|
||||||
default:
|
default:
|
||||||
|
CantHandle:
|
||||||
s.errorString("Scan: can't handle type: " + val.Type().String())
|
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
|
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
|
// those of the format. It returns the number of bytes (sic) consumed
|
||||||
// in the format. Newlines included, all runs of space characters in
|
// in the format. Newlines included, all runs of space characters in
|
||||||
// either input or format behave as a single space. This routines also
|
// either input or format behave as a single space. This routine also
|
||||||
// handles the %% case. If the return value is zero, either the format
|
// handles the %% case. If the return value is zero, either format
|
||||||
// is sitting on a % or the input is empty.
|
// starts with a % (with no following %) or the input is empty.
|
||||||
func (s *ss) advance(format string) (i int) {
|
func (s *ss) advance(format string) (i int) {
|
||||||
for i < len(format) {
|
for i < len(format) {
|
||||||
fmtc, w := utf8.DecodeRuneInString(format[i:])
|
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
|
i += w
|
||||||
continue
|
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] != '%' {
|
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) {
|
if i < len(a) {
|
||||||
s.errorString("too many arguments for format")
|
s.errorString("too many arguments for format")
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ type (
|
|||||||
renamedUint64 uint64
|
renamedUint64 uint64
|
||||||
renamedUintptr uintptr
|
renamedUintptr uintptr
|
||||||
renamedString string
|
renamedString string
|
||||||
|
renamedBytes []byte
|
||||||
renamedFloat float
|
renamedFloat float
|
||||||
renamedFloat32 float32
|
renamedFloat32 float32
|
||||||
renamedFloat64 float64
|
renamedFloat64 float64
|
||||||
@ -64,6 +65,7 @@ var (
|
|||||||
float32Val float32
|
float32Val float32
|
||||||
float64Val float64
|
float64Val float64
|
||||||
stringVal string
|
stringVal string
|
||||||
|
bytesVal []byte
|
||||||
complexVal complex
|
complexVal complex
|
||||||
complex64Val complex64
|
complex64Val complex64
|
||||||
complex128Val complex128
|
complex128Val complex128
|
||||||
@ -80,6 +82,7 @@ var (
|
|||||||
renamedUint64Val renamedUint64
|
renamedUint64Val renamedUint64
|
||||||
renamedUintptrVal renamedUintptr
|
renamedUintptrVal renamedUintptr
|
||||||
renamedStringVal renamedString
|
renamedStringVal renamedString
|
||||||
|
renamedBytesVal renamedBytes
|
||||||
renamedFloatVal renamedFloat
|
renamedFloatVal renamedFloat
|
||||||
renamedFloat32Val renamedFloat32
|
renamedFloat32Val renamedFloat32
|
||||||
renamedFloat64Val renamedFloat64
|
renamedFloat64Val renamedFloat64
|
||||||
@ -140,6 +143,7 @@ var scanTests = []ScanTest{
|
|||||||
ScanTest{"2.3e1\n", &float32Val, float32(2.3e1)},
|
ScanTest{"2.3e1\n", &float32Val, float32(2.3e1)},
|
||||||
ScanTest{"2.3e2\n", &float64Val, float64(2.3e2)},
|
ScanTest{"2.3e2\n", &float64Val, float64(2.3e2)},
|
||||||
ScanTest{"2.35\n", &stringVal, "2.35"},
|
ScanTest{"2.35\n", &stringVal, "2.35"},
|
||||||
|
ScanTest{"2345678\n", &bytesVal, []byte("2345678")},
|
||||||
ScanTest{"(3.4e1-2i)\n", &complexVal, 3.4e1 - 2i},
|
ScanTest{"(3.4e1-2i)\n", &complexVal, 3.4e1 - 2i},
|
||||||
ScanTest{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
|
ScanTest{"-3.45e1-3i\n", &complex64Val, complex64(-3.45e1 - 3i)},
|
||||||
ScanTest{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
|
ScanTest{"-.45e1-1e2i\n", &complex128Val, complex128(-.45e1 - 100i)},
|
||||||
@ -162,6 +166,7 @@ var scanTests = []ScanTest{
|
|||||||
ScanTest{"112\n", &renamedUint64Val, renamedUint64(112)},
|
ScanTest{"112\n", &renamedUint64Val, renamedUint64(112)},
|
||||||
ScanTest{"113\n", &renamedUintptrVal, renamedUintptr(113)},
|
ScanTest{"113\n", &renamedUintptrVal, renamedUintptr(113)},
|
||||||
ScanTest{"114\n", &renamedStringVal, renamedString("114")},
|
ScanTest{"114\n", &renamedStringVal, renamedString("114")},
|
||||||
|
ScanTest{"115\n", &renamedBytesVal, renamedBytes([]byte("115"))},
|
||||||
|
|
||||||
// Custom scanner.
|
// Custom scanner.
|
||||||
ScanTest{" xxx ", &xVal, Xs("xxx")},
|
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\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
|
||||||
ScanfTest{"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
|
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
|
// Renamed types
|
||||||
ScanfTest{"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
|
ScanfTest{"%v\n", "true\n", &renamedBoolVal, renamedBool(true)},
|
||||||
ScanfTest{"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
|
ScanfTest{"%t\n", "F\n", &renamedBoolVal, renamedBool(false)},
|
||||||
@ -213,6 +224,7 @@ var scanfTests = []ScanfTest{
|
|||||||
ScanfTest{"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
|
ScanfTest{"%d", "112\n", &renamedUint64Val, renamedUint64(112)},
|
||||||
ScanfTest{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
|
ScanfTest{"%d", "113\n", &renamedUintptrVal, renamedUintptr(113)},
|
||||||
ScanfTest{"%s", "114\n", &renamedStringVal, renamedString("114")},
|
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", "115.1\n", &renamedFloatVal, renamedFloat(115.1)},
|
||||||
ScanfTest{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
|
ScanfTest{"%g", "116e1\n", &renamedFloat32Val, renamedFloat32(116e1)},
|
||||||
ScanfTest{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
|
ScanfTest{"%g", "-11.7e+1", &renamedFloat64Val, renamedFloat64(-11.7e+1)},
|
||||||
|
Loading…
Reference in New Issue
Block a user