reflect: add Cap and Len support for map and chan
Этот коммит содержится в:
родитель
7e64bc8f77
коммит
2c71f08922
2 изменённых файлов: 34 добавлений и 8 удалений
|
@ -304,29 +304,48 @@ func (v Value) Slice(i, j int) Value {
|
|||
panic("unimplemented: (reflect.Value).Slice()")
|
||||
}
|
||||
|
||||
//go:linkname maplen runtime.hashmapLenUnsafePointer
|
||||
func maplen(p unsafe.Pointer) int
|
||||
|
||||
//go:linkname chanlen runtime.chanLenUnsafePointer
|
||||
func chanlen(p unsafe.Pointer) int
|
||||
|
||||
// Len returns the length of this value for slices, strings, arrays, channels,
|
||||
// and maps. For oter types, it panics.
|
||||
// and maps. For other types, it panics.
|
||||
func (v Value) Len() int {
|
||||
t := v.Type()
|
||||
switch t.Kind() {
|
||||
case Array:
|
||||
return v.Type().Len()
|
||||
case Chan:
|
||||
return chanlen(v.value)
|
||||
case Map:
|
||||
return maplen(v.value)
|
||||
case Slice:
|
||||
return int((*SliceHeader)(v.value).Len)
|
||||
case String:
|
||||
return int((*StringHeader)(v.value).Len)
|
||||
case Array:
|
||||
return v.Type().Len()
|
||||
default: // Chan, Map
|
||||
panic("unimplemented: (reflect.Value).Len()")
|
||||
default:
|
||||
panic(&ValueError{"Len"})
|
||||
}
|
||||
}
|
||||
|
||||
//go:linkname chancap runtime.chanCapUnsafePointer
|
||||
func chancap(p unsafe.Pointer) int
|
||||
|
||||
// Cap returns the capacity of this value for arrays, channels and slices.
|
||||
// For other types, it panics.
|
||||
func (v Value) Cap() int {
|
||||
t := v.Type()
|
||||
switch t.Kind() {
|
||||
case Array:
|
||||
return v.Type().Len()
|
||||
case Chan:
|
||||
return chancap(v.value)
|
||||
case Slice:
|
||||
return int((*SliceHeader)(v.value).Cap)
|
||||
default: // Array, Chan
|
||||
panic("unimplemented: (reflect.Value).Cap()")
|
||||
default:
|
||||
panic(&ValueError{"Cap"})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package runtime
|
||||
|
||||
// This is a hashmap implementation for the map[T]T type.
|
||||
// It is very rougly based on the implementation of the Go hashmap:
|
||||
// It is very roughly based on the implementation of the Go hashmap:
|
||||
//
|
||||
// https://golang.org/src/runtime/map.go
|
||||
|
||||
|
@ -80,6 +80,7 @@ func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
|
|||
|
||||
// Return the number of entries in this hashmap, called from the len builtin.
|
||||
// A nil hashmap is defined as having length 0.
|
||||
//go:inline
|
||||
func hashmapLen(m *hashmap) int {
|
||||
if m == nil {
|
||||
return 0
|
||||
|
@ -87,6 +88,12 @@ func hashmapLen(m *hashmap) int {
|
|||
return int(m.count)
|
||||
}
|
||||
|
||||
// wrapper for use in reflect
|
||||
func hashmapLenUnsafePointer(p unsafe.Pointer) int {
|
||||
m := (*hashmap)(p)
|
||||
return hashmapLen(m)
|
||||
}
|
||||
|
||||
// Set a specified key to a given value. Grow the map if necessary.
|
||||
//go:nobounds
|
||||
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче