reflect: allow Slice of arrays

R=r
CC=golang-dev
https://golang.org/cl/4444049
This commit is contained in:
Russ Cox 2011-04-18 20:00:42 -04:00
parent b331f3cfd0
commit 3bac16a6bf
5 changed files with 55 additions and 17 deletions

View File

@ -690,7 +690,7 @@ dtypesym(Type *t)
int ot, xt, n, isddd, dupok;
Sym *s, *s1, *s2;
Sig *a, *m;
Type *t1, *tbase;
Type *t1, *tbase, *t2;
if(isideal(t))
fatal("dtypesym %T", t);
@ -727,15 +727,25 @@ ok:
break;
case TARRAY:
// ../../pkg/runtime/type.go:/ArrayType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
if(t->bound < 0)
ot = duintptr(s, ot, -1);
else
if(t->bound >= 0) {
// ../../pkg/runtime/type.go:/ArrayType
s1 = dtypesym(t->type);
t2 = typ(TARRAY);
t2->type = t->type;
t2->bound = -1; // slice
s2 = dtypesym(t2);
ot = dcommontype(s, ot, t);
xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
ot = dsymptr(s, ot, s2, 0);
ot = duintptr(s, ot, t->bound);
} else {
// ../../pkg/runtime/type.go:/SliceType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
}
break;
case TCHAN:

View File

@ -1435,3 +1435,17 @@ func TestSmallNegativeInt(t *testing.T) {
t.Errorf("int16(-1).Int() returned %v", v.Int())
}
}
func TestSlice(t *testing.T) {
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
v := NewValue(xs).Slice(3, 5).Interface().([]int)
if len(v) != 2 || v[0] != 4 || v[1] != 5 {
t.Errorf("xs.Slice(3, 5) = %v", v)
}
xa := [7]int{10, 20, 30, 40, 50, 60, 70}
v = NewValue(&xa).Elem().Slice(2, 5).Interface().([]int)
if len(v) != 3 || v[0] != 30 || v[1] != 40 || v[2] != 50 {
t.Errorf("xa.Slice(2, 5) = %v", v)
}
}

View File

@ -260,6 +260,7 @@ const (
type arrayType struct {
commonType "array"
elem *runtime.Type
slice *runtime.Type
len uintptr
}

View File

@ -1244,20 +1244,32 @@ func (v Value) SetString(x string) {
*(*string)(iv.addr) = x
}
// BUG(rsc): Value.Slice should allow slicing arrays.
// Slice returns a slice of v.
// It panics if v's Kind is not Slice.
// It panics if v's Kind is not Array or Slice.
func (v Value) Slice(beg, end int) Value {
iv := v.internal()
iv.mustBe(Slice)
if iv.kind != Array && iv.kind != Slice {
panic(&ValueError{"reflect.Value.Slice", iv.kind})
}
cap := v.Cap()
if beg < 0 || end < beg || end > cap {
panic("reflect.Value.Slice: slice index out of bounds")
}
typ := iv.typ.toType()
var typ Type
var base uintptr
switch iv.kind {
case Array:
if iv.flag&flagAddr == 0 {
panic("reflect.Value.Slice: slice of unaddressable array")
}
typ = toType((*arrayType)(unsafe.Pointer(iv.typ)).slice)
base = uintptr(iv.addr)
case Slice:
typ = iv.typ.toType()
base = (*SliceHeader)(iv.addr).Data
}
s := new(SliceHeader)
s.Data = uintptr((*SliceHeader)(iv.addr).Data) + uintptr(beg)*typ.Elem().Size()
s.Data = base + uintptr(beg)*typ.Elem().Size()
s.Len = end - beg
s.Cap = cap - beg
return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))

View File

@ -117,8 +117,9 @@ type UnsafePointerType commonType
// ArrayType represents a fixed array type.
type ArrayType struct {
commonType
elem *Type // array element type
len uintptr
elem *Type // array element type
slice *Type // slice type
len uintptr
}
// SliceType represents a slice type.