summaryrefslogtreecommitdiff
path: root/src/pkg
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2010-06-02 16:28:01 -0700
committerRob Pike <r@golang.org>2010-06-02 16:28:01 -0700
commitacfa7bba3bc06798c6c2692e126fb61bbbaf9c2b (patch)
tree8cc6c73f92eb4340ff5af6736240ded11f832b7a /src/pkg
parent959c2f651e03ff0e7c40855176750bf3dd11508f (diff)
downloadgolang-acfa7bba3bc06798c6c2692e126fb61bbbaf9c2b.tar.gz
fmt.Scan: scan []byte arguments
R=rsc CC=golang-dev http://codereview.appspot.com/1486041
Diffstat (limited to 'src/pkg')
-rw-r--r--src/pkg/fmt/print.go1
-rw-r--r--src/pkg/fmt/scan.go28
-rw-r--r--src/pkg/fmt/scan_test.go12
3 files changed, 34 insertions, 7 deletions
diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go
index c45438c4e..bb6990ae9 100644
--- a/src/pkg/fmt/print.go
+++ b/src/pkg/fmt/print.go
@@ -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"
diff --git a/src/pkg/fmt/scan.go b/src/pkg/fmt/scan.go
index 270856857..87ec695fb 100644
--- a/src/pkg/fmt/scan.go
+++ b/src/pkg/fmt/scan.go
@@ -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")
}
diff --git a/src/pkg/fmt/scan_test.go b/src/pkg/fmt/scan_test.go
index cd19903eb..6ea5ec95f 100644
--- a/src/pkg/fmt/scan_test.go
+++ b/src/pkg/fmt/scan_test.go
@@ -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)},