mirror of
https://github.com/golang/go
synced 2024-11-25 22:07:58 -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;
|
int ot, xt, n, isddd, dupok;
|
||||||
Sym *s, *s1, *s2;
|
Sym *s, *s1, *s2;
|
||||||
Sig *a, *m;
|
Sig *a, *m;
|
||||||
Type *t1, *tbase;
|
Type *t1, *tbase, *t2;
|
||||||
|
|
||||||
if(isideal(t))
|
if(isideal(t))
|
||||||
fatal("dtypesym %T", t);
|
fatal("dtypesym %T", t);
|
||||||
@ -727,15 +727,25 @@ ok:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
|
if(t->bound >= 0) {
|
||||||
// ../../pkg/runtime/type.go:/ArrayType
|
// ../../pkg/runtime/type.go:/ArrayType
|
||||||
s1 = dtypesym(t->type);
|
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);
|
ot = dcommontype(s, ot, t);
|
||||||
xt = ot - 2*widthptr;
|
xt = ot - 2*widthptr;
|
||||||
ot = dsymptr(s, ot, s1, 0);
|
ot = dsymptr(s, ot, s1, 0);
|
||||||
if(t->bound < 0)
|
}
|
||||||
ot = duintptr(s, ot, -1);
|
|
||||||
else
|
|
||||||
ot = duintptr(s, ot, t->bound);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
|
@ -1435,3 +1435,17 @@ func TestSmallNegativeInt(t *testing.T) {
|
|||||||
t.Errorf("int16(-1).Int() returned %v", v.Int())
|
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 {
|
type arrayType struct {
|
||||||
commonType "array"
|
commonType "array"
|
||||||
elem *runtime.Type
|
elem *runtime.Type
|
||||||
|
slice *runtime.Type
|
||||||
len uintptr
|
len uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,20 +1244,32 @@ func (v Value) SetString(x string) {
|
|||||||
*(*string)(iv.addr) = x
|
*(*string)(iv.addr) = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG(rsc): Value.Slice should allow slicing arrays.
|
|
||||||
|
|
||||||
// Slice returns a slice of v.
|
// 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 {
|
func (v Value) Slice(beg, end int) Value {
|
||||||
iv := v.internal()
|
iv := v.internal()
|
||||||
iv.mustBe(Slice)
|
if iv.kind != Array && iv.kind != Slice {
|
||||||
|
panic(&ValueError{"reflect.Value.Slice", iv.kind})
|
||||||
|
}
|
||||||
cap := v.Cap()
|
cap := v.Cap()
|
||||||
if beg < 0 || end < beg || end > cap {
|
if beg < 0 || end < beg || end > cap {
|
||||||
panic("reflect.Value.Slice: slice index out of bounds")
|
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 := 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.Len = end - beg
|
||||||
s.Cap = cap - beg
|
s.Cap = cap - beg
|
||||||
return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
|
return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
|
||||||
|
@ -118,6 +118,7 @@ type UnsafePointerType commonType
|
|||||||
type ArrayType struct {
|
type ArrayType struct {
|
||||||
commonType
|
commonType
|
||||||
elem *Type // array element type
|
elem *Type // array element type
|
||||||
|
slice *Type // slice type
|
||||||
len uintptr
|
len uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user