1
0
mirror of https://github.com/golang/go synced 2024-10-03 04:21:22 -06:00

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 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)]; op, ok := decOpMap[reflect.Typeof(typ)];
if !ok { if !ok {
// Special cases // Special cases
@ -398,15 +401,13 @@ func decOpFor(typ reflect.Type) decOp {
op = decUint8Array; op = decUint8Array;
break; break;
} }
elemOp := decOpFor(t.Elem()); elemOp, elemIndir := decOpFor(t.Elem());
_, elemIndir := indirect(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) { op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir); state.err = decodeSlice(t, state, uintptr(p), elemOp, t.Elem().Size(), i.indir, elemIndir);
}; };
case *reflect.ArrayType: case *reflect.ArrayType:
elemOp := decOpFor(t.Elem()); elemOp, elemIndir := decOpFor(t.Elem());
_, elemIndir := indirect(t.Elem());
op = func(i *decInstr, state *DecState, p unsafe.Pointer) { 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); 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 { 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 { 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. // TODO(r): verify compatibility with corresponding field of data.
// For now, assume perfect correspondence between struct and gob. // For now, assume perfect correspondence between struct and gob.
f := srt.Field(fieldnum); f := srt.Field(fieldnum);
ftyp, indir := indirect(f.Type); op, indir := decOpFor(f.Type);
op := decOpFor(ftyp);
engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)}; engine.instr[fieldnum] = decInstr{op, fieldnum, indir, uintptr(f.Offset)};
} }
return engine; 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); p := unsafe.Pointer(basep+instr.offset);
if instr.indir > 0 { if instr.indir > 0 {
if p = encIndirect(p, instr.indir); p == nil { if p = encIndirect(p, instr.indir); p == nil {
state.fieldnum = i;
continue continue
} }
} }
@ -321,9 +320,13 @@ var encOpMap = map[reflect.Type] encOp {
func getEncEngine(rt reflect.Type) *encEngine 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)]; op, ok := encOpMap[reflect.Typeof(typ)];
if !ok { if !ok {
typ, _ := indirect(rt);
// Special cases // Special cases
switch t := typ.(type) { switch t := typ.(type) {
case *reflect.SliceType: case *reflect.SliceType:
@ -332,8 +335,7 @@ func encOpFor(typ reflect.Type) encOp {
break; break;
} }
// Slices have a header; we decode it to find the underlying array. // Slices have a header; we decode it to find the underlying array.
elemOp := encOpFor(t.Elem()); elemOp, indir := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) { op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
slice := (*reflect.SliceHeader)(p); slice := (*reflect.SliceHeader)(p);
if slice.Len == 0 { if slice.Len == 0 {
@ -344,8 +346,7 @@ func encOpFor(typ reflect.Type) encOp {
}; };
case *reflect.ArrayType: case *reflect.ArrayType:
// True arrays have size in the type. // True arrays have size in the type.
elemOp := encOpFor(t.Elem()); elemOp, indir := encOpFor(t.Elem());
_, indir := indirect(t.Elem());
op = func(i *encInstr, state *EncState, p unsafe.Pointer) { op = func(i *encInstr, state *EncState, p unsafe.Pointer) {
state.update(i); state.update(i);
state.err = encodeArray(state.w, uintptr(p), elemOp, t.Elem().Size(), t.Len(), indir); 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 { 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 // 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 engine.instr = make([]encInstr, srt.NumField()+1); // +1 for terminator
for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ { for fieldnum := 0; fieldnum < srt.NumField(); fieldnum++ {
f := srt.Field(fieldnum); f := srt.Field(fieldnum);
ftyp, indir := indirect(f.Type); op, indir := encOpFor(f.Type);
op := encOpFor(ftyp);
engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)}; engine.instr[fieldnum] = encInstr{op, fieldnum, indir, uintptr(f.Offset)};
} }
engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0}; engine.instr[srt.NumField()] = encInstr{encStructTerminator, 0, 0, 0};