mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
store ids rather than Types in the structs so they can be encoded.
change Type to gobType. fix some bugs around recursive structures. lots of cleanup. add the first cut at a type encoder. R=rsc DELTA=400 (287 added, 11 deleted, 102 changed) OCL=31401 CL=31406
This commit is contained in:
parent
7472f4c951
commit
ec23467e65
8 changed files with 384 additions and 106 deletions
|
|
@ -199,6 +199,16 @@ func decUint64(i *decInstr, state *DecState, p unsafe.Pointer) {
|
|||
*(*uint64)(p) = uint64(DecodeUint(state));
|
||||
}
|
||||
|
||||
func decUintptr(i *decInstr, state *DecState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
if *(*unsafe.Pointer)(p) == nil {
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(uintptr));
|
||||
}
|
||||
p = *(*unsafe.Pointer)(p);
|
||||
}
|
||||
*(*uintptr)(p) = uintptr(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
|
||||
|
|
@ -367,7 +377,6 @@ func decodeSlice(atyp *reflect.SliceType, state *DecState, p uintptr, elemOp dec
|
|||
return decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, int(length), elemIndir);
|
||||
}
|
||||
|
||||
var decEngineMap = make(map[reflect.Type] *decEngine)
|
||||
var decOpMap = map[reflect.Type] decOp {
|
||||
reflect.Typeof((*reflect.BoolType)(nil)): decBool,
|
||||
reflect.Typeof((*reflect.IntType)(nil)): decInt,
|
||||
|
|
@ -380,6 +389,7 @@ var decOpMap = map[reflect.Type] decOp {
|
|||
reflect.Typeof((*reflect.Uint16Type)(nil)): decUint16,
|
||||
reflect.Typeof((*reflect.Uint32Type)(nil)): decUint32,
|
||||
reflect.Typeof((*reflect.Uint64Type)(nil)): decUint64,
|
||||
reflect.Typeof((*reflect.UintptrType)(nil)): decUintptr,
|
||||
reflect.Typeof((*reflect.FloatType)(nil)): decFloat,
|
||||
reflect.Typeof((*reflect.Float32Type)(nil)): decFloat32,
|
||||
reflect.Typeof((*reflect.Float64Type)(nil)): decFloat64,
|
||||
|
|
@ -415,8 +425,10 @@ func decOpFor(rt reflect.Type) (decOp, int) {
|
|||
case *reflect.StructType:
|
||||
// Generate a closure that calls out to the engine for the nested type.
|
||||
engine := getDecEngine(typ);
|
||||
info := getTypeInfo(typ);
|
||||
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
|
||||
state.err = decodeStruct(engine, t, state.r, uintptr(p), i.indir)
|
||||
// indirect through info to delay evaluation for recursive structs
|
||||
state.err = decodeStruct(info.decoder, t, state.r, uintptr(p), i.indir)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -426,7 +438,7 @@ func decOpFor(rt reflect.Type) (decOp, int) {
|
|||
return op, indir
|
||||
}
|
||||
|
||||
func compileDec(rt reflect.Type, typ Type) *decEngine {
|
||||
func compileDec(rt reflect.Type, typ gobType) *decEngine {
|
||||
srt, ok1 := rt.(*reflect.StructType);
|
||||
styp, ok2 := typ.(*structType);
|
||||
if !ok1 || !ok2 {
|
||||
|
|
@ -436,8 +448,8 @@ func compileDec(rt reflect.Type, typ Type) *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.
|
||||
// Assumes perfect correspondence between struct and gob,
|
||||
// which is safe to assume since typ was compiled from rt.
|
||||
f := srt.Field(fieldnum);
|
||||
op, indir := decOpFor(f.Type);
|
||||
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)};
|
||||
|
|
@ -446,14 +458,19 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
|
|||
}
|
||||
|
||||
|
||||
// typeLock must be held.
|
||||
func getDecEngine(rt reflect.Type) *decEngine {
|
||||
engine, ok := decEngineMap[rt];
|
||||
if !ok {
|
||||
pkg, name := rt.Name();
|
||||
engine = compileDec(rt, newType(name, rt));
|
||||
decEngineMap[rt] = engine;
|
||||
info := getTypeInfo(rt);
|
||||
if info.decoder == nil {
|
||||
if info.typeId.gobType() == nil {
|
||||
_pkg, name := rt.Name();
|
||||
info.typeId = newType(name, rt).id();
|
||||
}
|
||||
// mark this engine as underway before compiling to handle recursive types.
|
||||
info.decoder = new(decEngine);
|
||||
info.decoder = compileDec(rt, info.typeId.gobType());
|
||||
}
|
||||
return engine;
|
||||
return info.decoder;
|
||||
}
|
||||
|
||||
func Decode(r io.Reader, e interface{}) os.Error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue