summaryrefslogtreecommitdiff
path: root/src/pkg/reflect/value.go
diff options
context:
space:
mode:
authorEvan Shaw <chickencha@gmail.com>2012-10-21 17:02:10 -0400
committerEvan Shaw <chickencha@gmail.com>2012-10-21 17:02:10 -0400
commitccc1240045690316c51953de2130cdf6cc71211f (patch)
treed08defbe3f4d6428cb6fe1c5242941cee8592e2b /src/pkg/reflect/value.go
parent84f1122a2523f4be41e40378eb6ec2406a1b48d5 (diff)
downloadgo-ccc1240045690316c51953de2130cdf6cc71211f.tar.gz
reflect: make Index and Slice accept strings
Fixes issue 3284. R=golang-dev, r, rsc CC=golang-dev http://codereview.appspot.com/6643043 Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/pkg/reflect/value.go')
-rw-r--r--src/pkg/reflect/value.go28
1 files changed, 26 insertions, 2 deletions
diff --git a/src/pkg/reflect/value.go b/src/pkg/reflect/value.go
index 74addd195..be5d03504 100644
--- a/src/pkg/reflect/value.go
+++ b/src/pkg/reflect/value.go
@@ -810,8 +810,10 @@ func (v Value) Float() float64 {
panic(&ValueError{"reflect.Value.Float", k})
}
+var uint8Type = TypeOf(uint8(0)).(*commonType)
+
// 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 {
k := v.kind()
switch k {
@@ -852,6 +854,15 @@ func (v Value) Index(i int) Value {
fl |= flag(typ.Kind()) << flagKindShift
val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
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})
}
@@ -1437,7 +1448,7 @@ func (v Value) SetString(x string) {
}
// 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 {
var (
cap int
@@ -1447,6 +1458,7 @@ func (v Value) Slice(beg, end int) Value {
switch k := v.kind(); k {
default:
panic(&ValueError{"reflect.Value.Slice", k})
+
case Array:
if v.flag&flagAddr == 0 {
panic("reflect.Value.Slice: slice of unaddressable array")
@@ -1455,13 +1467,25 @@ func (v Value) Slice(beg, end int) Value {
cap = int(tt.len)
typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
base = v.val
+
case Slice:
typ = (*sliceType)(unsafe.Pointer(v.typ))
s := (*SliceHeader)(v.val)
base = unsafe.Pointer(s.Data)
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 {
panic("reflect.Value.Slice: slice index out of bounds")
}