2009-06-29 15:15:07 -07:00
|
|
|
// 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 (
|
2009-07-01 18:25:13 -07:00
|
|
|
"gob";
|
2009-06-29 15:15:07 -07:00
|
|
|
"io";
|
2009-06-30 17:59:41 -07:00
|
|
|
"math";
|
2009-06-29 15:15:07 -07:00
|
|
|
"os";
|
2009-07-01 18:25:13 -07:00
|
|
|
"reflect";
|
2009-06-30 16:20:31 -07:00
|
|
|
"unsafe";
|
2009-06-29 15:15:07 -07:00
|
|
|
)
|
|
|
|
|
|
2009-06-30 16:20:31 -07:00
|
|
|
// The global execution state of an instance of the decoder.
|
|
|
|
|
type DecState struct {
|
|
|
|
|
r io.Reader;
|
|
|
|
|
err os.Error;
|
|
|
|
|
base uintptr;
|
2009-07-01 18:25:13 -07:00
|
|
|
fieldnum int; // the last field number read.
|
2009-06-30 16:20:31 -07:00
|
|
|
buf [1]byte; // buffer used by the decoder; here to avoid allocation.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DecodeUint reads an encoded unsigned integer from state.r.
|
|
|
|
|
// Sets state.err. If state.err is already non-nil, it does nothing.
|
|
|
|
|
func DecodeUint(state *DecState) (x uint64) {
|
|
|
|
|
if state.err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2009-06-29 15:15:07 -07:00
|
|
|
for shift := uint(0);; shift += 7 {
|
2009-06-30 16:20:31 -07:00
|
|
|
var n int;
|
|
|
|
|
n, state.err = state.r.Read(&state.buf);
|
2009-06-29 15:15:07 -07:00
|
|
|
if n != 1 {
|
2009-06-30 16:20:31 -07:00
|
|
|
return 0
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-06-30 16:20:31 -07:00
|
|
|
b := uint64(state.buf[0]);
|
2009-06-29 15:15:07 -07:00
|
|
|
x |= b << shift;
|
|
|
|
|
if b&0x80 != 0 {
|
|
|
|
|
x &^= 0x80 << shift;
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-30 16:20:31 -07:00
|
|
|
return x;
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
|
2009-06-30 16:20:31 -07:00
|
|
|
// DecodeInt reads an encoded signed integer from state.r.
|
|
|
|
|
// Sets state.err. If state.err is already non-nil, it does nothing.
|
|
|
|
|
func DecodeInt(state *DecState) int64 {
|
|
|
|
|
x := DecodeUint(state);
|
|
|
|
|
if state.err != nil {
|
|
|
|
|
return 0
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
|
|
|
|
if x & 1 != 0 {
|
2009-06-30 16:20:31 -07:00
|
|
|
return ^int64(x>>1)
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-06-30 16:20:31 -07:00
|
|
|
return int64(x >> 1)
|
2009-06-29 15:15:07 -07:00
|
|
|
}
|
2009-06-30 17:59:41 -07:00
|
|
|
|
|
|
|
|
// The 'instructions' of the decoding machine
|
|
|
|
|
type decInstr struct {
|
|
|
|
|
op func(i *decInstr, state *DecState);
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since the encoder writes no zeros, if we arrive at a decoder we have
|
|
|
|
|
// a value to extract and store. The field number has already been read
|
|
|
|
|
// (it's how we knew to call this decoder).
|
|
|
|
|
// Each decoder is responsible for handling any indirections associated
|
|
|
|
|
// with the data structure. If any pointer so reached is nil, allocation must
|
|
|
|
|
// be done.
|
|
|
|
|
|
|
|
|
|
// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end.
|
|
|
|
|
func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer {
|
|
|
|
|
for ; indir > 1; indir-- {
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
// Allocation required
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer));
|
|
|
|
|
}
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
return p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decBool(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*bool)(p) = v != 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decInt(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*int)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decUint(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := uint(DecodeUint(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*uint)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decInt8(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int8(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*int8)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decUint8(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := uint8(DecodeUint(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*uint8)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decInt16(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int16(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*int16)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decUint16(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := uint16(DecodeUint(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*uint16)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decInt32(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int32(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*int32)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decUint32(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := uint32(DecodeUint(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*uint32)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decInt64(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := int64(DecodeInt(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*int64)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decUint64(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := uint64(DecodeUint(state));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*uint64)(p) = 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
|
|
|
|
|
// unswizzling.
|
|
|
|
|
func floatFromBits(u uint64) float64 {
|
|
|
|
|
var v uint64;
|
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
|
v <<= 8;
|
|
|
|
|
v |= u & 0xFF;
|
|
|
|
|
u >>= 8;
|
|
|
|
|
}
|
|
|
|
|
return math.Float64frombits(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decFloat(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := float(floatFromBits(uint64(DecodeUint(state))));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*float)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decFloat32(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := float32(floatFromBits(uint64(DecodeUint(state))));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*float32)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decFloat64(i *decInstr, state *DecState) {
|
|
|
|
|
p := unsafe.Pointer(state.base+i.offset);
|
|
|
|
|
if i.indir > 0 {
|
|
|
|
|
if i.indir > 1 {
|
|
|
|
|
p = decIndirect(p, i.indir);
|
|
|
|
|
}
|
|
|
|
|
if *(*unsafe.Pointer)(p) == nil {
|
|
|
|
|
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(int));
|
|
|
|
|
p = *(*unsafe.Pointer)(p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
v := floatFromBits(uint64(DecodeUint(state)));
|
|
|
|
|
if state.err == nil {
|
|
|
|
|
*(*float64)(p) = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-01 18:25:13 -07:00
|
|
|
|
|
|
|
|
// Execution engine
|
|
|
|
|
|
|
|
|
|
// The encoder engine is an array of instructions indexed by field number of the incoming
|
|
|
|
|
// data. It is executed with random access according to field number.
|
|
|
|
|
type decEngine struct {
|
|
|
|
|
instr []decInstr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var decEngineMap = make(map[reflect.Type] *decEngine)
|
|
|
|
|
var decOp = map[int] func(*decInstr, *DecState) {
|
|
|
|
|
reflect.BoolKind: decBool,
|
|
|
|
|
reflect.IntKind: decInt,
|
|
|
|
|
reflect.Int8Kind: decInt8,
|
|
|
|
|
reflect.Int16Kind: decInt16,
|
|
|
|
|
reflect.Int32Kind: decInt32,
|
|
|
|
|
reflect.Int64Kind: decInt64,
|
|
|
|
|
reflect.UintKind: decUint,
|
|
|
|
|
reflect.Uint8Kind: decUint8,
|
|
|
|
|
reflect.Uint16Kind: decUint16,
|
|
|
|
|
reflect.Uint32Kind: decUint32,
|
|
|
|
|
reflect.Uint64Kind: decUint64,
|
|
|
|
|
reflect.FloatKind: decFloat,
|
|
|
|
|
reflect.Float32Kind: decFloat32,
|
|
|
|
|
reflect.Float64Kind: decFloat64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func compileDec(rt reflect.Type, typ Type) *decEngine {
|
|
|
|
|
srt, ok1 := rt.(reflect.StructType);
|
|
|
|
|
styp, ok2 := typ.(*structType);
|
|
|
|
|
if !ok1 || !ok2 {
|
|
|
|
|
panicln("TODO: can't handle non-structs");
|
|
|
|
|
}
|
|
|
|
|
engine := new(decEngine);
|
|
|
|
|
engine.instr = make([]decInstr, len(styp.field));
|
|
|
|
|
for fieldnum := 0; fieldnum < len(styp.field); fieldnum++ {
|
|
|
|
|
field := styp.field[fieldnum];
|
|
|
|
|
// TODO(r): verify compatibility with corresponding field of data.
|
|
|
|
|
// For now, assume perfect correspondence between struct and gob.
|
|
|
|
|
_name, ftyp, _tag, offset := srt.Field(fieldnum);
|
|
|
|
|
// How many indirections to the underlying data?
|
|
|
|
|
indir := 0;
|
|
|
|
|
for {
|
|
|
|
|
pt, ok := ftyp.(reflect.PtrType);
|
|
|
|
|
if !ok {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
ftyp = pt.Sub();
|
|
|
|
|
indir++;
|
|
|
|
|
}
|
|
|
|
|
op, ok := decOp[ftyp.Kind()];
|
|
|
|
|
if !ok {
|
|
|
|
|
panicln("can't handle decode for type", ftyp.String());
|
|
|
|
|
}
|
|
|
|
|
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(offset)};
|
|
|
|
|
}
|
|
|
|
|
return engine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func getDecEngine(rt reflect.Type) *decEngine {
|
|
|
|
|
engine, ok := decEngineMap[rt];
|
|
|
|
|
if !ok {
|
|
|
|
|
return compileDec(rt, newType(rt.Name(), rt));
|
|
|
|
|
decEngineMap[rt] = engine;
|
|
|
|
|
}
|
|
|
|
|
return engine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (engine *decEngine) decode(r io.Reader, v reflect.Value) os.Error {
|
|
|
|
|
sv, ok := v.(reflect.StructValue);
|
|
|
|
|
if !ok {
|
|
|
|
|
panicln("decoder can't handle non-struct values yet");
|
|
|
|
|
}
|
|
|
|
|
state := new(DecState);
|
|
|
|
|
state.r = r;
|
|
|
|
|
state.base = uintptr(sv.Addr());
|
|
|
|
|
state.fieldnum = -1;
|
|
|
|
|
for state.err == nil {
|
|
|
|
|
delta := int(DecodeUint(state));
|
|
|
|
|
if state.err != nil || delta == 0 { // struct terminator is zero delta fieldnum
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fieldnum := state.fieldnum + delta;
|
|
|
|
|
if fieldnum >= len(engine.instr) {
|
|
|
|
|
panicln("TODO(r): need to handle unknown data");
|
|
|
|
|
}
|
|
|
|
|
instr := &engine.instr[fieldnum];
|
|
|
|
|
instr.op(instr, state);
|
|
|
|
|
state.fieldnum = fieldnum;
|
|
|
|
|
}
|
|
|
|
|
return state.err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Decode(r io.Reader, e interface{}) os.Error {
|
|
|
|
|
// Dereference down to the underlying object.
|
|
|
|
|
rt := reflect.Typeof(e);
|
|
|
|
|
v := reflect.NewValue(e);
|
|
|
|
|
for {
|
|
|
|
|
pt, ok := rt.(reflect.PtrType);
|
|
|
|
|
if !ok {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
rt = pt.Sub();
|
|
|
|
|
v = reflect.Indirect(v);
|
|
|
|
|
}
|
|
|
|
|
typeLock.Lock();
|
|
|
|
|
engine := getDecEngine(rt);
|
|
|
|
|
typeLock.Unlock();
|
|
|
|
|
return engine.decode(r, v);
|
|
|
|
|
}
|