Hashmap
uint32_t hash(void *data, uint64_t length);Defines
Section titled “Defines”#define HASHMAP_KEY_LEN 256#define hash_map(type) \ struct { \ struct { \ struct { \ type item; \ uint8_t key_data[HASHMAP_KEY_LEN]; \ uint64_t key_len; \ } *items; \ uint64_t capacity; \ uint64_t count; \ } *buckets; \ uint64_t capacity; \ }#define hashmap_init(map, cap) \ map = (typeof(map)) { \ .capacity = cap, .buckets = NULL, \ }hashmap_insert(map, key, key_length, value)
Section titled “hashmap_insert(map, key, key_length, value)”#define hashmap_insert(map, key, key_length, value) \ do { \ /* Copy macro values over. */#define hashmap_remove(map, key, key_length) \ ({ \ __label__ __stop; \ bool __ok = false; \ auto __key_data = (key); \ auto __key_len = (key_length); \ auto __hashmap = (map); \ if (__hashmap->buckets == NULL) \ goto __stop; \ uint64_t __hash = hash(__key_data, __key_len); \ uint64_t __index = __hash % __hashmap->capacity; \ auto __bucket = &__hashmap->buckets[__index]; \ for (uint64_t __i = 0; __i < __bucket->count; __i++) { \ if (__key_len != __bucket->items[__i].key_len) \ continue; \ if (memcmp(__key_data, __bucket->items[__i].key_data, \ __key_len) == 0) { \ if (__i != __bucket->count - 1) { \ memcpy(&__bucket->items[__i], \ &__bucket->items[__bucket->count - 1], \ sizeof(*__bucket->items)); \ } \ __bucket->count -= 1; \ __ok = true; \ break; \ } \ } \ __stop: \ __ok; \ })#define hashmap_get(map, ret, key, key_length) \ ({ \ __label__ __stop; \ bool __ok = false; \ auto __key_data = (key); \ auto __key_len = (key_length); \ auto __map = (map); \ if (__map->buckets == NULL) \ goto __stop; \ uint64_t __hash = hash(__key_data, __key_len); \ uint64_t __index = __hash % __map->capacity; \ auto __bucket = &__map->buckets[__index]; \ for (uint64_t __i = 0; __i < __bucket->count; __i++) { \ if (__key_len != __bucket->items[__i].key_len) \ continue; \ if (memcmp(__key_data, __bucket->items[__i].key_data, \ __key_len) == 0) { \ (ret) = __bucket->items[__i].item; \ __ok = true; \ break; \ } \ } \ __stop: \ __ok; \ })