mirror of
https://github.com/golang/go
synced 2024-11-25 22:17:58 -07:00
indirection on array elements.
R=rsc DELTA=57 (34 added, 10 deleted, 13 changed) OCL=31098 CL=31101
This commit is contained in:
parent
b5666a123a
commit
c1fc4c8f37
@ -529,9 +529,12 @@ func TestEncode(t *testing.T) {
|
|||||||
type T2 struct {
|
type T2 struct {
|
||||||
t string
|
t string
|
||||||
}
|
}
|
||||||
|
s1 := "string1";
|
||||||
|
s2 := "string2";
|
||||||
type T1 struct {
|
type T1 struct {
|
||||||
a, b,c int;
|
a, b,c int;
|
||||||
n *[3]float;
|
n *[3]float;
|
||||||
|
strs *[2]string;
|
||||||
s string;
|
s string;
|
||||||
y []byte;
|
y []byte;
|
||||||
t *T2;
|
t *T2;
|
||||||
@ -541,6 +544,7 @@ func TestEncode(t *testing.T) {
|
|||||||
b: 18,
|
b: 18,
|
||||||
c: -5,
|
c: -5,
|
||||||
n: &[3]float{1.5, 2.5, 3.5},
|
n: &[3]float{1.5, 2.5, 3.5},
|
||||||
|
strs: &[2]string{s1, s2},
|
||||||
s: "Now is the time",
|
s: "Now is the time",
|
||||||
y: strings.Bytes("hello, sailor"),
|
y: strings.Bytes("hello, sailor"),
|
||||||
t: &T2{"this is T2"},
|
t: &T2{"this is T2"},
|
||||||
|
@ -313,7 +313,7 @@ func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uin
|
|||||||
return state.err
|
return state.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid int, length int, indir int) os.Error {
|
func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decOp, elemWid int, length int, indir, elemIndir int) os.Error {
|
||||||
if indir > 0 {
|
if indir > 0 {
|
||||||
up := unsafe.Pointer(p);
|
up := unsafe.Pointer(p);
|
||||||
if *(*unsafe.Pointer)(up) == nil {
|
if *(*unsafe.Pointer)(up) == nil {
|
||||||
@ -324,12 +324,16 @@ func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
|
|||||||
}
|
}
|
||||||
p = *(*uintptr)(up);
|
p = *(*uintptr)(up);
|
||||||
}
|
}
|
||||||
instr := &decInstr{elemOp, 0, 0, 0}; // TODO(r): indir on elements
|
instr := &decInstr{elemOp, 0, elemIndir, 0};
|
||||||
if DecodeUint(state) != uint64(length) {
|
if DecodeUint(state) != uint64(length) {
|
||||||
state.err = os.ErrorString("length mismatch in decodeArray");
|
state.err = os.ErrorString("length mismatch in decodeArray");
|
||||||
}
|
}
|
||||||
for i := 0; i < length && state.err == nil; i++ {
|
for i := 0; i < length && state.err == nil; i++ {
|
||||||
elemOp(instr, state, unsafe.Pointer(p));
|
up := unsafe.Pointer(p);
|
||||||
|
if elemIndir > 1 {
|
||||||
|
up = decIndirect(up, elemIndir);
|
||||||
|
}
|
||||||
|
elemOp(instr, state, up);
|
||||||
p += uintptr(elemWid);
|
p += uintptr(elemWid);
|
||||||
}
|
}
|
||||||
return state.err
|
return state.err
|
||||||
@ -368,8 +372,9 @@ func decOpFor(typ reflect.Type) decOp {
|
|||||||
case atyp.IsSlice():
|
case atyp.IsSlice():
|
||||||
case !atyp.IsSlice():
|
case !atyp.IsSlice():
|
||||||
elemOp := decOpFor(atyp.Elem());
|
elemOp := decOpFor(atyp.Elem());
|
||||||
|
_, elemIndir := indirect(atyp.Elem());
|
||||||
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
|
op = func(i *decInstr, state *DecState, p unsafe.Pointer) {
|
||||||
state.err = decodeArray(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), i.indir);
|
state.err = decodeArray(atyp, state, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), i.indir, elemIndir);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,14 +434,9 @@ func getDecEngine(rt reflect.Type) *decEngine {
|
|||||||
|
|
||||||
func Decode(r io.Reader, e interface{}) os.Error {
|
func Decode(r io.Reader, e interface{}) os.Error {
|
||||||
// Dereference down to the underlying object.
|
// Dereference down to the underlying object.
|
||||||
rt := reflect.Typeof(e);
|
rt, indir := indirect(reflect.Typeof(e));
|
||||||
v := reflect.NewValue(e);
|
v := reflect.NewValue(e);
|
||||||
for {
|
for i := 0; i < indir; i++ {
|
||||||
pt, ok := rt.(reflect.PtrType);
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
rt = pt.Sub();
|
|
||||||
v = reflect.Indirect(v);
|
v = reflect.Indirect(v);
|
||||||
}
|
}
|
||||||
if rt.Kind() != reflect.StructKind {
|
if rt.Kind() != reflect.StructKind {
|
||||||
|
@ -14,6 +14,21 @@ import (
|
|||||||
"unsafe";
|
"unsafe";
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Step through the indirections on a type to discover the base type.
|
||||||
|
// Return the number of indirections.
|
||||||
|
func indirect(t reflect.Type) (rt reflect.Type, count int) {
|
||||||
|
rt = t;
|
||||||
|
for {
|
||||||
|
pt, ok := rt.(reflect.PtrType);
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
rt = pt.Sub();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The global execution state of an instance of the encoder.
|
// The global execution state of an instance of the encoder.
|
||||||
// Field numbers are delta encoded and always increase. The field
|
// Field numbers are delta encoded and always increase. The field
|
||||||
// number is initialized to -1 so 0 comes out as delta(1). A delta of
|
// number is initialized to -1 so 0 comes out as delta(1). A delta of
|
||||||
@ -280,13 +295,21 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error {
|
|||||||
return state.err
|
return state.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int) os.Error {
|
func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elemIndir int) os.Error {
|
||||||
state := new(EncState);
|
state := new(EncState);
|
||||||
state.w = w;
|
state.w = w;
|
||||||
state.fieldnum = -1;
|
state.fieldnum = -1;
|
||||||
EncodeUint(state, uint64(length));
|
EncodeUint(state, uint64(length));
|
||||||
for i := 0; i < length && state.err == nil; i++ {
|
for i := 0; i < length && state.err == nil; i++ {
|
||||||
op(nil, state, unsafe.Pointer(p)); // TODO(r): indir on elements
|
up := unsafe.Pointer(p);
|
||||||
|
if elemIndir > 0 {
|
||||||
|
if up = encIndirect(up, elemIndir); up == nil {
|
||||||
|
state.err = os.ErrorString("encodeArray: nil element");
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p = uintptr(up);
|
||||||
|
}
|
||||||
|
op(nil, state, unsafe.Pointer(p));
|
||||||
p += uintptr(elemWid);
|
p += uintptr(elemWid);
|
||||||
}
|
}
|
||||||
return state.err
|
return state.err
|
||||||
@ -325,20 +348,22 @@ func encOpFor(typ reflect.Type) encOp {
|
|||||||
case atyp.IsSlice():
|
case atyp.IsSlice():
|
||||||
// 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(atyp.Elem());
|
elemOp := encOpFor(atyp.Elem());
|
||||||
|
_, indir := indirect(atyp.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 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state.update(i);
|
state.update(i);
|
||||||
state.err = encodeArray(state.w, slice.Data, elemOp, atyp.Elem().Size(), int(slice.Len));
|
state.err = encodeArray(state.w, slice.Data, elemOp, atyp.Elem().Size(), int(slice.Len), indir);
|
||||||
};
|
};
|
||||||
case !atyp.IsSlice():
|
case !atyp.IsSlice():
|
||||||
// True arrays have size in the type.
|
// True arrays have size in the type.
|
||||||
elemOp := encOpFor(atyp.Elem());
|
elemOp := encOpFor(atyp.Elem());
|
||||||
|
_, indir := indirect(atyp.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, atyp.Elem().Size(), atyp.Len());
|
state.err = encodeArray(state.w, uintptr(p), elemOp, atyp.Elem().Size(), atyp.Len(), indir);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,18 +423,13 @@ func getEncEngine(rt reflect.Type) *encEngine {
|
|||||||
|
|
||||||
func Encode(w io.Writer, e interface{}) os.Error {
|
func Encode(w io.Writer, e interface{}) os.Error {
|
||||||
// Dereference down to the underlying object.
|
// Dereference down to the underlying object.
|
||||||
rt := reflect.Typeof(e);
|
rt, indir := indirect(reflect.Typeof(e));
|
||||||
v := reflect.NewValue(e);
|
v := reflect.NewValue(e);
|
||||||
for {
|
for i := 0; i < indir; i++ {
|
||||||
pt, ok := rt.(reflect.PtrType);
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
rt = pt.Sub();
|
|
||||||
v = reflect.Indirect(v);
|
v = reflect.Indirect(v);
|
||||||
}
|
}
|
||||||
if v.Kind() != reflect.StructKind {
|
if v.Kind() != reflect.StructKind {
|
||||||
return os.ErrorString("decode can't handle " + v.Type().String())
|
return os.ErrorString("encode can't handle " + v.Type().String())
|
||||||
}
|
}
|
||||||
typeLock.Lock();
|
typeLock.Lock();
|
||||||
engine := getEncEngine(rt);
|
engine := getEncEngine(rt);
|
||||||
|
Loading…
Reference in New Issue
Block a user