diff -r fd3368c20413 -r 69a83fad8a35 src/hash_map.c --- a/src/hash_map.c Fri May 27 17:40:27 2022 +0200 +++ b/src/hash_map.c Wed Jun 08 21:33:31 2022 +0200 @@ -30,60 +30,6 @@ #include "cx/hash_map.h" #include "cx/utils.h" -/** - * Computes a murmur hash-2. - * - * @param data the data to hash - * @param len the length of the data - * @return the murmur hash-2 of the data - */ -static unsigned cx_hash_map_murmur( - unsigned char const *data, - size_t len -) { - unsigned m = 0x5bd1e995; - unsigned r = 24; - unsigned h = 25 ^ len; - unsigned i = 0; - while (len >= 4) { - unsigned k = data[i + 0] & 0xFF; - k |= (data[i + 1] & 0xFF) << 8; - k |= (data[i + 2] & 0xFF) << 16; - k |= (data[i + 3] & 0xFF) << 24; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - i += 4; - len -= 4; - } - - switch (len) { - case 3: - h ^= (data[i + 2] & 0xFF) << 16; - __attribute__((__fallthrough__)); - case 2: - h ^= (data[i + 1] & 0xFF) << 8; - __attribute__((__fallthrough__)); - case 1: - h ^= (data[i + 0] & 0xFF); - h *= m; - __attribute__((__fallthrough__)); - default: - /* do nothing */; - } - - h ^= h >> 13; - h *= m; - h ^= h >> 15; - - return h; -} - static void cx_hash_map_clear(struct cx_map_s *map) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; cx_for_n(i, hash_map->bucket_count) { @@ -92,7 +38,7 @@ do { struct cx_hash_map_element_s *next = elem->next; // free the key data - cxFree(map->allocator, elem->key.data); + cxFree(map->allocator, elem->key.data.obj); // free the node cxFree(map->allocator, elem); // proceed @@ -119,13 +65,17 @@ static int cx_hash_map_put( CxMap *map, - CxDataPtr key, + CxHashKey key, void *value ) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; CxAllocator *allocator = map->allocator; - unsigned hash = cx_hash_map_murmur(key.data, key.len); + unsigned hash = key.hash; + if (hash == 0) { + cx_hash_murmur(&key); + hash = key.hash; + } size_t slot = hash % hash_map->bucket_count; struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; @@ -151,8 +101,8 @@ if (kd == NULL) { return -1; } - memcpy(kd, key.data, key.len); - e->key.data = kd; + memcpy(kd, key.data.obj, key.len); + e->key.data.obj = kd; e->key.len = key.len; e->key.hash = hash; @@ -187,7 +137,7 @@ prev->next = elm->next; } // free element - cxFree(hash_map->base.allocator, elm->key.data); + cxFree(hash_map->base.allocator, elm->key.data.obj); cxFree(hash_map->base.allocator, elm); // decrease size hash_map->base.size--; @@ -203,19 +153,23 @@ */ static void *cx_hash_map_get_remove( CxMap *map, - CxDataPtr key, + CxHashKey key, bool remove ) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; - unsigned hash = cx_hash_map_murmur(key.data, key.len); + unsigned hash = key.hash; + if (hash == 0) { + cx_hash_murmur(&key); + hash = key.hash; + } size_t slot = hash % hash_map->bucket_count; struct cx_hash_map_element_s *elm = hash_map->buckets[slot]; struct cx_hash_map_element_s *prev = NULL; while (elm && elm->key.hash <= hash) { if (elm->key.hash == hash && elm->key.len == key.len) { - if (memcmp(elm->key.data, key.data, key.len) == 0) { + if (memcmp(elm->key.data.obj, key.data.obj, key.len) == 0) { void *data = elm->data; if (remove) { cx_hash_map_unlink(hash_map, slot, prev, elm); @@ -232,7 +186,7 @@ static void *cx_hash_map_get( CxMap const *map, - CxDataPtr key + CxHashKey key ) { // we can safely cast, because we know when remove=false, the map stays untouched return cx_hash_map_get_remove((CxMap *) map, key, false); @@ -240,7 +194,7 @@ static void *cx_hash_map_remove( CxMap *map, - CxDataPtr key + CxHashKey key ) { return cx_hash_map_get_remove(map, key, true); }