diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 15:47:21 +0000 |
commit | adb0401dac41c81571722312d4586b2693f95aa6 (patch) | |
tree | ea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/gob/encode.go | |
parent | 5548ca3540bccbc908a45942896d635ea5f1c23f (diff) | |
download | gcc-adb0401dac41c81571722312d4586b2693f95aa6.zip gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.bz2 |
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/gob/encode.go')
-rw-r--r-- | libgo/go/gob/encode.go | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/libgo/go/gob/encode.go b/libgo/go/gob/encode.go index f9e691a..317014e 100644 --- a/libgo/go/gob/encode.go +++ b/libgo/go/gob/encode.go @@ -11,7 +11,7 @@ import ( "unsafe" ) -const uint64Size = unsafe.Sizeof(uint64(0)) +const uint64Size = int(unsafe.Sizeof(uint64(0))) // encoderState is the global execution state of an instance of the encoder. // Field numbers are delta encoded and always increase. The field @@ -62,7 +62,7 @@ func (state *encoderState) encodeUint(x uint64) { var n, m int m = uint64Size for n = 1; x > 0; n++ { - state.buf[m] = uint8(x & 0xFF) + state.buf[m] = uint8(x) x >>= 8 m-- } @@ -466,9 +466,30 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { enc.freeEncoderState(state) } +// isZero returns whether the value is the zero of its type. +func isZero(val reflect.Value) bool { + switch val.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return val.Len() == 0 + case reflect.Bool: + return !val.Bool() + case reflect.Complex64, reflect.Complex128: + return val.Complex() == 0 + case reflect.Chan, reflect.Func, reflect.Ptr: + return val.IsNil() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return val.Int() == 0 + case reflect.Float32, reflect.Float64: + return val.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return val.Uint() == 0 + } + panic("unknown type in isZero " + val.Type().String()) +} + // encGobEncoder encodes a value that implements the GobEncoder interface. // The data is sent as a byte array. -func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value, index int) { +func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, v reflect.Value) { // TODO: should we catch panics from the called method? // We know it's a GobEncoder, so just call the method directly. data, err := v.Interface().(GobEncoder).GobEncode() @@ -557,7 +578,9 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp // the iteration. v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) mv := reflect.Indirect(v) - if !state.sendZero && mv.Len() == 0 { + // We send zero-length (but non-nil) maps because the + // receiver might want to use the map. (Maps don't use append.) + if !state.sendZero && mv.IsNil() { return } state.update(i) @@ -592,17 +615,6 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp return &op, indir } -// methodIndex returns which method of rt implements the method. -func methodIndex(rt reflect.Type, method string) int { - for i := 0; i < rt.NumMethod(); i++ { - if rt.Method(i).Name == method { - return i - } - } - errorf("internal error: can't find method %s", method) - return 0 -} - // gobEncodeOpFor returns the op for a type that is known to implement // GobEncoder. func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { @@ -623,8 +635,11 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { } else { v = reflect.ValueOf(unsafe.Unreflect(rt, p)) } + if !state.sendZero && isZero(v) { + return + } state.update(i) - state.enc.encodeGobEncoder(state.b, v, methodIndex(rt, gobEncodeMethodName)) + state.enc.encodeGobEncoder(state.b, v) } return &op, int(ut.encIndir) // encIndir: op will get called with p == address of receiver. } |