Files
tyche/lib/table.c
Andre Wagner d4aa83869c .
2026-05-16 12:14:11 -05:00

133 lines
3.4 KiB
C

#include "priv.h"
#include "khash.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
KHASH_MAP_INIT_INT64(TABLE_INT, VALUE)
KHASH_MAP_INIT_STR(TABLE_STR, VALUE)
#pragma GCC diagnostic pop
struct Table {
khash_t(TABLE_INT)* tbl_int;
khash_t(TABLE_STR)* tbl_str;
Heap const* heap;
};
Table* table_new(Heap const* heap)
{
Table* t = xcalloc(1, sizeof(Table));
t->tbl_int = kh_init(TABLE_INT);
t->tbl_str = kh_init(TABLE_STR);
t->heap = heap;
return t;
}
void table_destroy(Table* t)
{
kh_destroy(TABLE_INT, t->tbl_int);
kh_destroy(TABLE_STR, t->tbl_str);
free(t);
}
size_t table_len(Table* t)
{
return kh_size(t->tbl_int) + kh_size(t->tbl_str);
}
static TABLE_HASH value_hash(VALUE v)
{
switch (value_type(v)) {
case TT_NIL:
return 0;
case TT_INTEGER:
return (uint64_t) value_integer(v);
case TT_REAL: {
uint32_t vv;
float f = value_real(v);
memcpy(&vv, &f, sizeof(uint32_t));
break;
}
case TT_STRING_CONST:
return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 33);
case TT_ARRAY:
return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 34);
case TT_TABLE:
return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 35);
case TT_FUNCTION:
return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 36);
case TT_NATIVE_PTR:
return (TABLE_HASH) value_idx(v) | ((TABLE_HASH) 1 << 37);
case TT_STRING:
case TT_COUNT__:
default:
__builtin_unreachable();
}
return 0;
}
TYC_RESULT table_get(Table const* t, VALUE key, VALUE* value)
{
if (value_type(key) == TT_STRING) {
const char* skey;
if (heap_get_string(t->heap, value_idx(key), &skey) != T_OK)
abort();
khiter_t k = kh_get(TABLE_STR, t->tbl_str, skey);
if (k == kh_end(t->tbl_str))
return T_ERR_TABLE_KEY_NOT_FOUND;
*value = kh_value(t->tbl_str, k);
} else {
TABLE_HASH hash = value_hash(key);
khiter_t k = kh_get(TABLE_INT, t->tbl_int, hash);
if (k == kh_end(t->tbl_int))
return T_ERR_TABLE_KEY_NOT_FOUND;
*value = kh_value(t->tbl_int, k);
}
return T_OK;
}
void table_set(Table* t, VALUE key, VALUE value)
{
int ret;
if (value_type(key) == TT_STRING) {
const char* skey;
if (heap_get_string(t->heap, value_idx(key), &skey) != T_OK)
abort();
khiter_t k = kh_put(TABLE_STR, t->tbl_str, skey, &ret);
if (ret < 0)
out_of_memory();
kh_value(t->tbl_str, k) = value;
} else {
TABLE_HASH hash = value_hash(key);
khiter_t k = kh_put(TABLE_INT, t->tbl_int, hash, &ret);
if (ret < 0)
out_of_memory();
kh_value(t->tbl_int, k) = value;
}
}
void table_del(Table* t, VALUE key)
{
if (value_type(key) == TT_STRING) {
const char* skey;
if (heap_get_string(t->heap, value_idx(key), &skey) != T_OK)
abort();
khiter_t k = kh_get(TABLE_STR, t->tbl_str, skey);
if (k == kh_end(t->tbl_str))
return;
kh_del(TABLE_STR, t->tbl_str, k);
} else {
TABLE_HASH hash = value_hash(key);
khiter_t k = kh_get(TABLE_INT, t->tbl_int, hash);
if (k == kh_end(t->tbl_int))
return;
kh_del(TABLE_INT, t->tbl_int, k);
}
}