bug fix: encOpFor etc. need to indirect

R=rsc
DELTA=28  (7 added, 7 deleted, 14 changed)
OCL=31312
CL=31322
This commit is contained in:
Rob Pike 2009-07-07 21:05:24 -07:00
parent d7f1f53e86
commit 0ae7882b5c
2 changed files with 19 additions and 19 deletions

View File

@ -388,7 +388,10 @@ var decOpMap = map[reflect.Type] decOp {
func getDecEngine(rt reflect.Type) *decEngine
func decOpFor(typ reflect.Type) decOp {
// Return the decoding op for the base type under rt and
// the indirection count to reach it.
func decOpFor(rt reflect.Type) (decOp, int) {
typ, indir := indirect(rt);
op, ok := decOpMap[reflect.Typeof(typ)];
if !ok {
// Special cases
@ -398,15 +401,13 @@ func decOpFor(typ reflect.Type) decOp {
op = decUint8Array;
break;
}
elemOp := decOpFor(t.Elem());
_, elemIndir := indirect(t.Elem());
elemOp, elemIndir := decOpFor(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir);
};
case *reflect.ArrayType:
elemOp := decOpFor(t.Elem());
_, elemIndir := indirect(t.Elem());
elemOp, elemIndir := decOpFor(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeArray(t, state, uintptr(p), elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir);
};
@ -420,9 +421,9 @@ func decOpFor(typ reflect.Type) decOp {
}
}
if op == nil {
panicln("decode can't handle type", typ.String());
panicln("decode can't handle type", rt.String());
}
return op
return op, indir
}
func compileDec(rt reflect.Type, typ Type) *decEngine {
@ -438,8 +439,7 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
// TODO(r): verify compatibility with corresponding field of data.
// For now, assume perfect correspondence between struct and gob.
f := srt.Field(fieldnum);
ftyp, indir := indirect(f.Type);
op := decOpFor(ftyp);
op, indir := decOpFor(f.Type);
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)};
}
return engine;

View File

@ -268,7 +268,6 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error {
p := unsafe.Pointer(basep+instr.offset);
if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil {
state.fieldnum = i;
continue
}
}
@ -321,9 +320,13 @@ var encOpMap = map[reflect.Type] encOp {
func getEncEngine(rt reflect.Type) *encEngine
func encOpFor(typ reflect.Type) encOp {
// Return the encoding op for the base type under rt and
// the indirection count to reach it.
func encOpFor(rt reflect.Type) (encOp, int) {
typ, indir := indirect(rt);
op, ok := encOpMap[reflect.Typeof(typ)];
if !ok {
typ, _ := indirect(rt);
// Special cases
switch t := typ.(type) {
case *reflect.SliceType:
@ -332,8 +335,7 @@ func encOpFor(typ reflect.Type) encOp {
break;
}
// Slices have a header; we decode it to find the underlying array.
elemOp := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
elemOp, indir := encOpFor(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
slice := (*reflect.SliceHeader)(p);
if slice.Len == 0 {
@ -344,8 +346,7 @@ func encOpFor(typ reflect.Type) encOp {
};
case *reflect.ArrayType:
// True arrays have size in the type.
elemOp := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
elemOp, indir := encOpFor(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
state.update(i);
state.err = encodeArray(state.w, uintptr(p), elemOp, t.Elem().Size(), t.Len(), indir);
@ -360,9 +361,9 @@ func encOpFor(typ reflect.Type) encOp {
}
}
if op == nil {
panicln("encode can't handle type", typ.String());
panicln("encode can't handle type", rt.String());
}
return op
return op, indir
}
// The local Type was compiled from the actual value, so we know
@ -377,8 +378,7 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine {
engine.instr = make([]encInstr, srt.NumField()+1); // +1 for terminator
for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
f := srt.Field(fieldnum);
ftyp, indir := indirect(f.Type);
op := encOpFor(ftyp);
op, indir := encOpFor(f.Type);
engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)};
}
engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0};