From 2e4ecca19aadc09d5c3d927724f8004b6a0ff0b0 Mon Sep 17 00:00:00 2001 From: quou Date: Thu, 13 Feb 2025 23:32:28 +1100 Subject: refactoring; prep for shadows --- hashmap.hpp | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 hashmap.hpp (limited to 'hashmap.hpp') diff --git a/hashmap.hpp b/hashmap.hpp new file mode 100644 index 0000000..952bf86 --- /dev/null +++ b/hashmap.hpp @@ -0,0 +1,158 @@ +#ifndef hashmap_hpp +#define hashmap_hpp + +extern "C" { +#include "plat.h" +} + +#include +#include + +template +struct Hash_Function {}; + +template +struct Hash_Map { + enum { + flags_tombstone = 1 << 0, + flags_null = 1 << 1 + }; + + Key keys[size]; + Value values[size]; + uint8_t flags[size]; + + void init() { + int i; + for (i = 0; i < size; i++) flags[i] = flags_null; + } + + int find(const Key& to_find) const { + int tombstone = -1, i; + int bucket = (int)(Hash_Function{}(to_find) % (size_t)size); + for (i = 0; i < size; i++) { + const Key& k = keys[bucket]; + uint8_t flag = flags[bucket]; + if (flag & flags_null) { + if (flag & flags_tombstone) { + if (tombstone < 0) tombstone = bucket; + } else return tombstone >= 0? tombstone: bucket; + } else if (k == to_find) return bucket; + bucket = (bucket + 1) % size; + } + if (tombstone >= 0) return tombstone; + return -1; + } + + Value& set(const Key& k, const Value& v) { + int bucket = find(k); + assert(bucket >= 0); /* full */ + flags[bucket] = 0; + keys[bucket] = k; + values[bucket] = v; + return values[bucket]; + } + + Value* get(const Key& k) { + int bucket = find(k); + if (bucket < 0 || flags[bucket] & flags_null) return 0; + return &values[bucket]; + } + + Value& operator[](const Key& k) { + int bucket = find(k); + assert(bucket >= 0); + return values[bucket]; + } + + const Value& operator[](const Key& k) const { + int bucket = find(k); + assert(bucket >= 0); + return values[bucket]; + } + + Key* kaddr(const Key& k) { + int bucket = find(k); + if (bucket < 0 || flags[bucket] & flags_null) return 0; + return &keys[bucket]; + } + + void remove(const Key& k) { + int bucket = find(k); + assert(bucket >= 0); + flags[bucket] = flags_null | flags_tombstone; + } + + int has(const Key& k) { + int bucket = find(k); + return bucket >= 0 && ~flags[bucket] & flags_null; + } + + template + struct iterator { + Table* table; + int bucket; + + void init_begin(Table* t) { + bucket = 0; + table = t; + while ( + bucket < size && + table->flags[bucket] & flags_null + ) bucket++; + } + void init_end(Table* t) { + bucket = size; + table = t; + } + bool equals(const iterator& other) { + return bucket == other.bucket && table == other.table; + } + bool operator==(const iterator
& other) { + return equals(other); + } + bool operator!=(const iterator
& other) { + return !equals(other); + } + iterator
operator++() { + bucket++; + while ( + bucket < size && + table->flags[bucket] & flags_null + ) bucket++; + return *this; + } + std::pair operator*() { + return { table->keys[bucket], table->values[bucket] }; + } + std::pair operator*() const { + return { table->keys[bucket], table->values[bucket] }; + } + }; + + iterator> begin() { + iterator> r; + r.init_begin(this); + return r; + } + + iterator> end() { + iterator> r; + r.init_end(this); + return r; + } + + iterator> begin() const { + iterator> r; + r.init_begin(this); + return r; + } + + iterator> end() const { + iterator> r; + r.init_end(this); + return r; + } +}; + +#endif -- cgit v1.2.3-54-g00ecf