// 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 // TODO(rsc): When garbage collector changes, revisit // the allocations in this file that use unsafe.Pointer. import ( "gob"; "io"; "math"; "os"; "reflect"; "unsafe"; ) // The global execution state of an instance of the decoder. type DecState struct { r io.Reader; err os.Error; fieldnum int; // the last field number read. 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 } for shift := uint(0);; shift += 7 { var n int; n, state.err = state.r.Read(&state.buf); if n != 1 { return 0 } b := uint64(state.buf[0]); x |= b << shift; if b&0x80 != 0 { x &^= 0x80 << shift; break } } return x; } // 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 } if x & 1 != 0 { return ^int64(x>>1) } return int64(x >> 1) } type decInstr struct type decOp func(i *decInstr, state *DecState, p unsafe.Pointer); // The 'instructions' of the decoding machine type decInstr struct { op decOp; 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) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool)); } p = *(*unsafe.Pointer)(p); } *(*bool)(p) = DecodeInt(state) != 0; } func decInt(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int)); } p = *(*unsafe.Pointer)(p); } *(*int)(p) = int(DecodeInt(state)); } func decUint(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint)); } p = *(*unsafe.Pointer)(p); } *(*uint)(p) = uint(DecodeUint(state)); } func decInt8(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8)); } p = *(*unsafe.Pointer)(p); } *(*int8)(p) = int8(DecodeInt(state)); } func decUint8(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8)); } p = *(*unsafe.Pointer)(p); } *(*uint8)(p) = uint8(DecodeUint(state)); } func decInt16(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16)); } p = *(*unsafe.Pointer)(p); } *(*int16)(p) = int16(DecodeInt(state)); } func decUint16(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16)); } p = *(*unsafe.Pointer)(p); } *(*uint16)(p) = uint16(DecodeUint(state)); } func decInt32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32)); } p = *(*unsafe.Pointer)(p); } *(*int32)(p) = int32(DecodeInt(state)); } func decUint32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32)); } p = *(*unsafe.Pointer)(p); } *(*uint32)(p) = uint32(DecodeUint(state)); } func decInt64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64)); } p = *(*unsafe.Pointer)(p); } *(*int64)(p) = int64(DecodeInt(state)); } func decUint64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64)); } p = *(*unsafe.Pointer)(p); } *(*uint64)(p) = uint64(DecodeUint(state)); } // 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) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float)); } p = *(*unsafe.Pointer)(p); } *(*float)(p) = float(floatFromBits(uint64(DecodeUint(state)))); } func decFloat32(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32)); } p = *(*unsafe.Pointer)(p); } *(*float32)(p) = float32(floatFromBits(uint64(DecodeUint(state)))); } func decFloat64(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64)); } p = *(*unsafe.Pointer)(p); } *(*float64)(p) = floatFromBits(uint64(DecodeUint(state))); } // uint8 arrays are encoded as an unsigned count followed by the raw bytes. func decUint8Array(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8)); } p = *(*unsafe.Pointer)(p); } b := make([]uint8, DecodeUint(state)); state.r.Read(b); *(*[]uint8)(p) = b; } // Strings are encoded as an unsigned count followed by the raw bytes. func decString(i *decInstr, state *DecState, p unsafe.Pointer) { if i.indir > 0 { if *(*unsafe.Pointer)(p) == nil { *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]byte)); } p = *(*unsafe.Pointer)(p); } b := make([]byte, DecodeUint(state)); state.r.Read(b); *(*string)(p) = string(b); } // 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 } func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uintptr, indir int) os.Error { if indir > 0 { up := unsafe.Pointer(p); if *(*unsafe.Pointer)(up) == nil { // Allocate the structure by making a slice of bytes and recording the // address of the beginning of the array. TODO(rsc). b := make([]byte, rtyp.Size()); *(*unsafe.Pointer)(up) = unsafe.Pointer(&b[0]); } p = *(*uintptr)(up); } state := new(DecState); state.r = r; state.fieldnum = -1; basep := p; 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]; p := unsafe.Pointer(basep+instr.offset); if instr.indir > 1 { p = decIndirect(p, instr.indir); } instr.op(instr, state, p); state.fieldnum = fieldnum; } return state.err } func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length, elemIndir int) os.Error { instr := &decInstr{elemOp, 0, elemIndir, 0}; for i := 0; i < length && state.err == nil; i++ { up := unsafe.Pointer(p); if elemIndir > 1 { up = decIndirect(up, elemIndir); } elemOp(instr, state, up); p += uintptr(elemWid); } return state.err } func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, length, indir, elemIndir int) os.Error { if indir > 0 { up := unsafe.Pointer(p); if *(*unsafe.Pointer)(up) == nil { // Allocate the array by making a slice of bytes of the correct size // and taking the address of the beginning of the array. TODO(rsc). b := make([]byte, atyp.Size()); *(**byte)(up) = &b[0]; } p = *(*uintptr)(up); } if DecodeUint(state) != uint64(length) { return os.ErrorString("length mismatch in decodeArray"); } return decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir); } func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid, indir, elemIndir int) os.Error { length := int(DecodeUint(state)); if indir > 0 { up := unsafe.Pointer(p); if *(*unsafe.Pointer)(up) == nil { // Allocate the slice header. *(*unsafe.Pointer)(up) = unsafe.Pointer(new(reflect.SliceHeader)); } p = *(*uintptr)(up); } // Allocate storage for the slice elements, that is, the underlying array. data := make([]byte, length*atyp.Elem().Size()); // Always write a header at p. hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p)); hdrp.Data = uintptr(unsafe.Pointer(&data[0])); hdrp.Len = uint32(length); hdrp.Cap = uint32(length); return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, length, elemIndir); } var decEngineMap = make(map[reflect.Type] *decEngine) var decOpMap = map[int] decOp { 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, reflect.StringKind: decString, } func getDecEngine(rt reflect.Type) *decEngine func decOpFor(typ reflect.Type) decOp { op, ok := decOpMap[typ.Kind()]; if !ok { // Special cases if typ.Kind() == reflect.ArrayKind { atyp := typ.(reflect.ArrayType); switch { case atyp.Elem().Kind() == reflect.Uint8Kind: op = decUint8Array case atyp.IsSlice(): elemOp := decOpFor(atyp.Elem()); _, elemIndir := indirect(atyp.Elem()); op = func(i *decInstr, state *DecState, p unsafe.Pointer) { state.err = decodeSlice(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), i.indir, elemIndir); }; case !atyp.IsSlice(): elemOp := decOpFor(atyp.Elem()); _, elemIndir := indirect(atyp.Elem()); op = func(i *decInstr, state *DecState, p unsafe.Pointer) { state.err = decodeArray(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), i.indir, elemIndir); }; } } if typ.Kind() == reflect.StructKind { // Generate a closure that calls out to the engine for the nested type. engine := getDecEngine(typ); styp := typ.(reflect.StructType); op = func(i *decInstr, state *DecState, p unsafe.Pointer) { state.err = decodeStruct(engine, styp, state.r, uintptr(p), i.indir) }; } } if op == nil { panicln("decode can't handle type", typ.String()); } return op } 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 := decOpFor(ftyp); 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 Decode(r io.Reader, e interface{}) os.Error { // Dereference down to the underlying object. rt, indir := indirect(reflect.Typeof(e)); v := reflect.NewValue(e); for i := 0; i < indir; i++ { v = reflect.Indirect(v); } if rt.Kind() != reflect.StructKind { return os.ErrorString("decode can't handle " + rt.String()) } typeLock.Lock(); engine := getDecEngine(rt); typeLock.Unlock(); return decodeStruct(engine, rt.(reflect.StructType), r, uintptr(v.Addr()), 0); }