v/vlib/builtin/map.v

173 lines
3.1 KiB
Go

// 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.
module builtin
struct map {
// cap int
// keys []string
// table byteptr
// keys_table *string
// table *Entry
element_size int
// collisions []Entry
pub:
entries []Entry
is_sorted bool
}
struct Entry {
pub:
key string
val voidptr
// linked list for collisions
// next *Entry
}
fn new_map(cap, elm_size int) map {
res := map {
// len: len,
element_size: elm_size
// entries:
// keys: []string
}
return res
}
fn (m &map) new_entry(key string, val voidptr) Entry {
new_e := Entry {
key: key
val: malloc(m.element_size)
// next: 0
}
C.memcpy(new_e.val, val, m.element_size)
return new_e
}
fn (m mut map) _set(key string, val voidptr) {
e := m.new_entry(key, val)
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
if entry.key == key {
// e := Entry2{key: key, val: val}
m.entries[i] = e
return
}
}
m.entries << e// m.new_entry(key, val)
m.is_sorted = false
}
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)
}
fn compare_map(a, b *Entry) int {
if a.key < b.key {
return -1
}
if a.key > b.key {
return 1
}
return 0
}
pub fn (m mut map) sort() {
m.entries.sort_with_compare(compare_map)
m.is_sorted = true
}
pub fn (m map) keys() []string {
mut keys := []string{}
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
keys << entry.key
}
return keys
}
fn (m map) get(key string, out voidptr) bool {
if m.is_sorted {
// println('\n\nget "$key" sorted')
m.bs(key, 0, m.entries.len, out)
return true
}
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
if entry.key == key {
C.memcpy(out, entry.val, m.element_size)
return true
}
}
return false
}
pub fn (m map) exists(key string) bool {
for i := 0; i < m.entries.len; i++ {
entry := m.entries[i]
if entry.key == key {
return true
}
}
return false
}
pub fn (m map) print() {
println('<<<<<<<<')
for i := 0; i < m.entries.len; i++ {
// entry := m.entries[i]
// println('$entry.key => $entry.val')
}
/*
for i := 0; i < m.cap * m.element_size; i++ {
b := m.table[i]
print('$i: ')
C.printf('%02x', b)
println('')
}
*/
println('>>>>>>>>>>')
}
pub fn (m map) free() {
// C.free(m.table)
// C.free(m.keys_table)
}
pub fn (m map_string) str() string {
// return 'not impl'
if m.entries.len == 0 {
return '{}'
}
// TODO use bytes buffer
mut s := '{\n'
for entry in m.entries {
val := m[entry.key]
s += ' "$entry.key" => "$val"\n'
}
s += '}'
return s
}