X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fhashmap.c;h=dcfbb67228e826b21260d4d995ca6ed3a5494bfb;hp=6928118615ba48306f15b9afee225550a62ed758;hb=a4bcff5ba36115495994e9f9ba66074471de76ab;hpb=d7832d2c6e0ef5f2839a2296c1cc2fc85c7d9632 diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index 692811861..dcfbb6722 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ @@ -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,11 +298,14 @@ void hashmap_free(Hashmap*h) { } void hashmap_free_free(Hashmap *h) { - void *p; - while ((p = hashmap_steal_first(h))) - free(p); + /* Free the hashmap and all data objects in it, but not the + * keys */ + + if (!h) + return; + hashmap_clear_free(h); hashmap_free(h); } @@ -293,6 +317,16 @@ void hashmap_clear(Hashmap *h) { remove_entry(h, h->iterate_list_head); } +void hashmap_clear_free(Hashmap *h) { + void *p; + + if (!h) + return; + + while ((p = hashmap_steal_first(h))) + free(p); +} + static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) { struct hashmap_entry *e; assert(h); @@ -313,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; @@ -344,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; @@ -354,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; @@ -362,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; @@ -729,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; +}