X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fhashmap.c;h=a2c728d642540bab342e1c989924bb0e4d0ae721;hp=ab00957306e9fb2fdb2d8e1b0e63263368973e07;hb=090cafa0678333435486f2d70296311d20a2ed5d;hpb=9946996cda11a18b44d82344676e5a0e96339408 diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index ab0095730..a2c728d64 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -103,7 +103,7 @@ static void deallocate_tile(void **first_tile, void *p) { *first_tile = p; } -#ifndef __OPTIMIZE__ +#ifdef VALGRIND static void drop_pool(struct pool *p) { while (p) { @@ -147,6 +147,25 @@ int trivial_compare_func(const void *a, const void *b) { return a < b ? -1 : (a > b ? 1 : 0); } +unsigned uint64_hash_func(const void *p) { + uint64_t u; + + assert_cc(sizeof(uint64_t) == 2*sizeof(unsigned)); + + u = *(const uint64_t*) p; + + return (unsigned) ((u >> 32) ^ u); +} + +int uint64_compare_func(const void *_a, const void *_b) { + uint64_t a, b; + + a = *(const uint64_t*) _a; + b = *(const uint64_t*) _b; + + return a < b ? -1 : (a > b ? 1 : 0); +} + Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { bool b; Hashmap *h; @@ -265,6 +284,8 @@ static void remove_entry(Hashmap *h, struct hashmap_entry *e) { void hashmap_free(Hashmap*h) { + /* Free the hashmap, but nothing in it */ + if (!h) return; @@ -277,6 +298,13 @@ void hashmap_free(Hashmap*h) { } void hashmap_free_free(Hashmap *h) { + + /* Free the hashmap and all data objects in it, but not the + * keys */ + + if (!h) + return; + hashmap_clear_free(h); hashmap_free(h); } @@ -292,7 +320,8 @@ void hashmap_clear(Hashmap *h) { void hashmap_clear_free(Hashmap *h) { void *p; - assert(h); + if (!h) + return; while ((p = hashmap_steal_first(h))) free(p); @@ -318,7 +347,8 @@ int hashmap_put(Hashmap *h, const void *key, void *value) { hash = h->hash_func(key) % NBUCKETS; - if ((e = hash_scan(h, hash, key))) { + e = hash_scan(h, hash, key); + if (e) { if (e->value == value) return 0; @@ -349,8 +379,8 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { assert(h); hash = h->hash_func(key) % NBUCKETS; - - if ((e = hash_scan(h, hash, key))) { + e = hash_scan(h, hash, key); + if (e) { e->key = key; e->value = value; return 0; @@ -359,6 +389,21 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { return hashmap_put(h, key, value); } +int hashmap_update(Hashmap *h, const void *key, void *value) { + struct hashmap_entry *e; + unsigned hash; + + assert(h); + + hash = h->hash_func(key) % NBUCKETS; + e = hash_scan(h, hash, key); + if (!e) + return -ENOENT; + + e->value = value; + return 0; +} + void* hashmap_get(Hashmap *h, const void *key) { unsigned hash; struct hashmap_entry *e; @@ -367,13 +412,45 @@ void* hashmap_get(Hashmap *h, const void *key) { return NULL; hash = h->hash_func(key) % NBUCKETS; + e = hash_scan(h, hash, key); + if (!e) + return NULL; - if (!(e = hash_scan(h, hash, key))) + return e->value; +} + +void* hashmap_get2(Hashmap *h, const void *key, void **key2) { + unsigned hash; + struct hashmap_entry *e; + + if (!h) return NULL; + hash = h->hash_func(key) % NBUCKETS; + e = hash_scan(h, hash, key); + if (!e) + return NULL; + + if (key2) + *key2 = (void*) e->key; + return e->value; } +bool hashmap_contains(Hashmap *h, const void *key) { + unsigned hash; + + if (!h) + return false; + + hash = h->hash_func(key) % NBUCKETS; + + if (!hash_scan(h, hash, key)) + return false; + + return true; +} + void* hashmap_remove(Hashmap *h, const void *key) { struct hashmap_entry *e; unsigned hash; @@ -734,3 +811,25 @@ char **hashmap_get_strv(Hashmap *h) { return sv; } + +void *hashmap_next(Hashmap *h, const void *key) { + unsigned hash; + struct hashmap_entry *e; + + assert(h); + assert(key); + + if (!h) + return NULL; + + hash = h->hash_func(key) % NBUCKETS; + e = hash_scan(h, hash, key); + if (!e) + return NULL; + + e = e->iterate_next; + if (!e) + return NULL; + + return e->value; +}