reflect: add support for remaining map types
Этот коммит содержится в:
родитель
a6084767b3
коммит
69e5c5088d
3 изменённых файлов: 56 добавлений и 5 удалений
|
@ -785,6 +785,9 @@ func hashmapStringGet(m unsafe.Pointer, key string, value unsafe.Pointer, valueS
|
||||||
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGetUnsafePointer
|
//go:linkname hashmapBinaryGet runtime.hashmapBinaryGetUnsafePointer
|
||||||
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
func hashmapBinaryGet(m unsafe.Pointer, key, value unsafe.Pointer, valueSize uintptr) bool
|
||||||
|
|
||||||
|
//go:linkname hashmapInterfaceGet runtime.hashmapInterfaceGetUnsafePointer
|
||||||
|
func hashmapInterfaceGet(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool
|
||||||
|
|
||||||
func (v Value) MapIndex(key Value) Value {
|
func (v Value) MapIndex(key Value) Value {
|
||||||
if v.Kind() != Map {
|
if v.Kind() != Map {
|
||||||
panic(&ValueError{Method: "MapIndex", Kind: v.Kind()})
|
panic(&ValueError{Method: "MapIndex", Kind: v.Kind()})
|
||||||
|
@ -816,10 +819,12 @@ func (v Value) MapIndex(key Value) Value {
|
||||||
return Value{}
|
return Value{}
|
||||||
}
|
}
|
||||||
return elem.Elem()
|
return elem.Elem()
|
||||||
|
} else {
|
||||||
|
if ok := hashmapInterfaceGet(v.pointer(), key.Interface(), elem.value, elemType.Size()); !ok {
|
||||||
|
return Value{}
|
||||||
|
}
|
||||||
|
return elem.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dgryski): Add other map types. For now, just string and binary types are supported.
|
|
||||||
panic("unimplemented: (reflect.Value).MapIndex()")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname hashmapNewIterator runtime.hashmapNewIterator
|
//go:linkname hashmapNewIterator runtime.hashmapNewIterator
|
||||||
|
@ -1292,12 +1297,18 @@ func hashmapStringSet(m unsafe.Pointer, key string, value unsafe.Pointer)
|
||||||
//go:linkname hashmapBinarySet runtime.hashmapBinarySetUnsafePointer
|
//go:linkname hashmapBinarySet runtime.hashmapBinarySetUnsafePointer
|
||||||
func hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)
|
func hashmapBinarySet(m unsafe.Pointer, key, value unsafe.Pointer)
|
||||||
|
|
||||||
|
//go:linkname hashmapInterfaceSet runtime.hashmapInterfaceSetUnsafePointer
|
||||||
|
func hashmapInterfaceSet(m unsafe.Pointer, key interface{}, value unsafe.Pointer)
|
||||||
|
|
||||||
//go:linkname hashmapStringDelete runtime.hashmapStringDeleteUnsafePointer
|
//go:linkname hashmapStringDelete runtime.hashmapStringDeleteUnsafePointer
|
||||||
func hashmapStringDelete(m unsafe.Pointer, key string)
|
func hashmapStringDelete(m unsafe.Pointer, key string)
|
||||||
|
|
||||||
//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDeleteUnsafePointer
|
//go:linkname hashmapBinaryDelete runtime.hashmapBinaryDeleteUnsafePointer
|
||||||
func hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)
|
func hashmapBinaryDelete(m unsafe.Pointer, key unsafe.Pointer)
|
||||||
|
|
||||||
|
//go:linkname hashmapInterfaceDelete runtime.hashmapInterfaceDeleteUnsafePointer
|
||||||
|
func hashmapInterfaceDelete(m unsafe.Pointer, key interface{})
|
||||||
|
|
||||||
func (v Value) SetMapIndex(key, elem Value) {
|
func (v Value) SetMapIndex(key, elem Value) {
|
||||||
if v.Kind() != Map {
|
if v.Kind() != Map {
|
||||||
panic(&ValueError{Method: "SetMapIndex", Kind: v.Kind()})
|
panic(&ValueError{Method: "SetMapIndex", Kind: v.Kind()})
|
||||||
|
@ -1348,7 +1359,18 @@ func (v Value) SetMapIndex(key, elem Value) {
|
||||||
hashmapBinarySet(v.pointer(), keyptr, elemptr)
|
hashmapBinarySet(v.pointer(), keyptr, elemptr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic("unimplemented: (reflect.Value).MapIndex()")
|
if del {
|
||||||
|
hashmapInterfaceDelete(v.pointer(), key.Interface())
|
||||||
|
} else {
|
||||||
|
var elemptr unsafe.Pointer
|
||||||
|
if elem.isIndirect() || elem.typecode.Size() > unsafe.Sizeof(uintptr(0)) {
|
||||||
|
elemptr = elem.value
|
||||||
|
} else {
|
||||||
|
elemptr = unsafe.Pointer(&elem.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashmapInterfaceSet(v.pointer(), key.Interface(), elemptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,7 +1420,7 @@ func MakeMapWithSize(typ Type, n int) Value {
|
||||||
} else if key.isBinary() {
|
} else if key.isBinary() {
|
||||||
alg = hashmapAlgorithmBinary
|
alg = hashmapAlgorithmBinary
|
||||||
} else {
|
} else {
|
||||||
panic("reflect.MakeMap: unimplemented key type")
|
alg = hashmapAlgorithmInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
m := hashmapMake(key.Size(), val.Size(), uintptr(n), alg)
|
m := hashmapMake(key.Size(), val.Size(), uintptr(n), alg)
|
||||||
|
|
|
@ -115,6 +115,23 @@ func TestMap(t *testing.T) {
|
||||||
if m2["foo"] != 2 {
|
if m2["foo"] != 2 {
|
||||||
t.Errorf("MakeMap failed to create map")
|
t.Errorf("MakeMap failed to create map")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stringint struct {
|
||||||
|
s string
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
simap := make(map[stringint]int)
|
||||||
|
|
||||||
|
refsimap := MakeMap(TypeOf(simap))
|
||||||
|
|
||||||
|
refsimap.SetMapIndex(ValueOf(stringint{"hello", 4}), ValueOf(6))
|
||||||
|
|
||||||
|
six := refsimap.MapIndex(ValueOf(stringint{"hello", 4}))
|
||||||
|
|
||||||
|
if six.Interface().(int) != 6 {
|
||||||
|
t.Errorf("m[hello, 4]=%v, want 6", six)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlice(t *testing.T) {
|
func TestSlice(t *testing.T) {
|
||||||
|
|
|
@ -616,6 +616,10 @@ func hashmapInterfaceSet(m *hashmap, key interface{}, value unsafe.Pointer) {
|
||||||
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
hashmapSet(m, unsafe.Pointer(&key), value, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceSetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer) {
|
||||||
|
hashmapInterfaceSet((*hashmap)(m), key, value)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
memzero(value, uintptr(valueSize))
|
memzero(value, uintptr(valueSize))
|
||||||
|
@ -625,6 +629,10 @@ func hashmapInterfaceGet(m *hashmap, key interface{}, value unsafe.Pointer, valu
|
||||||
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
return hashmapGet(m, unsafe.Pointer(&key), value, valueSize, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceGetUnsafePointer(m unsafe.Pointer, key interface{}, value unsafe.Pointer, valueSize uintptr) bool {
|
||||||
|
return hashmapInterfaceGet((*hashmap)(m), key, value, valueSize)
|
||||||
|
}
|
||||||
|
|
||||||
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return
|
return
|
||||||
|
@ -632,3 +640,7 @@ func hashmapInterfaceDelete(m *hashmap, key interface{}) {
|
||||||
hash := hashmapInterfaceHash(key, m.seed)
|
hash := hashmapInterfaceHash(key, m.seed)
|
||||||
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
hashmapDelete(m, unsafe.Pointer(&key), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashmapInterfaceDeleteUnsafePointer(m unsafe.Pointer, key interface{}) {
|
||||||
|
hashmapInterfaceDelete((*hashmap)(m), key)
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче