mirror of
https://github.com/golang/go
synced 2024-11-20 06:14:53 -07:00
reflect: make Index and Slice accept strings
Fixes #3284. R=golang-dev, r, rsc CC=golang-dev https://golang.org/cl/6643043
This commit is contained in:
parent
d7a3407e3d
commit
772decbc80
@ -2036,6 +2036,24 @@ func TestSmallNegativeInt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIndex(t *testing.T) {
|
||||||
|
xs := []byte{1, 2, 3, 4, 5, 6, 7, 8}
|
||||||
|
v := ValueOf(xs).Index(3).Interface().(byte)
|
||||||
|
if v != xs[3] {
|
||||||
|
t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3])
|
||||||
|
}
|
||||||
|
xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}
|
||||||
|
v = ValueOf(xa).Index(2).Interface().(byte)
|
||||||
|
if v != xa[2] {
|
||||||
|
t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2])
|
||||||
|
}
|
||||||
|
s := "0123456789"
|
||||||
|
v = ValueOf(s).Index(3).Interface().(byte)
|
||||||
|
if v != s[3] {
|
||||||
|
t.Errorf("s.Index(3) = %v; expected %v", v, s[3])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSlice(t *testing.T) {
|
func TestSlice(t *testing.T) {
|
||||||
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
||||||
v := ValueOf(xs).Slice(3, 5).Interface().([]int)
|
v := ValueOf(xs).Slice(3, 5).Interface().([]int)
|
||||||
@ -2048,7 +2066,6 @@ func TestSlice(t *testing.T) {
|
|||||||
if !DeepEqual(v[0:5], xs[3:]) {
|
if !DeepEqual(v[0:5], xs[3:]) {
|
||||||
t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
|
t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
|
||||||
}
|
}
|
||||||
|
|
||||||
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
||||||
v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
|
v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
|
||||||
if len(v) != 3 {
|
if len(v) != 3 {
|
||||||
@ -2060,6 +2077,11 @@ func TestSlice(t *testing.T) {
|
|||||||
if !DeepEqual(v[0:6], xa[2:]) {
|
if !DeepEqual(v[0:6], xa[2:]) {
|
||||||
t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
|
t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
|
||||||
}
|
}
|
||||||
|
s := "0123456789"
|
||||||
|
vs := ValueOf(s).Slice(3, 5).Interface().(string)
|
||||||
|
if vs != s[3:5] {
|
||||||
|
t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVariadic(t *testing.T) {
|
func TestVariadic(t *testing.T) {
|
||||||
|
@ -810,8 +810,10 @@ func (v Value) Float() float64 {
|
|||||||
panic(&ValueError{"reflect.Value.Float", k})
|
panic(&ValueError{"reflect.Value.Float", k})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uint8Type = TypeOf(uint8(0)).(*commonType)
|
||||||
|
|
||||||
// Index returns v's i'th element.
|
// Index returns v's i'th element.
|
||||||
// It panics if v's Kind is not Array or Slice or i is out of range.
|
// It panics if v's Kind is not Array, Slice, or String or i is out of range.
|
||||||
func (v Value) Index(i int) Value {
|
func (v Value) Index(i int) Value {
|
||||||
k := v.kind()
|
k := v.kind()
|
||||||
switch k {
|
switch k {
|
||||||
@ -852,6 +854,15 @@ func (v Value) Index(i int) Value {
|
|||||||
fl |= flag(typ.Kind()) << flagKindShift
|
fl |= flag(typ.Kind()) << flagKindShift
|
||||||
val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
|
val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
|
||||||
return Value{typ, val, fl}
|
return Value{typ, val, fl}
|
||||||
|
|
||||||
|
case String:
|
||||||
|
fl := v.flag&flagRO | flag(Uint8<<flagKindShift)
|
||||||
|
s := (*StringHeader)(v.val)
|
||||||
|
if i < 0 || i >= s.Len {
|
||||||
|
panic("reflect: string index out of range")
|
||||||
|
}
|
||||||
|
val := *(*byte)(unsafe.Pointer(s.Data + uintptr(i)))
|
||||||
|
return Value{uint8Type, unsafe.Pointer(uintptr(val)), fl}
|
||||||
}
|
}
|
||||||
panic(&ValueError{"reflect.Value.Index", k})
|
panic(&ValueError{"reflect.Value.Index", k})
|
||||||
}
|
}
|
||||||
@ -1437,7 +1448,7 @@ func (v Value) SetString(x string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slice returns a slice of v.
|
// Slice returns a slice of v.
|
||||||
// It panics if v's Kind is not Array or Slice.
|
// It panics if v's Kind is not Array, Slice, or String.
|
||||||
func (v Value) Slice(beg, end int) Value {
|
func (v Value) Slice(beg, end int) Value {
|
||||||
var (
|
var (
|
||||||
cap int
|
cap int
|
||||||
@ -1447,6 +1458,7 @@ func (v Value) Slice(beg, end int) Value {
|
|||||||
switch k := v.kind(); k {
|
switch k := v.kind(); k {
|
||||||
default:
|
default:
|
||||||
panic(&ValueError{"reflect.Value.Slice", k})
|
panic(&ValueError{"reflect.Value.Slice", k})
|
||||||
|
|
||||||
case Array:
|
case Array:
|
||||||
if v.flag&flagAddr == 0 {
|
if v.flag&flagAddr == 0 {
|
||||||
panic("reflect.Value.Slice: slice of unaddressable array")
|
panic("reflect.Value.Slice: slice of unaddressable array")
|
||||||
@ -1455,13 +1467,25 @@ func (v Value) Slice(beg, end int) Value {
|
|||||||
cap = int(tt.len)
|
cap = int(tt.len)
|
||||||
typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
|
typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
|
||||||
base = v.val
|
base = v.val
|
||||||
|
|
||||||
case Slice:
|
case Slice:
|
||||||
typ = (*sliceType)(unsafe.Pointer(v.typ))
|
typ = (*sliceType)(unsafe.Pointer(v.typ))
|
||||||
s := (*SliceHeader)(v.val)
|
s := (*SliceHeader)(v.val)
|
||||||
base = unsafe.Pointer(s.Data)
|
base = unsafe.Pointer(s.Data)
|
||||||
cap = s.Cap
|
cap = s.Cap
|
||||||
|
|
||||||
|
case String:
|
||||||
|
s := (*StringHeader)(v.val)
|
||||||
|
if beg < 0 || end < beg || end > s.Len {
|
||||||
|
panic("reflect.Value.Slice: string slice index out of bounds")
|
||||||
|
}
|
||||||
|
var x string
|
||||||
|
val := (*StringHeader)(unsafe.Pointer(&x))
|
||||||
|
val.Data = s.Data + uintptr(beg)
|
||||||
|
val.Len = end - beg
|
||||||
|
return Value{v.typ, unsafe.Pointer(&x), v.flag}
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user