X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fbasic%2Fhashmap.c;h=289c2ad2c354f340704aee7538d108661d377c3c;hb=349cc4a507c4d84fcadf61f42159ea6412717896;hp=dcd8ae412d1b9013f4e1676f979934deb3a1caf1;hpb=599601a4b9e11951ec6ea1dc33262a87f3c12bc9;p=thirdparty%2Fsystemd.git diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index dcd8ae412d1..289c2ad2c35 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -36,7 +34,7 @@ #include "strv.h" #include "util.h" -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP #include #include "list.h" #endif @@ -144,7 +142,7 @@ typedef uint8_t dib_raw_t; #define DIB_FREE UINT_MAX -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP struct hashmap_debug_info { LIST_FIELDS(struct hashmap_debug_info, debug_list); unsigned max_entries; /* high watermark of n_entries */ @@ -178,7 +176,7 @@ enum HashmapType { }; struct _packed_ indirect_storage { - char *storage; /* where buckets and DIBs are stored */ + void *storage; /* where buckets and DIBs are stored */ uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */ unsigned n_entries; /* number of stored entries */ @@ -195,7 +193,7 @@ struct direct_storage { /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit. * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit, * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */ - char storage[sizeof(struct indirect_storage)]; + uint8_t storage[sizeof(struct indirect_storage)]; }; #define DIRECT_BUCKETS(entry_t) \ @@ -304,7 +302,7 @@ static void n_entries_dec(HashmapBase *h) { h->n_direct_entries--; } -static char *storage_ptr(HashmapBase *h) { +static void *storage_ptr(HashmapBase *h) { return h->has_indirect ? h->indirect.storage : h->direct.storage; } @@ -349,7 +347,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { return (struct hashmap_base_entry*) - (storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); + ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); } static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { @@ -383,7 +381,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_ static dib_raw_t *dib_raw_ptr(HashmapBase *h) { return (dib_raw_t*) - (storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); + ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); } static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) { @@ -501,7 +499,7 @@ static void base_remove_entry(HashmapBase *h, unsigned idx) { dibs = dib_raw_ptr(h); assert(dibs[idx] != DIB_RAW_FREE); -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP h->debug.rem_count++; h->debug.last_rem_idx = idx; #endif @@ -580,7 +578,7 @@ static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator * assert(e->p.b.key == i->next_key); } -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP i->prev_idx = idx; #endif @@ -637,7 +635,7 @@ static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) { } idx = i->idx; -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP i->prev_idx = idx; #endif @@ -660,7 +658,7 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) { return IDX_NIL; } -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP if (i->idx == IDX_FIRST) { i->put_count = h->debug.put_count; i->rem_count = h->debug.rem_count; @@ -752,7 +750,7 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu shared_hash_key_initialized= true; } -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP h->debug.func = func; h->debug.file = file; h->debug.line = line; @@ -809,7 +807,7 @@ static void hashmap_free_no_clear(HashmapBase *h) { assert(!h->has_indirect); assert(!h->n_direct_entries); -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0); LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug); assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); @@ -921,7 +919,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx, dib_raw_t raw_dib, *dibs; unsigned dib, distance; -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP h->debug.put_count++; #endif @@ -929,7 +927,7 @@ static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx, for (distance = 0; ; distance++) { raw_dib = dibs[idx]; - if (raw_dib == DIB_RAW_FREE || raw_dib == DIB_RAW_REHASH) { + if (IN_SET(raw_dib, DIB_RAW_FREE, DIB_RAW_REHASH)) { if (raw_dib == DIB_RAW_REHASH) bucket_move_entry(h, swap, idx, IDX_TMP); @@ -1014,7 +1012,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, assert_se(hashmap_put_robin_hood(h, idx, swap) == false); n_entries_inc(h); -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h)); #endif @@ -1030,7 +1028,7 @@ static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, */ static int resize_buckets(HashmapBase *h, unsigned entries_add) { struct swap_entries swap; - char *new_storage; + void *new_storage; dib_raw_t *old_dibs, *new_dibs; const struct hashmap_type_info *hi; unsigned idx, optimal_idx; @@ -1097,7 +1095,7 @@ static int resize_buckets(HashmapBase *h, unsigned entries_add) { h->indirect.n_buckets = (1U << new_shift) / (hi->entry_size + sizeof(dib_raw_t)); - old_dibs = (dib_raw_t*)(new_storage + hi->entry_size * old_n_buckets); + old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets); new_dibs = dib_raw_ptr(h); /* @@ -1242,7 +1240,7 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) { idx = bucket_scan(h, hash, key); if (idx != IDX_NIL) { e = plain_bucket_at(h, idx); -#ifdef ENABLE_DEBUG_HASHMAP +#if ENABLE_DEBUG_HASHMAP /* Although the key is equal, the key pointer may have changed, * and this would break our assumption for iterating. So count * this operation as incompatible with iteration. */ @@ -1766,6 +1764,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { int set_consume(Set *s, void *value) { int r; + assert(s); + assert(value); + r = set_put(s, value); if (r <= 0) free(value); @@ -1775,26 +1776,26 @@ int set_consume(Set *s, void *value) { int set_put_strdup(Set *s, const char *p) { char *c; - int r; assert(s); assert(p); + if (set_contains(s, (char*) p)) + return 0; + c = strdup(p); if (!c) return -ENOMEM; - r = set_consume(s, c); - if (r == -EEXIST) - return 0; - - return r; + return set_consume(s, c); } int set_put_strdupv(Set *s, char **l) { int n = 0, r; char **i; + assert(s); + STRV_FOREACH(i, l) { r = set_put_strdup(s, *i); if (r < 0) @@ -1805,3 +1806,23 @@ int set_put_strdupv(Set *s, char **l) { return n; } + +int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) { + const char *p = v; + int r; + + assert(s); + assert(v); + + for (;;) { + char *word; + + r = extract_first_word(&p, &word, separators, flags); + if (r <= 0) + return r; + + r = set_consume(s, word); + if (r < 0) + return r; + } +}