diff options
Diffstat (limited to 'libgo/go/encoding/binary/binary.go')
-rw-r--r-- | libgo/go/encoding/binary/binary.go | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index 8c2d1d9da47..a99ca019949 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -26,6 +26,7 @@ import ( "io" "math" "reflect" + "sync" ) // A ByteOrder specifies how to convert byte sequences into @@ -184,6 +185,10 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { *data = int64(order.Uint64(bs)) case *uint64: *data = order.Uint64(bs) + case *float32: + *data = math.Float32frombits(order.Uint32(bs)) + case *float64: + *data = math.Float64frombits(order.Uint64(bs)) case []bool: for i, x := range bs { // Easier to loop over the input for 8-bit values. data[i] = x != 0 @@ -218,8 +223,20 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { for i := range data { data[i] = order.Uint64(bs[8*i:]) } + case []float32: + for i := range data { + data[i] = math.Float32frombits(order.Uint32(bs[4*i:])) + } + case []float64: + for i := range data { + data[i] = math.Float64frombits(order.Uint64(bs[8*i:])) + } + default: + n = 0 // fast path doesn't apply + } + if n != 0 { + return nil } - return nil } // Fallback to reflect-based decoding. @@ -338,6 +355,22 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error { for i, x := range v { order.PutUint64(bs[8*i:], x) } + case *float32: + order.PutUint32(bs, math.Float32bits(*v)) + case float32: + order.PutUint32(bs, math.Float32bits(v)) + case []float32: + for i, x := range v { + order.PutUint32(bs[4*i:], math.Float32bits(x)) + } + case *float64: + order.PutUint64(bs, math.Float64bits(*v)) + case float64: + order.PutUint64(bs, math.Float64bits(v)) + case []float64: + for i, x := range v { + order.PutUint64(bs[8*i:], math.Float64bits(x)) + } } _, err := w.Write(bs) return err @@ -363,18 +396,32 @@ func Size(v interface{}) int { return dataSize(reflect.Indirect(reflect.ValueOf(v))) } +var structSize sync.Map // map[reflect.Type]int + // dataSize returns the number of bytes the actual data represented by v occupies in memory. // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice // it returns the length of the slice times the element size and does not count the memory // occupied by the header. If the type of v is not acceptable, dataSize returns -1. func dataSize(v reflect.Value) int { - if v.Kind() == reflect.Slice { + switch v.Kind() { + case reflect.Slice: if s := sizeof(v.Type().Elem()); s >= 0 { return s * v.Len() } return -1 + + case reflect.Struct: + t := v.Type() + if size, ok := structSize.Load(t); ok { + return size.(int) + } + size := sizeof(t) + structSize.Store(t, size) + return size + + default: + return sizeof(v.Type()) } - return sizeof(v.Type()) } // sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. @@ -677,6 +724,14 @@ func intDataSize(data interface{}) int { return 8 * len(data) case []uint64: return 8 * len(data) + case float32, *float32: + return 4 + case float64, *float64: + return 8 + case []float32: + return 4 * len(data) + case []float64: + return 8 * len(data) } return 0 } |