mirror of
https://github.com/golang/go
synced 2024-11-22 04:54:42 -07:00
encoding/binary: implemented the Write function
The ByteOrder.Put* methods are already available, this change uses them to implement the Write function. R=golang-dev, agl1, rsc, r https://golang.org/cl/152141
This commit is contained in:
parent
a09997c3aa
commit
a54684f8da
@ -117,8 +117,8 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
|
||||
// A fixed-size value is either a fixed-size integer
|
||||
// (int8, uint8, int16, uint16, ...) or an array or struct
|
||||
// containing only fixed-size values. Bytes read from
|
||||
// r are decoded using order and written to successive
|
||||
// fields of the data.
|
||||
// r are decoded using the specified byte order and written
|
||||
// to successive fields of the data.
|
||||
func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
v := reflect.NewValue(data).(*reflect.PtrValue).Elem();
|
||||
size := sizeof(v.Type());
|
||||
@ -133,6 +133,27 @@ func Read(r io.Reader, order ByteOrder, data interface{}) os.Error {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Write writes the binary representation of data into w.
|
||||
// Data must be a fixed-size value or a pointer to
|
||||
// a fixed-size value.
|
||||
// A fixed-size value is either a fixed-size integer
|
||||
// (int8, uint8, int16, uint16, ...) or an array or struct
|
||||
// containing only fixed-size values. Bytes written to
|
||||
// w are encoded using the specified byte order and read
|
||||
// from successive fields of the data.
|
||||
func Write(w io.Writer, order ByteOrder, data interface{}) os.Error {
|
||||
v := reflect.Indirect(reflect.NewValue(data));
|
||||
size := sizeof(v.Type());
|
||||
if size < 0 {
|
||||
return os.NewError("binary.Write: invalid type " + v.Type().String())
|
||||
}
|
||||
buf := make([]byte, size);
|
||||
e := &encoder{order: order, buf: buf};
|
||||
e.value(v);
|
||||
_, err := w.Write(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
func sizeof(t reflect.Type) int {
|
||||
switch t := t.(type) {
|
||||
case *reflect.ArrayType:
|
||||
@ -182,38 +203,71 @@ type decoder struct {
|
||||
buf []byte;
|
||||
}
|
||||
|
||||
type encoder struct {
|
||||
order ByteOrder;
|
||||
buf []byte;
|
||||
}
|
||||
|
||||
func (d *decoder) uint8() uint8 {
|
||||
x := d.buf[0];
|
||||
d.buf = d.buf[1:len(d.buf)];
|
||||
return x;
|
||||
}
|
||||
|
||||
func (e *encoder) uint8(x uint8) {
|
||||
e.buf[0] = x;
|
||||
e.buf = e.buf[1:len(e.buf)];
|
||||
}
|
||||
|
||||
func (d *decoder) uint16() uint16 {
|
||||
x := d.order.Uint16(d.buf[0:2]);
|
||||
d.buf = d.buf[2:len(d.buf)];
|
||||
return x;
|
||||
}
|
||||
|
||||
func (e *encoder) uint16(x uint16) {
|
||||
e.order.PutUint16(e.buf[0:2], x);
|
||||
e.buf = e.buf[2:len(e.buf)];
|
||||
}
|
||||
|
||||
func (d *decoder) uint32() uint32 {
|
||||
x := d.order.Uint32(d.buf[0:4]);
|
||||
d.buf = d.buf[4:len(d.buf)];
|
||||
return x;
|
||||
}
|
||||
|
||||
func (e *encoder) uint32(x uint32) {
|
||||
e.order.PutUint32(e.buf[0:4], x);
|
||||
e.buf = e.buf[4:len(e.buf)];
|
||||
}
|
||||
|
||||
func (d *decoder) uint64() uint64 {
|
||||
x := d.order.Uint64(d.buf[0:8]);
|
||||
d.buf = d.buf[8:len(d.buf)];
|
||||
return x;
|
||||
}
|
||||
|
||||
func (e *encoder) uint64(x uint64) {
|
||||
e.order.PutUint64(e.buf[0:8], x);
|
||||
e.buf = e.buf[8:len(e.buf)];
|
||||
}
|
||||
|
||||
func (d *decoder) int8() int8 { return int8(d.uint8()) }
|
||||
|
||||
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
|
||||
|
||||
func (d *decoder) int16() int16 { return int16(d.uint16()) }
|
||||
|
||||
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
|
||||
|
||||
func (d *decoder) int32() int32 { return int32(d.uint32()) }
|
||||
|
||||
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
|
||||
|
||||
func (d *decoder) int64() int64 { return int64(d.uint64()) }
|
||||
|
||||
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
|
||||
|
||||
func (d *decoder) value(v reflect.Value) {
|
||||
switch v := v.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
@ -249,3 +303,39 @@ func (d *decoder) value(v reflect.Value) {
|
||||
v.Set(math.Float64frombits(d.uint64()))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) value(v reflect.Value) {
|
||||
switch v := v.(type) {
|
||||
case *reflect.ArrayValue:
|
||||
l := v.Len();
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Elem(i))
|
||||
}
|
||||
case *reflect.StructValue:
|
||||
l := v.NumField();
|
||||
for i := 0; i < l; i++ {
|
||||
e.value(v.Field(i))
|
||||
}
|
||||
|
||||
case *reflect.Uint8Value:
|
||||
e.uint8(v.Get())
|
||||
case *reflect.Uint16Value:
|
||||
e.uint16(v.Get())
|
||||
case *reflect.Uint32Value:
|
||||
e.uint32(v.Get())
|
||||
case *reflect.Uint64Value:
|
||||
e.uint64(v.Get())
|
||||
case *reflect.Int8Value:
|
||||
e.int8(v.Get())
|
||||
case *reflect.Int16Value:
|
||||
e.int16(v.Get())
|
||||
case *reflect.Int32Value:
|
||||
e.int32(v.Get())
|
||||
case *reflect.Int64Value:
|
||||
e.int64(v.Get())
|
||||
case *reflect.Float32Value:
|
||||
e.uint32(math.Float32bits(v.Get()))
|
||||
case *reflect.Float64Value:
|
||||
e.uint64(math.Float64bits(v.Get()))
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"os";
|
||||
"bytes";
|
||||
"math";
|
||||
"reflect";
|
||||
@ -63,24 +64,36 @@ var little = []byte{
|
||||
39, 40, 41, 42,
|
||||
}
|
||||
|
||||
func TestRead(t *testing.T) {
|
||||
var sl, sb Struct;
|
||||
|
||||
err := Read(bytes.NewBuffer(big), BigEndian, &sb);
|
||||
func checkResult(t *testing.T, dir string, order, err os.Error, have, want interface{}) {
|
||||
if err != nil {
|
||||
t.Errorf("Read big-endian: %v", err);
|
||||
goto little;
|
||||
t.Errorf("%v %v: %v", dir, order, err);
|
||||
return;
|
||||
}
|
||||
if !reflect.DeepEqual(have, want) {
|
||||
t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
|
||||
}
|
||||
if !reflect.DeepEqual(sb, s) {
|
||||
t.Errorf("Read big-endian:\n\thave %+v\n\twant %+v", sb, s)
|
||||
}
|
||||
|
||||
little:
|
||||
err = Read(bytes.NewBuffer(little), LittleEndian, &sl);
|
||||
if err != nil {
|
||||
t.Errorf("Read little-endian: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(sl, s) {
|
||||
t.Errorf("Read little-endian:\n\thave %+v\n\twant %+v", sl, s)
|
||||
func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
|
||||
var s2 Struct;
|
||||
err := Read(bytes.NewBuffer(b), order, &s2);
|
||||
checkResult(t, "Read", order, err, s2, s1);
|
||||
}
|
||||
|
||||
func testWrite(t *testing.T, order ByteOrder, b []byte, s1 interface{}) {
|
||||
buf := new(bytes.Buffer);
|
||||
err := Write(buf, order, s1);
|
||||
checkResult(t, "Write", order, err, buf.Bytes(), b);
|
||||
}
|
||||
|
||||
func TestBigEndianRead(t *testing.T) { testRead(t, BigEndian, big, s) }
|
||||
|
||||
func TestLittleEndianRead(t *testing.T) { testRead(t, LittleEndian, little, s) }
|
||||
|
||||
func TestBigEndianWrite(t *testing.T) { testWrite(t, BigEndian, big, s) }
|
||||
|
||||
func TestLittleEndianWrite(t *testing.T) { testWrite(t, LittleEndian, little, s) }
|
||||
|
||||
func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) }
|
||||
|
||||
func TestLittleEndianPtrWrite(t *testing.T) { testWrite(t, LittleEndian, little, &s) }
|
||||
|
Loading…
Reference in New Issue
Block a user