From afb1fe36b835633228a6bdd0bfd09dafdc9afa65 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Fri, 28 Jun 2024 16:16:50 +0200 Subject: [PATCH] introduce hashmap_ensure_replace() Similar to hashmap_ensure_put(), but replace existing items in the map, as hashmap_replace(). --- src/basic/hashmap.c | 20 ++++++++++++++++++++ src/basic/hashmap.h | 5 +++++ src/test/test-hashmap-plain.c | 24 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index a9fd7620295..951f63ae6da 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -874,6 +874,26 @@ int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ return ordered_hashmap_put(*h, key, value); } +int _ordered_hashmap_ensure_replace(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS) { + int r; + + r = _ordered_hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS); + if (r < 0) + return r; + + return ordered_hashmap_replace(*h, key, value); +} + +int _hashmap_ensure_replace(Hashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS) { + int r; + + r = _hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS); + if (r < 0) + return r; + + return hashmap_replace(*h, key, value); +} + static void hashmap_free_no_clear(HashmapBase *h) { assert(!h->has_indirect); assert(h->n_direct_entries == 0); diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 49d9d118cc3..01a4fb32043 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -130,14 +130,19 @@ HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); int _hashmap_ensure_put(Hashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +int _hashmap_ensure_replace(Hashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); #define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) #define hashmap_ensure_put(s, ops, key, value) _hashmap_ensure_put(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) #define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) +#define hashmap_ensure_replace(s, ops, key, value) _hashmap_ensure_replace(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); #define ordered_hashmap_ensure_put(s, ops, key, value) _ordered_hashmap_ensure_put(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) +int _ordered_hashmap_ensure_replace(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); +#define ordered_hashmap_ensure_replace(s, ops, key, value) _ordered_hashmap_ensure_replace(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) + IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h); static inline IteratedCache* hashmap_iterated_cache_new(Hashmap *h) { return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c index f2d2d4f75da..cb45c150879 100644 --- a/src/test/test-hashmap-plain.c +++ b/src/test/test-hashmap-plain.c @@ -49,6 +49,30 @@ TEST(hashmap_replace) { ASSERT_STREQ(r, "val5"); } +TEST(hashmap_ensure_replace) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + _cleanup_free_ char *val1 = NULL, *val2 = NULL; + + val1 = strdup("val1"); + ASSERT_NOT_NULL(val1); + val2 = strdup("val2"); + ASSERT_NOT_NULL(val2); + + ASSERT_OK(hashmap_ensure_replace(&m, &string_hash_ops, val1, val2)); + + ASSERT_OK(hashmap_ensure_replace(&m, &string_hash_ops, "key 1", val1)); + ASSERT_STREQ(hashmap_get(m, "key 1"), "val1"); + + ASSERT_OK(hashmap_ensure_replace(&m, &string_hash_ops, "key 2", val2)); + ASSERT_STREQ(hashmap_get(m, "key 2"), "val2"); + + ASSERT_OK(hashmap_ensure_replace(&m, &string_hash_ops, "key 3", val1)); + ASSERT_STREQ(hashmap_get(m, "key 3"), "val1"); + + ASSERT_OK(hashmap_ensure_replace(&m, &string_hash_ops, "key 3", val2)); + ASSERT_STREQ(hashmap_get(m, "key 3"), "val2"); +} + TEST(hashmap_copy) { _cleanup_hashmap_free_ Hashmap *m = NULL; _cleanup_hashmap_free_free_ Hashmap *copy = NULL; -- 2.47.3