/*
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
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
*/
#include "platform.h"
-#include "gnunet_util_lib.h"
+#include "gnunet_container_lib.h"
#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
* 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;
};
*
* @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
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];
struct MapEntry *p;
unsigned int i;
+ map->modification_counter++;
+
i = idx_of (map, key);
p = NULL;
e = map->map[i];
unsigned int i;
int ret;
+ map->modification_counter++;
+
ret = 0;
i = idx_of (map, key);
p = NULL;
int
GNUNET_CONTAINER_multihashmap32_contains_value (const struct
GNUNET_CONTAINER_MultiHashMap32
- *map,
+ *map,
uint32_t key,
const void *value)
{
unsigned int idx;
unsigned int i;
+ map->modification_counter++;
+
old_map = map->map;
old_len = map->map_length;
new_len = old_len * 2;
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;
}
+/**
+ * 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 */