mirror of
https://github.com/golang/go
synced 2024-11-14 08:30:25 -07:00
encoding/binary: Add support for slices of arrays of fixed-size values.
R=rsc CC=krasin https://golang.org/cl/167050
This commit is contained in:
parent
ddde7f6625
commit
349095885e
@ -113,15 +113,24 @@ func (bigEndian) String() string { return "BigEndian" }
|
|||||||
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
func (bigEndian) GoString() string { return "binary.BigEndian" }
|
||||||
|
|
||||||
// Read reads structured binary data from r into data.
|
// Read reads structured binary data from r into data.
|
||||||
// Data must be a pointer to a fixed-size value.
|
// Data must be a pointer to a fixed-size value or a slice
|
||||||
|
// of fixed-size values.
|
||||||
// A fixed-size value is either a fixed-size integer
|
// A fixed-size value is either a fixed-size integer
|
||||||
// (int8, uint8, int16, uint16, ...) or an array or struct
|
// (int8, uint8, int16, uint16, ...) or an array or struct
|
||||||
// containing only fixed-size values. Bytes read from
|
// containing only fixed-size values. Bytes read from
|
||||||
// r are decoded using the specified byte order and written
|
// r are decoded using the specified byte order and written
|
||||||
// to successive fields of the data.
|
// to successive fields of the data.
|
||||||
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||||
v := reflect.NewValue(data).(*reflect.PtrValue).Elem();
|
var v reflect.Value;
|
||||||
size := sizeof(v.Type());
|
switch d := reflect.NewValue(data).(type) {
|
||||||
|
case *reflect.PtrValue:
|
||||||
|
v = d.Elem()
|
||||||
|
case *reflect.SliceValue:
|
||||||
|
v = d
|
||||||
|
default:
|
||||||
|
return os.NewError("binary.Read: invalid type " + v.Type().String())
|
||||||
|
}
|
||||||
|
size := TotalSize(v);
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
return os.NewError("binary.Read: invalid type " + v.Type().String())
|
return os.NewError("binary.Read: invalid type " + v.Type().String())
|
||||||
}
|
}
|
||||||
@ -143,7 +152,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
|||||||
// from successive fields of the data.
|
// from successive fields of the data.
|
||||||
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
||||||
v := reflect.Indirect(reflect.NewValue(data));
|
v := reflect.Indirect(reflect.NewValue(data));
|
||||||
size := sizeof(v.Type());
|
size := TotalSize(v);
|
||||||
if size < 0 {
|
if size < 0 {
|
||||||
return os.NewError("binary.Write: invalid type " + v.Type().String())
|
return os.NewError("binary.Write: invalid type " + v.Type().String())
|
||||||
}
|
}
|
||||||
@ -154,8 +163,19 @@ func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
func sizeof(t reflect.Type) int {
|
func TotalSize(v reflect.Value) int {
|
||||||
switch t := t.(type) {
|
if sv, ok := v.(*reflect.SliceValue); ok {
|
||||||
|
elem := sizeof(v.Type().(*reflect.SliceType).Elem());
|
||||||
|
if elem < 0 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return sv.Len() * elem;
|
||||||
|
}
|
||||||
|
return sizeof(v.Type());
|
||||||
|
}
|
||||||
|
|
||||||
|
func sizeof(v reflect.Type) int {
|
||||||
|
switch t := v.(type) {
|
||||||
case *reflect.ArrayType:
|
case *reflect.ArrayType:
|
||||||
n := sizeof(t.Elem());
|
n := sizeof(t.Elem());
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
@ -281,6 +301,12 @@ func (d *decoder) value(v reflect.Value) {
|
|||||||
d.value(v.Field(i))
|
d.value(v.Field(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *reflect.SliceValue:
|
||||||
|
l := v.Len();
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
d.value(v.Elem(i))
|
||||||
|
}
|
||||||
|
|
||||||
case *reflect.Uint8Value:
|
case *reflect.Uint8Value:
|
||||||
v.Set(d.uint8())
|
v.Set(d.uint8())
|
||||||
case *reflect.Uint16Value:
|
case *reflect.Uint16Value:
|
||||||
@ -316,6 +342,11 @@ func (e *encoder) value(v reflect.Value) {
|
|||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
e.value(v.Field(i))
|
e.value(v.Field(i))
|
||||||
}
|
}
|
||||||
|
case *reflect.SliceValue:
|
||||||
|
l := v.Len();
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
e.value(v.Elem(i))
|
||||||
|
}
|
||||||
|
|
||||||
case *reflect.Uint8Value:
|
case *reflect.Uint8Value:
|
||||||
e.uint8(v.Get())
|
e.uint8(v.Get())
|
||||||
|
@ -64,6 +64,9 @@ var little = []byte{
|
|||||||
39, 40, 41, 42,
|
39, 40, 41, 42,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
|
||||||
|
var res = []int32{0x01020304, 0x05060708}
|
||||||
|
|
||||||
func checkResult(t *testing.T, dir string, order, err os.Error, have, want interface{}) {
|
func checkResult(t *testing.T, dir string, order, err os.Error, have, want interface{}) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%v %v: %v", dir, order, err);
|
t.Errorf("%v %v: %v", dir, order, err);
|
||||||
@ -97,3 +100,15 @@ func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s)
|
|||||||
func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
|
func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
|
||||||
|
|
||||||
func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
|
func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
|
||||||
|
|
||||||
|
func TestReadSlice(t *testing.T) {
|
||||||
|
slice := make([]int32, 2);
|
||||||
|
err := Read(bytes.NewBuffer(src), BigEndian, slice);
|
||||||
|
checkResult(t, "ReadSlice", BigEndian, err, slice, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteSlice(t *testing.T) {
|
||||||
|
buf := new(bytes.Buffer);
|
||||||
|
err := Write(buf, BigEndian, res);
|
||||||
|
checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user