]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/binary: implemented the Write function
authorMôshe van der Sterre <moshevds@gmail.com>
Sat, 14 Nov 2009 22:42:22 +0000 (14:42 -0800)
committerRuss Cox <rsc@golang.org>
Sat, 14 Nov 2009 22:42:22 +0000 (14:42 -0800)
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

src/pkg/encoding/binary/binary.go
src/pkg/encoding/binary/binary_test.go

index abf2465cc751fe26291725e3a74b0b1728fafefe..92c89cea97413d045d496d83fa9314334c433cba 100644 (file)
@@ -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()))
+       }
+}
index 71c6875cc96bf26306a630ba4e808a75e5747cbb..d98f050563fc0ea2ae71dc9ad30f906a78947c82 100644 (file)
@@ -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(sb, s) {
-               t.Errorf("Read big-endian:\n\thave %+v\n\twant %+v", sb, s)
+       if !reflect.DeepEqual(have, want) {
+               t.Errorf("%v %v:\n\thave %+v\n\twant %+v", dir, order, have, want)
        }
+}
 
-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) }