From: Lennart Poettering Date: Mon, 18 Jan 2010 22:49:49 +0000 (+0100) Subject: implement hashmap_copy() and hashmap_merge() X-Git-Tag: v1~850 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=91cdde8a7a08c6797995cc67f4b55ac43780cdd8 implement hashmap_copy() and hashmap_merge() --- diff --git a/hashmap.c b/hashmap.c index 1b2e059dd..4db61732f 100644 --- a/hashmap.c +++ b/hashmap.c @@ -18,7 +18,6 @@ struct hashmap_entry { const void *key; void *value; - struct hashmap_entry *bucket_next, *bucket_previous; struct hashmap_entry *iterate_next, *iterate_previous; }; @@ -323,3 +322,38 @@ bool hashmap_isempty(Hashmap *h) { return h->n_entries == 0; } + +int hashmap_merge(Hashmap *h, Hashmap *other) { + struct hashmap_entry *e; + + assert(h); + + if (!other) + return 0; + + for (e = other->iterate_list_head; e; e = e->iterate_next) { + int r; + + if ((r = hashmap_put(h, e->key, e->value)) < 0) + if (r != -EEXIST) + return r; + } + + return 0; +} + +Hashmap *hashmap_copy(Hashmap *h) { + Hashmap *copy; + + assert(h); + + if (!(copy = hashmap_new(h->hash_func, h->compare_func))) + return NULL; + + if (hashmap_merge(copy, h) < 0) { + hashmap_free(copy); + return NULL; + } + + return copy; +} diff --git a/hashmap.h b/hashmap.h index 4c946e35b..e3b9d9aa3 100644 --- a/hashmap.h +++ b/hashmap.h @@ -22,12 +22,15 @@ unsigned trivial_hash_func(const void *p); int trivial_compare_func(const void *a, const void *b); Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func); -void hashmap_free(Hashmap*); +void hashmap_free(Hashmap *h); +Hashmap *hashmap_copy(Hashmap *h); int hashmap_put(Hashmap *h, const void *key, void *value); void* hashmap_get(Hashmap *h, const void *key); void* hashmap_remove(Hashmap *h, const void *key); +int hashmap_merge(Hashmap *h, Hashmap *other); + unsigned hashmap_size(Hashmap *h); bool hashmap_isempty(Hashmap *h); diff --git a/set.c b/set.c index 3aa227bbc..21a1739b0 100644 --- a/set.c +++ b/set.c @@ -61,3 +61,11 @@ void* set_first(Set *s) { void* set_last(Set *s) { return hashmap_last(MAKE_HASHMAP(s)); } + +int set_merge(Set *s, Set *other) { + return hashmap_merge(MAKE_HASHMAP(s), MAKE_HASHMAP(other)); +} + +Set* set_copy(Set *s) { + return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s))); +} diff --git a/set.h b/set.h index 9aefdbcb5..a2e405941 100644 --- a/set.h +++ b/set.h @@ -14,21 +14,24 @@ typedef struct Set Set; Set *set_new(hash_func_t hash_func, compare_func_t compare_func); -void set_free(Set* set); +Set* set_copy(Set *s); +void set_free(Set* s); int set_put(Set *s, void *value); void *set_get(Set *s, void *value); void *set_remove(Set *s, void *value); +int set_merge(Set *s, Set *other); + unsigned set_size(Set *s); bool set_isempty(Set *s); -void *set_iterate(Set *h, void **state); -void *set_iterate_backwards(Set *h, void **state); +void *set_iterate(Set *s, void **state); +void *set_iterate_backwards(Set *s, void **state); -void *set_steal_first(Set *h); -void* set_first(Set *h); -void* set_last(Set *h); +void *set_steal_first(Set *s); +void* set_first(Set *s); +void* set_last(Set *s); #define SET_FOREACH(e, s, state) \ for ((state) = NULL, (e) = set_iterate((s), &(state)); (e); (e) = set_iterate((s), &(state)))