diff --git a/hashmap.c b/hashmap.c index 554b283..fa21374 100644 --- a/hashmap.c +++ b/hashmap.c @@ -408,6 +408,42 @@ bool hashmap_scan(struct hashmap *map, return true; } + +// hashmap_iter iterates one key at a time yielding a reference to an +// entry at each iteration. Useful to write simple loops and avoid writing +// dedicated callbacks and udata structures, as in hashmap_scan. +// +// map is a hash map handle. i is a pointer to a size_t cursor that +// should be initialized to 0 at the beginning of the loop. item is a void +// pointer pointer that is populated with the retrieved item. Note that this +// is NOT a copy of the item stored in the hash map and can be directly +// modified. +// +// Note that if hashmap_delete() is called on the hashmap being iterated, +// the buckets are rearranged and the iterator must be reset to 0, otherwise +// unexpected results may be returned after deletion. +// +// This function has not been tested for thread safety. +// +// The function returns true if an item was retrieved; false if the end of the +// iteration has been reached. +bool hashmap_iter(struct hashmap *map, size_t *i, void **item) +{ + struct bucket *bucket; + + do { + if (*i >= map->nbuckets) return false; + + bucket = bucket_at(map, *i); + (*i)++; + } while (!bucket->dib); + + *item = bucket_item(bucket); + + return true; +} + + //----------------------------------------------------------------------------- // SipHash reference C implementation // @@ -738,6 +774,13 @@ static void all() { while (!(vals2 = xmalloc(N * sizeof(int)))) {} memset(vals2, 0, N * sizeof(int)); assert(hashmap_scan(map, iter_ints, &vals2)); + + // Test hashmap_iter. This does the same as hashmap_scan above. + size_t iter = 0; + void *iter_val; + while (hashmap_iter (map, &iter, &iter_val)) { + assert (iter_ints(iter_val, &vals2)); + } for (int i = 0; i < N; i++) { assert(vals2[i] == 1); } diff --git a/hashmap.h b/hashmap.h index f3d6ad1..fa4a129 100644 --- a/hashmap.h +++ b/hashmap.h @@ -41,6 +41,7 @@ void *hashmap_delete(struct hashmap *map, void *item); void *hashmap_probe(struct hashmap *map, uint64_t position); bool hashmap_scan(struct hashmap *map, bool (*iter)(const void *item, void *udata), void *udata); +bool hashmap_iter(struct hashmap *map, size_t *i, void **item); uint64_t hashmap_sip(const void *data, size_t len, uint64_t seed0, uint64_t seed1);