mirror of
https://github.com/kanaka/mal.git
synced 2024-11-11 00:52:44 +03:00
80 lines
1.5 KiB
OpenEdge ABL
80 lines
1.5 KiB
OpenEdge ABL
|
// Implement our old naive O(n) map because Yeti's hash table (h_new()) cannot
|
||
|
// be used inside arrays and structs (we can't get a pointer to hash table).
|
||
|
// This prevents saving pointer to environment in MalFunction for example.
|
||
|
|
||
|
struct Hash {
|
||
|
pointer keys
|
||
|
pointer vals
|
||
|
}
|
||
|
|
||
|
func hash_new(void)
|
||
|
{
|
||
|
return Hash(keys=&[], vals=&[])
|
||
|
}
|
||
|
|
||
|
func hash_get(h, key)
|
||
|
{
|
||
|
for (i = 1; i <= numberof(*h.keys); ++i) {
|
||
|
if ((*h.keys)(i) == key) return *((*h.vals)(i))
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func hash_has_key(h, key)
|
||
|
{
|
||
|
for (i = 1; i <= numberof(*h.keys); ++i) {
|
||
|
if ((*h.keys)(i) == key) return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func hash_set(&h, key, val)
|
||
|
{
|
||
|
if (is_void(*h.keys)) {
|
||
|
h.keys = &[key]
|
||
|
h.vals = &[&val]
|
||
|
return
|
||
|
}
|
||
|
for (i = 1; i <= numberof(*h.keys); ++i) {
|
||
|
if ((*h.keys)(i) == key) {
|
||
|
(*h.vals)(i) = &val
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
tmp = *h.keys
|
||
|
grow, tmp, [key]
|
||
|
h.keys = &tmp
|
||
|
tmp = *h.vals
|
||
|
grow, tmp, [&val]
|
||
|
h.vals = &tmp
|
||
|
}
|
||
|
|
||
|
func hash_delete(&h, key)
|
||
|
{
|
||
|
if (is_void(*h.keys) || numberof(*h.keys) == 0) return
|
||
|
k = *h.keys
|
||
|
v = *h.vals
|
||
|
if (numberof(k) == 1) {
|
||
|
if (k(1) == key) {
|
||
|
h.keys = &[]
|
||
|
h.vals = &[]
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
for (i = 1; i <= numberof(k); ++i) {
|
||
|
if (k(i) == key) {
|
||
|
if (i == 1) {
|
||
|
h.keys = &(k(i+1:))
|
||
|
h.vals = &(v(i+1:))
|
||
|
} else if (i == numberof(k)) {
|
||
|
h.keys = &(k(1:i-1))
|
||
|
h.vals = &(v(1:i-1))
|
||
|
} else {
|
||
|
h.keys = &grow(k(1:i-1), k(i+1:))
|
||
|
h.vals = &grow(v(1:i-1), v(i+1:))
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}
|