make libextractor actually optional, both for GNUnet and GNUnet-taler builds
[oweals/gnunet.git] / src / util / container_multihashmap.c
index 567ee12516dde93f97081103944d4c614856f25c..46379b34efe2d8a62f029863423a1c98715ac7d4 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2008, 2012 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2008, 2012 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -24,7 +24,7 @@
  */
 
 #include "platform.h"
-#include "gnunet_util_lib.h"
+#include "gnunet_container_lib.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
@@ -275,8 +275,8 @@ GNUNET_CONTAINER_multihashmap_size (const struct GNUNET_CONTAINER_MultiHashMap
  *   key-value pairs with value NULL
  */
 void *
-GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap
-                                   *map, const struct GNUNET_HashCode *key)
+GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *map,
+                                   const struct GNUNET_HashCode *key)
 {
   union MapEntry me;
 
@@ -446,8 +446,8 @@ GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map,
  * @return number of values removed
  */
 int
-GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap
-                                          *map, const struct GNUNET_HashCode *key)
+GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap *map,
+                                          const struct GNUNET_HashCode *key)
 {
   union MapEntry me;
   unsigned int i;
@@ -522,6 +522,49 @@ GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap
 }
 
 
+/**
+ * Callback used to remove all entries from the map.
+ *
+ * @param cls the `struct GNUNET_CONTAINER_MultiHashMap`
+ * @param key the key
+ * @param value the value
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+remove_all (void *cls,
+            const struct GNUNET_HashCode *key,
+            void *value)
+{
+  struct GNUNET_CONTAINER_MultiHashMap *map = cls;
+
+  GNUNET_CONTAINER_multihashmap_remove (map,
+                                        key,
+                                        value);
+  return GNUNET_OK;
+}
+
+
+/**
+ * @ingroup hashmap
+ * Remove all entries from the map.
+ * Note that the values would not be "freed".
+ *
+ * @param map the map
+ * @return number of values removed
+ */
+unsigned int
+GNUNET_CONTAINER_multihashmap_clear (struct GNUNET_CONTAINER_MultiHashMap *map)
+{
+  unsigned int ret;
+
+  ret = map->size;
+  GNUNET_CONTAINER_multihashmap_iterate (map,
+                                         &remove_all,
+                                         map);
+  return ret;
+}
+
+
 /**
  * Check if the map contains any value under the given
  * key (including values that are NULL).
@@ -795,6 +838,80 @@ GNUNET_CONTAINER_multihashmap_get_multiple (const struct
 }
 
 
+/**
+ * @ingroup hashmap
+ * Call @a it on a random value from the map, or not at all
+ * if the map is empty. Note that this function has linear
+ * complexity (in the size of the map).
+ *
+ * @param map the map
+ * @param it function to call on a random entry
+ * @param it_cls extra argument to @a it
+ * @return the number of key value pairs processed, zero or one.
+ */
+unsigned int
+GNUNET_CONTAINER_multihashmap_get_random (const struct GNUNET_CONTAINER_MultiHashMap *map,
+                                          GNUNET_CONTAINER_HashMapIterator it,
+                                          void *it_cls)
+{
+  unsigned int off;
+  unsigned int idx;
+  union MapEntry me;
+
+  if (0 == map->size)
+    return 0;
+  if (NULL == it)
+    return 1;
+  off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                  map->size);
+  for (idx = 0; idx < map->map_length; idx++)
+  {
+    me = map->map[idx];
+    if (map->use_small_entries)
+    {
+      struct SmallMapEntry *sme;
+      struct SmallMapEntry *nxt;
+
+      nxt = me.sme;
+      while (NULL != (sme = nxt))
+      {
+        nxt = sme->next;
+        if (0 == off)
+        {
+          if (GNUNET_OK != it (it_cls,
+                               sme->key,
+                               sme->value))
+            return GNUNET_SYSERR;
+          return 1;
+        }
+        off--;
+      }
+    }
+    else
+    {
+      struct BigMapEntry *bme;
+      struct BigMapEntry *nxt;
+
+      nxt = me.bme;
+      while (NULL != (bme = nxt))
+      {
+        nxt = bme->next;
+        if (0 == off)
+        {
+          if (GNUNET_OK != it (it_cls,
+                               &bme->key, bme->value))
+            return GNUNET_SYSERR;
+          return 1;
+        }
+        off--;
+      }
+    }
+  }
+  GNUNET_break (0);
+  return GNUNET_SYSERR;
+}
+
+
 /**
  * Create an iterator for a multihashmap.
  * The iterator can be used to retrieve all the elements in the multihashmap