builtin: add `map.values()` (#14301)
parent
ce99a306c0
commit
0699f324b5
|
@ -86,8 +86,8 @@ mut:
|
|||
// array allocated (with `cap` bytes) on first deletion
|
||||
// has non-zero element when key deleted
|
||||
all_deleted &u8
|
||||
values &u8
|
||||
keys &u8
|
||||
values &u8
|
||||
}
|
||||
|
||||
[inline]
|
||||
|
@ -126,8 +126,8 @@ fn (d &DenseArray) has_index(i int) bool {
|
|||
[inline]
|
||||
fn (mut d DenseArray) expand() int {
|
||||
old_cap := d.cap
|
||||
old_value_size := d.value_bytes * old_cap
|
||||
old_key_size := d.key_bytes * old_cap
|
||||
old_value_size := d.value_bytes * old_cap
|
||||
if d.cap == d.len {
|
||||
d.cap += d.cap >> 3
|
||||
unsafe {
|
||||
|
@ -628,6 +628,31 @@ pub fn (m &map) keys() array {
|
|||
return keys
|
||||
}
|
||||
|
||||
// Returns all values in the map.
|
||||
pub fn (m &map) values() array {
|
||||
mut values := __new_array(m.len, 0, m.value_bytes)
|
||||
mut item := unsafe { &u8(values.data) }
|
||||
|
||||
if m.key_values.deletes == 0 {
|
||||
unsafe {
|
||||
vmemcpy(item, m.key_values.values, m.value_bytes * m.key_values.len)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
for i := 0; i < m.key_values.len; i++ {
|
||||
if !m.key_values.has_index(i) {
|
||||
continue
|
||||
}
|
||||
unsafe {
|
||||
pvalue := m.key_values.value(i)
|
||||
vmemcpy(item, pvalue, m.value_bytes)
|
||||
item = item + m.value_bytes
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// warning: only copies keys, does not clone
|
||||
[unsafe]
|
||||
fn (d &DenseArray) clone() DenseArray {
|
||||
|
|
|
@ -47,6 +47,16 @@ fn test_keys_many() {
|
|||
assert keys == strings
|
||||
}
|
||||
|
||||
fn test_values_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in strings {
|
||||
m[s] = i
|
||||
}
|
||||
values := m.values()
|
||||
assert values.len == strings.len
|
||||
assert values.len == m.len
|
||||
}
|
||||
|
||||
fn test_deletes_many() {
|
||||
mut m := map[string]int{}
|
||||
for i, s in strings {
|
||||
|
@ -59,6 +69,7 @@ fn test_deletes_many() {
|
|||
}
|
||||
assert m.len == 0
|
||||
assert m.keys().len == 0
|
||||
assert m.values().len == 0
|
||||
}
|
||||
|
||||
struct User {
|
||||
|
@ -103,6 +114,13 @@ fn test_map() {
|
|||
assert m['hi'] == 0
|
||||
assert m.keys().len == 1
|
||||
assert m.keys()[0] == 'hello'
|
||||
// Test `.values()`
|
||||
values := m.values()
|
||||
assert values.len == 1
|
||||
assert 80 !in values
|
||||
assert 101 in values
|
||||
assert m.values().len == 1
|
||||
assert m.values()[0] == 101
|
||||
// //
|
||||
mut users := map[string]User{}
|
||||
users['1'] = User{'Peter'}
|
||||
|
@ -580,6 +598,7 @@ fn test_int_keys() {
|
|||
4: 16
|
||||
5: 25
|
||||
}
|
||||
assert m2.values() == [9, 16, 25]
|
||||
|
||||
assert m2.len == 3
|
||||
// clone
|
||||
|
@ -636,6 +655,16 @@ fn test_voidptr_keys() {
|
|||
assert m.len == 2
|
||||
}
|
||||
|
||||
fn test_voidptr_values() {
|
||||
mut m := map[string]voidptr{}
|
||||
v := 5
|
||||
m['var'] = &v
|
||||
m['map'] = &m
|
||||
assert m['var'] == &v
|
||||
assert m['map'] == &m
|
||||
assert m.values().len == 2
|
||||
}
|
||||
|
||||
fn test_rune_keys() {
|
||||
mut m := {
|
||||
`!`: 2
|
||||
|
|
|
@ -1111,7 +1111,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||
if left_sym.kind == .array && method_name in array_builtin_methods {
|
||||
return c.array_builtin_method_call(mut node, left_type, c.table.sym(left_type))
|
||||
} else if (left_sym.kind == .map || final_left_sym.kind == .map)
|
||||
&& method_name in ['clone', 'keys', 'move', 'delete'] {
|
||||
&& method_name in ['clone', 'keys', 'values', 'move', 'delete'] {
|
||||
if left_sym.kind == .map {
|
||||
return c.map_builtin_method_call(mut node, left_type, left_sym)
|
||||
} else {
|
||||
|
@ -1820,12 +1820,16 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
|
|||
}
|
||||
ret_type = ret_type.clear_flag(.shared_f)
|
||||
}
|
||||
'keys' {
|
||||
'keys', 'values' {
|
||||
if node.args.len != 0 {
|
||||
c.error('`.keys()` does not have any arguments', node.args[0].pos)
|
||||
c.error('`.${method_name}()` does not have any arguments', node.args[0].pos)
|
||||
}
|
||||
info := left_sym.info as ast.Map
|
||||
typ := c.table.find_or_register_array(info.key_type)
|
||||
typ := if method_name == 'keys' {
|
||||
c.table.find_or_register_array(info.key_type)
|
||||
} else {
|
||||
c.table.find_or_register_array(info.value_type)
|
||||
}
|
||||
ret_type = ast.Type(typ)
|
||||
}
|
||||
'delete' {
|
||||
|
|
|
@ -1044,6 +1044,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
} else if final_left_sym.kind == .map {
|
||||
if node.name == 'keys' {
|
||||
name = 'map_keys'
|
||||
} else if node.name == 'values' {
|
||||
name = 'map_values'
|
||||
}
|
||||
}
|
||||
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
|
||||
|
|
Loading…
Reference in New Issue