basic/hashmap: add hashops variant that does strdup/freeing on its own
So far, we'd use hashmap_free_free to free both keys and values along with the hashmap. I think it's better to make this more encapsulated: in this variant the way contents are freed can be decided when the hashmap is created, and users of the hashmap can always use hashmap_free.
This commit is contained in:
parent
0bf2c5e5ec
commit
87da87846d
|
@ -10,6 +10,9 @@ void string_hash_func(const char *p, struct siphash *state) {
|
|||
}
|
||||
|
||||
DEFINE_HASH_OPS(string_hash_ops, char, string_hash_func, string_compare_func);
|
||||
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
|
||||
char, string_hash_func, string_compare_func, free,
|
||||
char, free);
|
||||
|
||||
void path_hash_func(const char *q, struct siphash *state) {
|
||||
size_t n;
|
||||
|
|
|
@ -76,6 +76,7 @@ struct hash_ops {
|
|||
void string_hash_func(const char *p, struct siphash *state);
|
||||
#define string_compare_func strcmp
|
||||
extern const struct hash_ops string_hash_ops;
|
||||
extern const struct hash_ops string_hash_ops_free_free;
|
||||
|
||||
void path_hash_func(const char *p, struct siphash *state);
|
||||
int path_compare_func(const char *a, const char *b) _pure_;
|
||||
|
|
|
@ -1768,6 +1768,32 @@ int set_consume(Set *s, void *value) {
|
|||
return r;
|
||||
}
|
||||
|
||||
int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
|
||||
int r;
|
||||
|
||||
r = hashmap_ensure_allocated(h, &string_hash_ops_free_free);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *kdup = NULL, *vdup = NULL;
|
||||
kdup = strdup(k);
|
||||
vdup = strdup(v);
|
||||
if (!kdup || !vdup)
|
||||
return -ENOMEM;
|
||||
|
||||
r = hashmap_put(*h, kdup, vdup);
|
||||
if (r < 0) {
|
||||
if (r == -EEXIST && streq(v, hashmap_get(*h, kdup)))
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(r > 0); /* 0 would mean vdup is already in the hashmap, which cannot be */
|
||||
kdup = vdup = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_put_strdup(Set *s, const char *p) {
|
||||
char *c;
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@ static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *
|
|||
return hashmap_put(PLAIN_HASHMAP(h), key, value);
|
||||
}
|
||||
|
||||
int hashmap_put_strdup(Hashmap **h, const char *k, const char *v);
|
||||
|
||||
int hashmap_update(Hashmap *h, const void *key, void *value);
|
||||
static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
|
||||
return hashmap_update(PLAIN_HASHMAP(h), key, value);
|
||||
|
|
|
@ -978,6 +978,33 @@ static void test_hashmap_reserve(void) {
|
|||
assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM);
|
||||
}
|
||||
|
||||
static void test_string_strv_hashmap(void) {
|
||||
_cleanup_hashmap_free_ Hashmap *m = NULL;
|
||||
char **s;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 1);
|
||||
assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
|
||||
assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 1);
|
||||
assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 0);
|
||||
assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0);
|
||||
assert_se(hashmap_contains(m, "foo"));
|
||||
|
||||
s = hashmap_get(m, "foo");
|
||||
assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
|
||||
|
||||
assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 1);
|
||||
assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
|
||||
assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 1);
|
||||
assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 0);
|
||||
assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0);
|
||||
assert_se(hashmap_contains(m, "xxx"));
|
||||
|
||||
s = hashmap_get(m, "xxx");
|
||||
assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
|
||||
}
|
||||
|
||||
void test_hashmap_funcs(void) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
@ -1012,4 +1039,5 @@ void test_hashmap_funcs(void) {
|
|||
test_hashmap_clear_free_free();
|
||||
test_hashmap_clear_free_with_destructor();
|
||||
test_hashmap_reserve();
|
||||
test_string_strv_hashmap();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue