mirror of
https://github.com/golang/go
synced 2024-11-22 00:24:41 -07:00
reflect: allow Slice of arrays
R=r CC=golang-dev https://golang.org/cl/4444049
This commit is contained in:
parent
b331f3cfd0
commit
3bac16a6bf
@ -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:
|
||||
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);
|
||||
if(t->bound < 0)
|
||||
ot = duintptr(s, ot, -1);
|
||||
else
|
||||
ot = duintptr(s, ot, t->bound);
|
||||
}
|
||||
break;
|
||||
|
||||
case TCHAN:
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +260,7 @@ const (
|
||||
type arrayType struct {
|
||||
commonType "array"
|
||||
elem *runtime.Type
|
||||
slice *runtime.Type
|
||||
len uintptr
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
|
@ -118,6 +118,7 @@ type UnsafePointerType commonType
|
||||
type ArrayType struct {
|
||||
commonType
|
||||
elem *Type // array element type
|
||||
slice *Type // slice type
|
||||
len uintptr
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user