diff options
| author | steven-na <noreply.github@stvnc.dev> | 2026-10-02 00:28:46 -0700 |
|---|---|---|
| committer | steven-na <noreply.github@stvnc.dev> | 2026-10-02 00:28:46 -0700 |
| commit | e01d3f64d42e2fe88f737d4616424b1c5949ae85 (patch) | |
| tree | caf7102b19f8d2cc74069fe767e23fce6d27400b /src/map.c | |
| parent | b5f1cb4e373f859c41ec32d6fdb9b3c4597e37c2 (diff) | |
Improved map api
Diffstat (limited to 'src/map.c')
| -rw-r--r-- | src/map.c | 86 |
1 files changed, 52 insertions, 34 deletions
@@ -13,13 +13,13 @@ #define ENTRY_MASK 0b11111110 typedef struct { - void const *key; + u8 const *key; u64 keylen; } map_key_entry_t; typedef struct _map_t { u64 table_size; - u8 *hashlookup; + u8 *hashlookup; u64 *hashes; map_key_entry_t *keys; void **values; @@ -42,27 +42,27 @@ map_t map_create(smrt_arena_t *arena, u64 capacity) { return map; } -i32 map_insert(map_t const map, u8 const *key, u64 keylen, void *value) { +MapInsertResultK map_insert(map_t map, u8 const *key, u64 keylen, void *value) { u64 h = a5hash128(key, keylen, 0, NULL); u8 h_lookup = h >> (64-8) & ENTRY_MASK; u64 start = h % map->table_size; i64 first_tombstone = -1; u64 tsize = map->table_size; - for (u64 i = start; i != start - 1; i=(i+1)%tsize) { + for (u64 count = 0, i = start; count < tsize; count++, i = (i + 1) % tsize) { u8 h_lookupcmp = map->hashlookup[i]; if (h_lookupcmp == ENTRY_EMPTY) { if (first_tombstone != -1) i = first_tombstone; - map->hashes[i] = h; map->hashlookup[i] = h_lookup; map->keys[i] = (map_key_entry_t){ .key=key, .keylen=keylen }; map->values[i] = value; - return 0; + return MapInsertResultSuccessNew; } if (first_tombstone == -1 && - h_lookupcmp == ENTRY_TOMBSTONE) { + h_lookupcmp == ENTRY_TOMBSTONE) + { first_tombstone = i; continue; } @@ -75,44 +75,31 @@ i32 map_insert(map_t const map, u8 const *key, u64 keylen, void *value) { ) { map->keys[i].key=key; map->values[i]=value; + return MapInsertResultSuccessPreexisted; } } - log_warn("Attempted to insert value with key \"%.*s...\" into hashmap that is full", - (i32)MIN(5, keylen), key); - return -1; -} -i32 map_delete(map_t const map, u8 const *key, u64 keylen) { - u64 h = a5hash128(key, keylen, 0, NULL); - u8 h_lookup = h >> (64-8) & ENTRY_MASK; - - u64 start = h % map->table_size; - u64 tsize = map->table_size; - for (u64 i = start; i != start - 1; i=(i+1)%tsize) { - u8 h_lookupcmp = map->hashlookup[i]; - if (h_lookupcmp == ENTRY_EMPTY) return -1; - if (h_lookupcmp == ENTRY_TOMBSTONE) continue; - - if (h_lookupcmp == h_lookup && - h == map->hashes[i] && - keylen == map->keys[i].keylen && - (memcmp(key, map->keys[i].key, keylen) == 0)) - { map->keys[i].keylen=0; - map->hashlookup[i]=ENTRY_TOMBSTONE; - return 0; } + if (first_tombstone >= 0) { + map->hashes[first_tombstone] = h; + map->hashlookup[first_tombstone] = h_lookup; + map->keys[first_tombstone] = (map_key_entry_t){ .key=key, .keylen=keylen }; + map->values[first_tombstone] = value; + return MapInsertResultSuccessNew; } - return -1; + log_warn("Attempted to insert value with key \"%.*s...\" into hashmap that is full", + (i32)MIN(5, keylen), key); + return MapInsertResultFailedFull; } -void *map_lookup(map_t const map, u8 const *key, u64 keylen) { +static inline i64 map_find_slot(map_t const map, u8 const *key, u64 keylen) { u64 h = a5hash128(key, keylen, 0, NULL); u8 h_lookup = h >> (64-8) & ENTRY_MASK; u64 start = h % map->table_size; u64 tsize = map->table_size; - for (u64 i = start; i != start - 1; i = (i+1)%tsize) { + for (u64 count = 0, i = start; count < tsize; count++, i = (i + 1) % tsize) { u8 h_lookupcmp = map->hashlookup[i]; if (h_lookupcmp == ENTRY_EMPTY) break; if (h_lookupcmp == ENTRY_TOMBSTONE) continue; @@ -122,8 +109,39 @@ void *map_lookup(map_t const map, u8 const *key, u64 keylen) { h == map->hashes[i] && k.keylen == keylen && (memcmp(key, k.key, keylen) == 0)) - { return map->values[i]; } + { return (i64)i; } + } + + return -1; +} + +MapDeleteResultK map_delete(map_t map, u8 const *key, u64 keylen) { + i64 slot = map_find_slot(map, key, keylen); + if (slot >= 0) { + map->keys[slot].keylen=0; + map->hashlookup[slot]=ENTRY_TOMBSTONE; + return MapDeleteResultSuccess; + } + return MapDeleteResultNotFound; +} + +void map_clear(map_t map) { + for (u64 i = 0; i < map->table_size; i++) { + map->hashlookup[i] = ENTRY_EMPTY; + } +} + +void *map_lookup(map_t const map, u8 const *key, u64 keylen) { + i64 slot = map_find_slot(map, key, keylen); + return slot >= 0 ? map->values[slot] : NULL; +} + +MapChangeKeyPtrResultK map_change_key_ptr(map_t map, u8 const *new_but_identical_key, u64 keylen) { + i64 slot = map_find_slot(map, new_but_identical_key, keylen); + if (slot >= 0) { + map->keys[slot].key = new_but_identical_key; + return MapChangeKeyPtrResultSuccess; } - return NULL; + return MapChangeKeyPtrResultKeyNotPresent; } |