diff options
author | Lassi Pulkkinen <lassi@pulk.fi> | 2024-10-31 03:11:21 +0200 |
---|---|---|
committer | Lassi Pulkkinen <lassi@pulk.fi> | 2024-10-31 03:51:35 +0200 |
commit | ae44478b30d890fe0fb04022f44d474dcdcc3f9d (patch) | |
tree | 5f462459ae4b47d22114eed717d1382d08cf4dfe /idreg.ha |
Diffstat (limited to 'idreg.ha')
-rw-r--r-- | idreg.ha | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/idreg.ha b/idreg.ha new file mode 100644 index 0000000..1cdd74a --- /dev/null +++ b/idreg.ha @@ -0,0 +1,72 @@ +use hash::fnv; +use htab; +use strings; +use types; + +type IdRegistry = struct { + idtoname: []str, + nametoid: htab::table, // u32 +}; + +def HTAB_EMPTY = htab::table { + // XXX: harec limitation... + table = &htab::empty, + nslots = 1, + ... +}; + +def IDREG_EMPTY = IdRegistry { + nametoid = HTAB_EMPTY, + ... +}; + +fn newidreg() IdRegistry = + IdRegistry { + idtoname = [], + nametoid = htab::new(0, size(u32)), + }; + +fn idreg_count(reg: *IdRegistry) u32 = + len(reg.idtoname): u32; + +fn idreg_exists(reg: *IdRegistry, id: u32) bool = + id < len(reg.idtoname); + +fn idreg_getname(reg: *IdRegistry, id: u32) str = + reg.idtoname[id]; + +fn idreg_eqfunc(ctx: *opaque, entry: *opaque) bool = { + const ctx = ctx: *(*IdRegistry, str); + return ctx.1 == ctx.0.idtoname[*(entry: *u32)]; +}; + +fn idreg_lookup(reg: *IdRegistry, name: str) (u32 | void) = { + const hash = fnv::string64(name); + match (htab::get(®.nametoid, hash, + &idreg_eqfunc, &(reg, name), size(u32))) { + case let entry: *opaque => + return *(entry: *u32); + case null => void; + }; +}; + +fn idreg_register(reg: *IdRegistry, name: str) u32 = { + assert(idreg_lookup(reg, name) is void, "already registered"); + assert(len(reg.idtoname) < types::U32_MAX, "registry full"); + + const id = len(reg.idtoname): u32; + append(reg.idtoname, strings::dup(name)); + + const hash = fnv::string64(name); + const entry = htab::add(®.nametoid, hash, size(u32)); + *(entry: *u32) = id; + + return id; +}; + +fn idreg_clear(reg: *IdRegistry) void = { + strings::freeall(reg.idtoname); + htab::finish(®.nametoid); + reg.idtoname = []; + reg.nametoid = htab::new(0, size(u32)); +}; |