builtin: add `map.values()` (#14301)
parent
ce99a306c0
commit
0699f324b5
|
@ -86,8 +86,8 @@ mut:
|
||||||
// array allocated (with `cap` bytes) on first deletion
|
// array allocated (with `cap` bytes) on first deletion
|
||||||
// has non-zero element when key deleted
|
// has non-zero element when key deleted
|
||||||
all_deleted &u8
|
all_deleted &u8
|
||||||
values &u8
|
|
||||||
keys &u8
|
keys &u8
|
||||||
|
values &u8
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -126,8 +126,8 @@ fn (d &DenseArray) has_index(i int) bool {
|
||||||
[inline]
|
[inline]
|
||||||
fn (mut d DenseArray) expand() int {
|
fn (mut d DenseArray) expand() int {
|
||||||
old_cap := d.cap
|
old_cap := d.cap
|
||||||
old_value_size := d.value_bytes * old_cap
|
|
||||||
old_key_size := d.key_bytes * old_cap
|
old_key_size := d.key_bytes * old_cap
|
||||||
|
old_value_size := d.value_bytes * old_cap
|
||||||
if d.cap == d.len {
|
if d.cap == d.len {
|
||||||
d.cap += d.cap >> 3
|
d.cap += d.cap >> 3
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -628,6 +628,31 @@ pub fn (m &map) keys() array {
|
||||||
return keys
|
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
|
// warning: only copies keys, does not clone
|
||||||
[unsafe]
|
[unsafe]
|
||||||
fn (d &DenseArray) clone() DenseArray {
|
fn (d &DenseArray) clone() DenseArray {
|
||||||
|
|
|
@ -47,6 +47,16 @@ fn test_keys_many() {
|
||||||
assert keys == strings
|
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() {
|
fn test_deletes_many() {
|
||||||
mut m := map[string]int{}
|
mut m := map[string]int{}
|
||||||
for i, s in strings {
|
for i, s in strings {
|
||||||
|
@ -59,6 +69,7 @@ fn test_deletes_many() {
|
||||||
}
|
}
|
||||||
assert m.len == 0
|
assert m.len == 0
|
||||||
assert m.keys().len == 0
|
assert m.keys().len == 0
|
||||||
|
assert m.values().len == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
|
@ -103,6 +114,13 @@ fn test_map() {
|
||||||
assert m['hi'] == 0
|
assert m['hi'] == 0
|
||||||
assert m.keys().len == 1
|
assert m.keys().len == 1
|
||||||
assert m.keys()[0] == 'hello'
|
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{}
|
mut users := map[string]User{}
|
||||||
users['1'] = User{'Peter'}
|
users['1'] = User{'Peter'}
|
||||||
|
@ -580,6 +598,7 @@ fn test_int_keys() {
|
||||||
4: 16
|
4: 16
|
||||||
5: 25
|
5: 25
|
||||||
}
|
}
|
||||||
|
assert m2.values() == [9, 16, 25]
|
||||||
|
|
||||||
assert m2.len == 3
|
assert m2.len == 3
|
||||||
// clone
|
// clone
|
||||||
|
@ -636,6 +655,16 @@ fn test_voidptr_keys() {
|
||||||
assert m.len == 2
|
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() {
|
fn test_rune_keys() {
|
||||||
mut m := {
|
mut m := {
|
||||||
`!`: 2
|
`!`: 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 {
|
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))
|
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)
|
} 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 {
|
if left_sym.kind == .map {
|
||||||
return c.map_builtin_method_call(mut node, left_type, left_sym)
|
return c.map_builtin_method_call(mut node, left_type, left_sym)
|
||||||
} else {
|
} 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)
|
ret_type = ret_type.clear_flag(.shared_f)
|
||||||
}
|
}
|
||||||
'keys' {
|
'keys', 'values' {
|
||||||
if node.args.len != 0 {
|
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
|
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)
|
ret_type = ast.Type(typ)
|
||||||
}
|
}
|
||||||
'delete' {
|
'delete' {
|
||||||
|
|
|
@ -1044,6 +1044,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
} else if final_left_sym.kind == .map {
|
} else if final_left_sym.kind == .map {
|
||||||
if node.name == 'keys' {
|
if node.name == 'keys' {
|
||||||
name = 'map_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__')
|
if g.pref.obfuscate && g.cur_mod.name == 'main' && name.starts_with('main__')
|
||||||
|
|
Loading…
Reference in New Issue