X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fcontainer_multihashmap32.c;h=4cc9b7ebd3985e9632c8a0a420b8f32b2cdbdd18;hb=ed28dd2141e77aa073d81089cb5a07e0a0fc013c;hp=29ad14d3abcdb04634cc55e6d7ecafa106a2c159;hpb=c886c53017f31d76c22f5ed55df61719b71ef87a;p=oweals%2Fgnunet.git diff --git a/src/util/container_multihashmap32.c b/src/util/container_multihashmap32.c index 29ad14d3a..4cc9b7ebd 100644 --- a/src/util/container_multihashmap32.c +++ b/src/util/container_multihashmap32.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2008 Christian Grothoff (and other contributing authors) + Copyright (C) 2008 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** * @file util/container_multihashmap32.c @@ -26,9 +26,7 @@ */ #include "platform.h" -#include "gnunet_common.h" #include "gnunet_container_lib.h" -#include "gnunet_crypto_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) @@ -75,6 +73,41 @@ struct GNUNET_CONTAINER_MultiHashMap32 * Length of the "map" array. */ unsigned int map_length; + + /** + * Counts the destructive modifications (grow, remove) + * to the map, so that iterators can check if they are still valid. + */ + unsigned int modification_counter; +}; + + +/** + * Cursor into a multihashmap. + * Allows to enumerate elements asynchronously. + */ +struct GNUNET_CONTAINER_MultiHashMap32Iterator +{ + /** + * Position in the bucket 'idx' + */ + struct MapEntry *me; + + /** + * Current bucket index. + */ + unsigned int idx; + + /** + * Modification counter as observed on the map when the iterator + * was created. + */ + unsigned int modification_counter; + + /** + * Map that we are iterating over. + */ + const struct GNUNET_CONTAINER_MultiHashMap32 *map; }; @@ -186,9 +219,9 @@ GNUNET_CONTAINER_multihashmap32_get (const struct * * @param map the map * @param it function to call on each entry - * @param it_cls extra argument to it + * @param it_cls extra argument to @a it * @return the number of key value pairs processed, - * GNUNET_SYSERR if it aborted iteration + * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap32_iterate (const struct @@ -202,7 +235,7 @@ GNUNET_CONTAINER_multihashmap32_iterate (const struct struct MapEntry *n; count = 0; - GNUNET_assert (map != NULL); + GNUNET_assert (NULL != map); for (i = 0; i < map->map_length; i++) { n = map->map[i]; @@ -241,6 +274,8 @@ GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 struct MapEntry *p; unsigned int i; + map->modification_counter++; + i = idx_of (map, key); p = NULL; e = map->map[i]; @@ -282,6 +317,8 @@ GNUNET_CONTAINER_multihashmap32_remove_all (struct unsigned int i; int ret; + map->modification_counter++; + ret = 0; i = idx_of (map, key); p = NULL; @@ -352,7 +389,7 @@ GNUNET_CONTAINER_multihashmap32_contains (const struct int GNUNET_CONTAINER_multihashmap32_contains_value (const struct GNUNET_CONTAINER_MultiHashMap32 - *map, + *map, uint32_t key, const void *value) { @@ -385,6 +422,8 @@ grow (struct GNUNET_CONTAINER_MultiHashMap32 *map) unsigned int idx; unsigned int i; + map->modification_counter++; + old_map = map->map; old_len = map->map_length; new_len = old_len * 2; @@ -472,7 +511,7 @@ int GNUNET_CONTAINER_multihashmap32_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, - GNUNET_CONTAINER_HashMapIterator32 + GNUNET_CONTAINER_HashMapIterator32 it, void *it_cls) { int count; @@ -494,4 +533,84 @@ GNUNET_CONTAINER_multihashmap32_get_multiple (const struct } +/** + * Create an iterator for a multihashmap. + * The iterator can be used to retrieve all the elements in the multihashmap + * one by one, without having to handle all elements at once (in contrast to + * GNUNET_CONTAINER_multihashmap_iterate()). Note that the iterator can not be + * used anymore if elements have been removed from 'map' after the creation of + * the iterator, or 'map' has been destroyed. Adding elements to 'map' may + * result in skipped or repeated elements. + * + * @param map the map to create an iterator for + * @return an iterator over the given multihashmap 'map' + */ +struct GNUNET_CONTAINER_MultiHashMap32Iterator * +GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map) +{ + struct GNUNET_CONTAINER_MultiHashMap32Iterator *iter; + + iter = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap32Iterator); + iter->map = map; + iter->modification_counter = map->modification_counter; + iter->me = map->map[0]; + return iter; +} + + +/** + * Retrieve the next element from the hash map at the iterator's position. + * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' + * are not modified. + * This operation is only allowed if no elements have been removed from the + * multihashmap since the creation of 'iter', and the map has not been destroyed. + * Adding elements may result in repeating or skipping elements. + * + * @param iter the iterator to get the next element from + * @param key pointer to store the key in, can be NULL + * @param value pointer to store the value in, can be NULL + * @return #GNUNET_YES we returned an element, + * #GNUNET_NO if we are out of elements + */ +int +GNUNET_CONTAINER_multihashmap32_iterator_next (struct GNUNET_CONTAINER_MultiHashMap32Iterator *iter, + uint32_t *key, + const void **value) +{ + /* make sure the map has not been modified */ + GNUNET_assert (iter->modification_counter == iter->map->modification_counter); + + /* look for the next entry, skipping empty buckets */ + while (1) + { + if (iter->idx >= iter->map->map_length) + return GNUNET_NO; + if (NULL != iter->me) + { + if (NULL != key) + *key = iter->me->key; + if (NULL != value) + *value = iter->me->value; + iter->me = iter->me->next; + return GNUNET_YES; + } + iter->idx += 1; + if (iter->idx < iter->map->map_length) + iter->me = iter->map->map[iter->idx]; + } +} + + +/** + * Destroy a multihashmap iterator. + * + * @param iter the iterator to destroy + */ +void +GNUNET_CONTAINER_multihashmap32_iterator_destroy (struct GNUNET_CONTAINER_MultiHashMapIterator *iter) +{ + GNUNET_free (iter); +} + + /* end of container_multihashmap.c */