diff options
| author | Julian Hurst <julian.hurst@digdash.com> | 2025-01-15 18:08:44 +0100 |
|---|---|---|
| committer | Julian Hurst <julian.hurst@digdash.com> | 2025-01-15 18:31:21 +0100 |
| commit | 0490236116c4fcf80563251e4175dbcc78e05787 (patch) | |
| tree | 4c702a8c0de8840984c3dd969da4827e3135476b /map | |
| parent | 4129e3dba2cc3953af6b97fc1c99a1516b9214cd (diff) | |
| download | hatask-0490236116c4fcf80563251e4175dbcc78e05787.tar.gz | |
Add get command to get misc properties from tasks
Unknown entries in the task metadata are now added to a misc map and can be
gotten via the get command.
Diffstat (limited to 'map')
| -rw-r--r-- | map/map.ha | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/map/map.ha b/map/map.ha new file mode 100644 index 0000000..e266032 --- /dev/null +++ b/map/map.ha @@ -0,0 +1,117 @@ +use hash::fnv; +use strings; + +def BUCKETSZ: size = 32z; + +export type map = struct { + buckets: [BUCKETSZ][]entry, +}; + +export type entry = struct { + hash: size, + key: str, + val: str, +}; + +export type iterator = struct { + i: size, + j: size, + m: map, +}; + +export fn newmap() map = { + return map { + ... + }; +}; + +export fn newiterator(m: map) iterator = { + return iterator { + i = 0z, + j = 0z, + m = m, + }; +}; + +export fn put(m: *map, k: str, v: str) void = { + const s = fnv::string(k); + const bucket = &m.buckets[s%len(m.buckets)]; + for (let e &.. bucket) { + if (e.hash == s) { + e.val = v; + return; + }; + }; + append(bucket, entry { + hash = s, + key = strings::dup(k), + val = strings::dup(v), + })!; +}; + +export fn get(m: map, k: str) (str | void) = { + const s = fnv::string(k); + const bucket = m.buckets[s%len(m.buckets)]; + for (let e .. bucket) { + if (e.hash == s) { + return e.val; + }; + }; + return; +}; + +export fn next(it: *iterator) (entry | done) = { + if (len(it.m.buckets) == 0 || len(it.m.buckets) <= it.i) { + return done; + }; + for (true) { + if (len(it.m.buckets) <= it.i) { + return done; + }; + const b = it.m.buckets[it.i]; + if (len(b) == 0 || len(b) <= it.j) { + it.i += 1; + it.j = 0; + } else { + const e = b[it.j]; + it.j += 1; + return e; + }; + }; +}; + +export fn finishmap(m: *map) void = { + for (let e &.. m.buckets) { + finishentries(e); + }; +}; + +fn finishentries(e: *[]entry) void = { + for (let i = 0z; i < len(e); i += 1) { + free(e[i].key); + free(e[i].val); + }; +}; + +@test fn testmap() void = { + const m = newmap(); + defer finishmap(&m); + put(&m, "test", "value"); + const v = get(m, "test"); + assert(v is str); + assert(v as str == "value"); +}; + +@test fn testit() void = { + const m = newmap(); + defer finishmap(&m); + put(&m, "test", "value"); + let it = newiterator(m); + let count = 0; + for (let e => next(&it)) { + count += 1; + assert(e.key == "test"); + assert(e.val == "value"); + }; + assert(count == 1); +}; |
