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()")
|
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,
|
// 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 {
|
func (v Value) Len() int {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
|
case Array:
|
||||||
|
return v.Type().Len()
|
||||||
|
case Chan:
|
||||||
|
return chanlen(v.value)
|
||||||
|
case Map:
|
||||||
|
return maplen(v.value)
|
||||||
case Slice:
|
case Slice:
|
||||||
return int((*SliceHeader)(v.value).Len)
|
return int((*SliceHeader)(v.value).Len)
|
||||||
case String:
|
case String:
|
||||||
return int((*StringHeader)(v.value).Len)
|
return int((*StringHeader)(v.value).Len)
|
||||||
case Array:
|
default:
|
||||||
return v.Type().Len()
|
panic(&ValueError{"Len"})
|
||||||
default: // Chan, Map
|
|
||||||
panic("unimplemented: (reflect.Value).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 {
|
func (v Value) Cap() int {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
|
case Array:
|
||||||
|
return v.Type().Len()
|
||||||
|
case Chan:
|
||||||
|
return chancap(v.value)
|
||||||
case Slice:
|
case Slice:
|
||||||
return int((*SliceHeader)(v.value).Cap)
|
return int((*SliceHeader)(v.value).Cap)
|
||||||
default: // Array, Chan
|
default:
|
||||||
panic("unimplemented: (reflect.Value).Cap()")
|
panic(&ValueError{"Cap"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
// This is a hashmap implementation for the map[T]T type.
|
// 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
|
// 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.
|
// Return the number of entries in this hashmap, called from the len builtin.
|
||||||
// A nil hashmap is defined as having length 0.
|
// A nil hashmap is defined as having length 0.
|
||||||
|
//go:inline
|
||||||
func hashmapLen(m *hashmap) int {
|
func hashmapLen(m *hashmap) int {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -87,6 +88,12 @@ func hashmapLen(m *hashmap) int {
|
||||||
return int(m.count)
|
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.
|
// Set a specified key to a given value. Grow the map if necessary.
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
|
func hashmapSet(m *hashmap, key unsafe.Pointer, value unsafe.Pointer, hash uint32, keyEqual func(x, y unsafe.Pointer, n uintptr) bool) {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче