diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/go/gob/encode.go | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libgo/go/gob/encode.go')
-rw-r--r-- | libgo/go/gob/encode.go | 573 |
1 files changed, 573 insertions, 0 deletions
diff --git a/libgo/go/gob/encode.go b/libgo/go/gob/encode.go new file mode 100644 index 000000000..d286a7e00 --- /dev/null +++ b/libgo/go/gob/encode.go @@ -0,0 +1,573 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "bytes" + "io" + "math" + "os" + "reflect" + "unsafe" +) + +const uint64Size = unsafe.Sizeof(uint64(0)) + +// The global execution state of an instance of the encoder. +// Field numbers are delta encoded and always increase. The field +// number is initialized to -1 so 0 comes out as delta(1). A delta of +// 0 terminates the structure. +type encoderState struct { + enc *Encoder + b *bytes.Buffer + sendZero bool // encoding an array element or map key/value pair; send zero values + fieldnum int // the last field number written. + buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation. +} + +func newEncoderState(enc *Encoder, b *bytes.Buffer) *encoderState { + return &encoderState{enc: enc, b: b} +} + +// Unsigned integers have a two-state encoding. If the number is less +// than 128 (0 through 0x7F), its value is written directly. +// Otherwise the value is written in big-endian byte order preceded +// by the byte length, negated. + +// encodeUint writes an encoded unsigned integer to state.b. +func (state *encoderState) encodeUint(x uint64) { + if x <= 0x7F { + err := state.b.WriteByte(uint8(x)) + if err != nil { + error(err) + } + return + } + var n, m int + m = uint64Size + for n = 1; x > 0; n++ { + state.buf[m] = uint8(x & 0xFF) + x >>= 8 + m-- + } + state.buf[m] = uint8(-(n - 1)) + n, err := state.b.Write(state.buf[m : uint64Size+1]) + if err != nil { + error(err) + } +} + +// encodeInt writes an encoded signed integer to state.w. +// The low bit of the encoding says whether to bit complement the (other bits of the) +// uint to recover the int. +func (state *encoderState) encodeInt(i int64) { + var x uint64 + if i < 0 { + x = uint64(^i<<1) | 1 + } else { + x = uint64(i << 1) + } + state.encodeUint(uint64(x)) +} + +type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer) + +// The 'instructions' of the encoding machine +type encInstr struct { + op encOp + field int // field number + indir int // how many pointer indirections to reach the value in the struct + offset uintptr // offset in the structure of the field to encode +} + +// Emit a field number and update the state to record its value for delta encoding. +// If the instruction pointer is nil, do nothing +func (state *encoderState) update(instr *encInstr) { + if instr != nil { + state.encodeUint(uint64(instr.field - state.fieldnum)) + state.fieldnum = instr.field + } +} + +// Each encoder is responsible for handling any indirections associated +// with the data structure. If any pointer so reached is nil, no bytes are written. +// If the data item is zero, no bytes are written. +// Otherwise, the output (for a scalar) is the field number, as an encoded integer, +// followed by the field data in its appropriate format. + +func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { + for ; indir > 0; indir-- { + p = *(*unsafe.Pointer)(p) + if p == nil { + return unsafe.Pointer(nil) + } + } + return p +} + +func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { + b := *(*bool)(p) + if b || state.sendZero { + state.update(i) + if b { + state.encodeUint(1) + } else { + state.encodeUint(0) + } + } +} + +func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint8)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint16)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := int64(*(*int32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uint32)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*int64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeInt(v) + } +} + +func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := *(*uint64)(p) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { + v := uint64(*(*uintptr)(p)) + if v != 0 || state.sendZero { + state.update(i) + state.encodeUint(v) + } +} + +// Floating-point numbers are transmitted as uint64s holding the bits +// of the underlying representation. They are sent byte-reversed, with +// the exponent end coming out first, so integer floating point numbers +// (for example) transmit more compactly. This routine does the +// swizzling. +func floatBits(f float64) uint64 { + u := math.Float64bits(f) + var v uint64 + for i := 0; i < 8; i++ { + v <<= 8 + v |= u & 0xFF + u >>= 8 + } + return v +} + +func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) { + f := *(*float32)(p) + if f != 0 || state.sendZero { + v := floatBits(float64(f)) + state.update(i) + state.encodeUint(v) + } +} + +func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) { + f := *(*float64)(p) + if f != 0 || state.sendZero { + state.update(i) + v := floatBits(f) + state.encodeUint(v) + } +} + +// Complex numbers are just a pair of floating-point numbers, real part first. +func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) { + c := *(*complex64)(p) + if c != 0+0i || state.sendZero { + rpart := floatBits(float64(real(c))) + ipart := floatBits(float64(imag(c))) + state.update(i) + state.encodeUint(rpart) + state.encodeUint(ipart) + } +} + +func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { + c := *(*complex128)(p) + if c != 0+0i || state.sendZero { + rpart := floatBits(real(c)) + ipart := floatBits(imag(c)) + state.update(i) + state.encodeUint(rpart) + state.encodeUint(ipart) + } +} + +func encNoOp(i *encInstr, state *encoderState, p unsafe.Pointer) { +} + +// Byte arrays are encoded as an unsigned count followed by the raw bytes. +func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { + b := *(*[]byte)(p) + if len(b) > 0 || state.sendZero { + state.update(i) + state.encodeUint(uint64(len(b))) + state.b.Write(b) + } +} + +// Strings are encoded as an unsigned count followed by the raw bytes. +func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { + s := *(*string)(p) + if len(s) > 0 || state.sendZero { + state.update(i) + state.encodeUint(uint64(len(s))) + io.WriteString(state.b, s) + } +} + +// The end of a struct is marked by a delta field number of 0. +func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.encodeUint(0) +} + +// Execution engine + +// The encoder engine is an array of instructions indexed by field number of the encoding +// data, typically a struct. It is executed top to bottom, walking the struct. +type encEngine struct { + instr []encInstr +} + +const singletonField = 0 + +func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := newEncoderState(enc, b) + state.fieldnum = singletonField + // There is no surrounding struct to frame the transmission, so we must + // generate data even if the item is zero. To do this, set sendZero. + state.sendZero = true + instr := &engine.instr[singletonField] + p := unsafe.Pointer(basep) // offset will be zero + if instr.indir > 0 { + if p = encIndirect(p, instr.indir); p == nil { + return + } + } + instr.op(instr, state, p) +} + +func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep uintptr) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + for i := 0; i < len(engine.instr); i++ { + instr := &engine.instr[i] + p := unsafe.Pointer(basep + instr.offset) + if instr.indir > 0 { + if p = encIndirect(p, instr.indir); p == nil { + continue + } + } + instr.op(instr, state, p) + } +} + +func (enc *Encoder) encodeArray(b *bytes.Buffer, p uintptr, op encOp, elemWid uintptr, elemIndir int, length int) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + state.sendZero = true + state.encodeUint(uint64(length)) + for i := 0; i < length; i++ { + elemp := p + up := unsafe.Pointer(elemp) + if elemIndir > 0 { + if up = encIndirect(up, elemIndir); up == nil { + errorf("gob: encodeArray: nil element") + } + elemp = uintptr(up) + } + op(nil, state, unsafe.Pointer(elemp)) + p += uintptr(elemWid) + } +} + +func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir int) { + for i := 0; i < indir && v != nil; i++ { + v = reflect.Indirect(v) + } + if v == nil { + errorf("gob: encodeReflectValue: nil element") + } + op(nil, state, unsafe.Pointer(v.Addr())) +} + +func (enc *Encoder) encodeMap(b *bytes.Buffer, mv *reflect.MapValue, keyOp, elemOp encOp, keyIndir, elemIndir int) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + state.sendZero = true + keys := mv.Keys() + state.encodeUint(uint64(len(keys))) + for _, key := range keys { + encodeReflectValue(state, key, keyOp, keyIndir) + encodeReflectValue(state, mv.Elem(key), elemOp, elemIndir) + } +} + +// To send an interface, we send a string identifying the concrete type, followed +// by the type identifier (which might require defining that type right now), followed +// by the concrete value. A nil value gets sent as the empty string for the name, +// followed by no value. +func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv *reflect.InterfaceValue) { + state := newEncoderState(enc, b) + state.fieldnum = -1 + state.sendZero = true + if iv.IsNil() { + state.encodeUint(0) + return + } + + typ, _ := indirect(iv.Elem().Type()) + name, ok := concreteTypeToName[typ] + if !ok { + errorf("gob: type not registered for interface: %s", typ) + } + // Send the name. + state.encodeUint(uint64(len(name))) + _, err := io.WriteString(state.b, name) + if err != nil { + error(err) + } + // Send (and maybe first define) the type id. + enc.sendTypeDescriptor(typ) + // Encode the value into a new buffer. + data := new(bytes.Buffer) + err = enc.encode(data, iv.Elem()) + if err != nil { + error(err) + } + state.encodeUint(uint64(data.Len())) + _, err = state.b.Write(data.Bytes()) + if err != nil { + error(err) + } +} + +var encOpMap = []encOp{ + reflect.Bool: encBool, + reflect.Int: encInt, + reflect.Int8: encInt8, + reflect.Int16: encInt16, + reflect.Int32: encInt32, + reflect.Int64: encInt64, + reflect.Uint: encUint, + reflect.Uint8: encUint8, + reflect.Uint16: encUint16, + reflect.Uint32: encUint32, + reflect.Uint64: encUint64, + reflect.Uintptr: encUintptr, + reflect.Float32: encFloat32, + reflect.Float64: encFloat64, + reflect.Complex64: encComplex64, + reflect.Complex128: encComplex128, + reflect.String: encString, +} + +// Return the encoding op for the base type under rt and +// the indirection count to reach it. +func (enc *Encoder) encOpFor(rt reflect.Type) (encOp, int) { + typ, indir := indirect(rt) + var op encOp + k := typ.Kind() + if int(k) < len(encOpMap) { + op = encOpMap[k] + } + if op == nil { + // Special cases + switch t := typ.(type) { + case *reflect.SliceType: + if t.Elem().Kind() == reflect.Uint8 { + op = encUint8Array + break + } + // Slices have a header; we decode it to find the underlying array. + elemOp, indir := enc.encOpFor(t.Elem()) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + slice := (*reflect.SliceHeader)(p) + if !state.sendZero && slice.Len == 0 { + return + } + state.update(i) + state.enc.encodeArray(state.b, slice.Data, elemOp, t.Elem().Size(), indir, int(slice.Len)) + } + case *reflect.ArrayType: + // True arrays have size in the type. + elemOp, indir := enc.encOpFor(t.Elem()) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.update(i) + state.enc.encodeArray(state.b, uintptr(p), elemOp, t.Elem().Size(), indir, t.Len()) + } + case *reflect.MapType: + keyOp, keyIndir := enc.encOpFor(t.Key()) + elemOp, elemIndir := enc.encOpFor(t.Elem()) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + // Maps cannot be accessed by moving addresses around the way + // that slices etc. can. We must recover a full reflection value for + // the iteration. + v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p)))) + mv := reflect.Indirect(v).(*reflect.MapValue) + if !state.sendZero && mv.Len() == 0 { + return + } + state.update(i) + state.enc.encodeMap(state.b, mv, keyOp, elemOp, keyIndir, elemIndir) + } + case *reflect.StructType: + // Generate a closure that calls out to the engine for the nested type. + enc.getEncEngine(typ) + info := mustGetTypeInfo(typ) + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + state.update(i) + // indirect through info to delay evaluation for recursive structs + state.enc.encodeStruct(state.b, info.encoder, uintptr(p)) + } + case *reflect.InterfaceType: + op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + // Interfaces transmit the name and contents of the concrete + // value they contain. + v := reflect.NewValue(unsafe.Unreflect(t, unsafe.Pointer((p)))) + iv := reflect.Indirect(v).(*reflect.InterfaceValue) + if !state.sendZero && (iv == nil || iv.IsNil()) { + return + } + state.update(i) + state.enc.encodeInterface(state.b, iv) + } + } + } + if op == nil { + errorf("gob enc: can't happen: encode type %s", rt.String()) + } + return op, indir +} + +// The local Type was compiled from the actual value, so we know it's compatible. +func (enc *Encoder) compileEnc(rt reflect.Type) *encEngine { + srt, isStruct := rt.(*reflect.StructType) + engine := new(encEngine) + if isStruct { + engine.instr = make([]encInstr, srt.NumField()+1) // +1 for terminator + for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ { + f := srt.Field(fieldnum) + op, indir := enc.encOpFor(f.Type) + if !isExported(f.Name) { + op = encNoOp + } + engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)} + } + engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0} + } else { + engine.instr = make([]encInstr, 1) + op, indir := enc.encOpFor(rt) + engine.instr[0] = encInstr{op, singletonField, indir, 0} // offset is zero + } + return engine +} + +// typeLock must be held (or we're in initialization and guaranteed single-threaded). +// The reflection type must have all its indirections processed out. +func (enc *Encoder) getEncEngine(rt reflect.Type) *encEngine { + info, err1 := getTypeInfo(rt) + if err1 != nil { + error(err1) + } + if info.encoder == nil { + // mark this engine as underway before compiling to handle recursive types. + info.encoder = new(encEngine) + info.encoder = enc.compileEnc(rt) + } + return info.encoder +} + +// Put this in a function so we can hold the lock only while compiling, not when encoding. +func (enc *Encoder) lockAndGetEncEngine(rt reflect.Type) *encEngine { + typeLock.Lock() + defer typeLock.Unlock() + return enc.getEncEngine(rt) +} + +func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value) (err os.Error) { + defer catchError(&err) + // Dereference down to the underlying object. + rt, indir := indirect(value.Type()) + for i := 0; i < indir; i++ { + value = reflect.Indirect(value) + } + engine := enc.lockAndGetEncEngine(rt) + if value.Type().Kind() == reflect.Struct { + enc.encodeStruct(b, engine, value.Addr()) + } else { + enc.encodeSingle(b, engine, value.Addr()) + } + return nil +} |