v/vlib/builtin/map.v

285 lines
4.8 KiB
V
Raw Normal View History

2019-06-23 04:21:30 +02:00
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
2019-06-22 20:20:28 +02:00
module builtin
2019-08-29 00:52:32 +02:00
import strings
2019-08-05 04:34:12 +02:00
2019-10-24 11:47:21 +02:00
pub struct map {
2019-06-22 20:20:28 +02:00
element_size int
2019-12-19 21:52:45 +01:00
root &mapnode
2019-08-29 00:52:32 +02:00
pub:
2019-12-19 21:52:45 +01:00
size int
2019-06-22 20:20:28 +02:00
}
2019-08-29 00:52:32 +02:00
struct mapnode {
2019-12-19 21:52:45 +01:00
left &mapnode
right &mapnode
2019-11-22 18:05:27 +01:00
is_empty bool // set by delete()
2019-12-19 21:52:45 +01:00
key string
val voidptr
2019-06-22 20:20:28 +02:00
}
fn new_map(cap, elm_size int) map {
2019-12-19 21:52:45 +01:00
res := map{
2019-06-22 20:20:28 +02:00
element_size: elm_size
2019-08-29 00:52:32 +02:00
root: 0
2019-06-22 20:20:28 +02:00
}
return res
}
2019-08-29 00:52:32 +02:00
// `m := { 'one': 1, 'two': 2 }`
2019-09-01 21:51:16 +02:00
fn new_map_init(cap, elm_size int, keys &string, vals voidptr) map {
2019-12-19 21:52:45 +01:00
mut res := map{
2019-08-03 09:44:08 +02:00
element_size: elm_size
2019-08-29 00:52:32 +02:00
root: 0
2019-08-03 09:44:08 +02:00
}
for i in 0 .. cap {
2019-10-10 00:15:19 +02:00
res.set(keys[i], vals + i * elm_size)
2019-08-29 00:52:32 +02:00
}
2019-08-03 09:44:08 +02:00
return res
2019-08-29 00:52:32 +02:00
}
2019-08-03 09:44:08 +02:00
2019-09-01 21:51:16 +02:00
fn new_node(key string, val voidptr, element_size int) &mapnode {
2019-12-19 21:52:45 +01:00
new_e := &mapnode{
2019-06-22 20:20:28 +02:00
key: key
2019-07-14 11:01:32 +02:00
val: malloc(element_size)
left: 0
2019-08-29 00:52:32 +02:00
right: 0
2019-06-22 20:20:28 +02:00
}
2019-07-14 11:01:32 +02:00
C.memcpy(new_e.val, val, element_size)
2019-06-22 20:20:28 +02:00
return new_e
}
2019-08-29 00:52:32 +02:00
fn (m mut map) insert(n mut mapnode, key string, val voidptr) {
2019-07-14 11:01:32 +02:00
if n.key == key {
C.memcpy(n.val, val, m.element_size)
if n.is_empty {
m.size++
2019-12-19 19:17:12 +01:00
n.is_empty = false
}
2019-08-29 00:52:32 +02:00
return
}
2019-07-14 11:01:32 +02:00
if n.key > key {
2019-08-25 23:08:06 +02:00
if n.left == 0 {
2019-08-29 00:52:32 +02:00
n.left = new_node(key, val, m.element_size)
m.size++
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
m.insert(mut n.left, key, val)
}
return
}
2019-08-25 23:08:06 +02:00
if n.right == 0 {
2019-08-29 00:52:32 +02:00
n.right = new_node(key, val, m.element_size)
m.size++
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
m.insert(mut n.right, key, val)
}
}
2019-12-19 21:52:45 +01:00
fn (n &mapnode) find(key string, out voidptr, element_size int) bool {
2019-07-14 11:01:32 +02:00
if n.key == key {
C.memcpy(out, n.val, element_size)
2019-08-29 00:52:32 +02:00
return true
}
2019-07-14 11:01:32 +02:00
else if n.key > key {
2019-08-25 23:08:06 +02:00
if n.left == 0 {
2019-08-29 00:52:32 +02:00
return false
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
return n.left.find(key, out, element_size)
}
}
2019-07-14 11:01:32 +02:00
else {
2019-08-25 23:08:06 +02:00
if n.right == 0 {
2019-08-29 00:52:32 +02:00
return false
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
return n.right.find(key, out, element_size)
}
}
2019-08-29 00:52:32 +02:00
}
2019-07-14 11:01:32 +02:00
2019-08-29 00:52:32 +02:00
// same as `find`, but doesn't return a value. Used by `exists`
2019-12-19 21:52:45 +01:00
fn (n &mapnode) find2(key string, element_size int) bool {
2019-11-22 18:05:27 +01:00
if n.key == key && !n.is_empty {
2019-08-29 00:52:32 +02:00
return true
}
2019-07-14 11:01:32 +02:00
else if n.key > key {
if isnil(n.left) {
2019-08-29 00:52:32 +02:00
return false
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
return n.left.find2(key, element_size)
}
}
2019-07-14 11:01:32 +02:00
else {
if isnil(n.right) {
2019-08-29 00:52:32 +02:00
return false
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
return n.right.find2(key, element_size)
}
}
2019-08-29 00:52:32 +02:00
}
2019-07-14 11:01:32 +02:00
fn (m mut map) set(key string, val voidptr) {
if isnil(m.root) {
m.root = new_node(key, val, m.element_size)
m.size++
return
}
m.insert(mut m.root, key, val)
}
2019-08-29 00:52:32 +02:00
/*
2019-06-22 20:20:28 +02:00
fn (m map) bs(query string, start, end int, out voidptr) {
// println('bs "$query" $start -> $end')
mid := start + ((end - start) / 2)
if end - start == 0 {
last := m.entries[end]
C.memcpy(out, last.val, m.element_size)
return
}
if end - start == 1 {
first := m.entries[start]
C.memcpy(out, first.val, m.element_size)
return
}
if mid >= m.entries.len {
return
}
mid_msg := m.entries[mid]
// println('mid.key=$mid_msg.key')
if query < mid_msg.key {
m.bs(query, start, mid, out)
return
}
m.bs(query, mid, end, out)
}
2019-08-29 00:52:32 +02:00
*/
2019-06-22 20:20:28 +02:00
2019-12-19 21:52:45 +01:00
2019-08-29 00:52:32 +02:00
fn preorder_keys(node &mapnode, keys mut []string, key_i int) int {
mut i := key_i
if !node.is_empty {
keys[i] = node.key
i++
}
2019-08-29 00:52:32 +02:00
if !isnil(node.left) {
i = preorder_keys(node.left, mut keys, i)
2019-08-29 00:52:32 +02:00
}
if !isnil(node.right) {
i = preorder_keys(node.right, mut keys, i)
}
return i
2019-08-29 00:52:32 +02:00
}
2019-06-22 20:20:28 +02:00
2019-09-25 04:56:10 +02:00
pub fn (m &map) keys() []string {
2019-09-19 04:22:24 +02:00
mut keys := [''].repeat(m.size)
2019-07-14 11:01:32 +02:00
if isnil(m.root) {
return keys
}
preorder_keys(m.root, mut keys, 0)
return keys
2019-06-24 11:29:54 +02:00
}
2019-06-22 20:20:28 +02:00
fn (m map) get(key string, out voidptr) bool {
2019-12-19 21:52:45 +01:00
// println('g')
2019-08-25 23:08:06 +02:00
if m.root == 0 {
2019-08-29 00:52:32 +02:00
return false
}
return m.root.find(key, out, m.element_size)
2019-06-22 20:20:28 +02:00
}
2019-08-29 00:52:32 +02:00
pub fn (n mut mapnode) delete(key string, element_size int) {
2019-07-30 21:27:31 +02:00
if n.key == key {
C.memset(n.val, 0, element_size)
2019-08-29 00:52:32 +02:00
n.is_empty = true
return
}
2019-07-30 21:27:31 +02:00
else if n.key > key {
if isnil(n.left) {
2019-08-29 00:52:32 +02:00
return
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
n.left.delete(key, element_size)
}
}
2019-07-30 21:27:31 +02:00
else {
if isnil(n.right) {
2019-08-29 00:52:32 +02:00
return
2019-12-19 21:52:45 +01:00
}
else {
2019-08-29 00:52:32 +02:00
n.right.delete(key, element_size)
}
}
}
pub fn (m mut map) delete(key string) {
if m.exists(key) {
m.root.delete(key, m.element_size)
m.size--
}
2019-08-29 00:52:32 +02:00
}
2019-07-30 21:27:31 +02:00
fn (m map) exists(key string) bool {
return !isnil(m.root) && m.root.find2(key, m.element_size)
2019-07-23 22:57:06 +02:00
}
pub fn (m map) print() {
2019-06-22 20:20:28 +02:00
println('<<<<<<<<')
2019-12-19 21:52:45 +01:00
// for i := 0; i < m.entries.len; i++ {
// entry := m.entries[i]
// println('$entry.key => $entry.val')
// }
2019-06-24 22:37:53 +02:00
/*
2019-06-22 20:20:28 +02:00
for i := 0; i < m.cap * m.element_size; i++ {
b := m.table[i]
print('$i: ')
C.printf('%02x', b)
println('')
}
*/
2019-12-19 21:52:45 +01:00
2019-06-22 20:20:28 +02:00
println('>>>>>>>>>>')
}
fn (n mut mapnode) free() {
if n.val != 0 {
free(n.val)
}
if n.left != 0 {
n.left.free()
}
if n.right != 0 {
n.right.free()
}
free(n)
}
pub fn (m mut map) free() {
if m.root == 0 {
return
}
m.root.free()
2019-06-22 20:20:28 +02:00
// C.free(m.table)
// C.free(m.keys_table)
}
pub fn (m map_string) str() string {
2019-07-14 11:01:32 +02:00
if m.size == 0 {
2019-06-22 20:20:28 +02:00
return '{}'
}
mut sb := strings.new_builder(50)
2019-08-29 00:52:32 +02:00
sb.writeln('{')
2019-12-19 21:52:45 +01:00
for key, val in m {
2019-08-29 00:52:32 +02:00
sb.writeln(' "$key" => "$val"')
2019-08-05 04:34:12 +02:00
}
2019-08-29 00:52:32 +02:00
sb.writeln('}')
return sb.str()
2019-06-22 20:20:28 +02:00
}
2019-12-19 21:52:45 +01:00