GNUnet  0.10.x
container_multishortmap.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2008, 2012 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 
29 #define LOG(kind, ...) \
30  GNUNET_log_from (kind, "util-container-multishortmap", __VA_ARGS__)
31 
38 #define NEXT_CACHE_SIZE 16
39 
40 
44 struct BigMapEntry
45 {
46 
50  void *value;
51 
55  struct BigMapEntry *next;
56 
61 };
62 
63 
67 struct SmallMapEntry
68 {
69 
73  void *value;
74 
78  struct SmallMapEntry *next;
79 
83  const struct GNUNET_ShortHashCode *key;
84 };
85 
86 
90 union MapEntry
91 {
95  struct SmallMapEntry *sme;
96 
100  struct BigMapEntry *bme;
101 };
102 
103 
108 {
112  union MapEntry *map;
113 
117  unsigned int size;
118 
122  unsigned int map_length;
123 
129 
134  unsigned int modification_counter;
135 
141  union MapEntry next_cache[NEXT_CACHE_SIZE];
142 
147  unsigned int next_cache_off;
148 };
149 
150 
156 {
160  union MapEntry me;
161 
165  unsigned int idx;
166 
171  unsigned int modification_counter;
172 
177 };
178 
179 
196 GNUNET_CONTAINER_multishortmap_create (unsigned int len, int do_not_copy_keys)
197 {
199 
200  GNUNET_assert (len > 0);
202  map->map = GNUNET_malloc_large (len * sizeof (union MapEntry));
203  if (NULL == map->map)
204  {
205  GNUNET_free (map);
206  return NULL;
207  }
208  map->map_length = len;
209  map->use_small_entries = do_not_copy_keys;
210  return map;
211 }
212 
213 
220 void
223 {
224  GNUNET_assert (0 == map->next_cache_off);
225  for (unsigned int i = 0; i < map->map_length; i++)
226  {
227  union MapEntry me;
228 
229  me = map->map[i];
230  if (map->use_small_entries)
231  {
232  struct SmallMapEntry *sme;
233  struct SmallMapEntry *nxt;
234 
235  nxt = me.sme;
236  while (NULL != (sme = nxt))
237  {
238  nxt = sme->next;
239  GNUNET_free (sme);
240  }
241  me.sme = NULL;
242  }
243  else
244  {
245  struct BigMapEntry *bme;
246  struct BigMapEntry *nxt;
247 
248  nxt = me.bme;
249  while (NULL != (bme = nxt))
250  {
251  nxt = bme->next;
252  GNUNET_free (bme);
253  }
254  me.bme = NULL;
255  }
256  }
257  GNUNET_free (map->map);
258  GNUNET_free (map);
259 }
260 
261 
269 static unsigned int
271  const struct GNUNET_ShortHashCode *key)
272 {
273  unsigned int kx;
274 
275  GNUNET_assert (NULL != map);
276  GNUNET_memcpy (&kx, key, sizeof (kx));
277  return kx % map->map_length;
278 }
279 
280 
287 unsigned int
289  const struct GNUNET_CONTAINER_MultiShortmap *map)
290 {
291  return map->size;
292 }
293 
294 
305 void *
307  const struct GNUNET_CONTAINER_MultiShortmap *map,
308  const struct GNUNET_ShortHashCode *key)
309 {
310  union MapEntry me;
311 
312  me = map->map[idx_of (map, key)];
313  if (map->use_small_entries)
314  {
315  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
316  if (0 == GNUNET_memcmp (key, sme->key))
317  return sme->value;
318  }
319  else
320  {
321  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
322  if (0 == GNUNET_memcmp (key, &bme->key))
323  return bme->value;
324  }
325  return NULL;
326 }
327 
328 
338 int
342  void *it_cls)
343 {
344  int count;
345  union MapEntry me;
346  union MapEntry *ce;
347  struct GNUNET_ShortHashCode kc;
348 
349  count = 0;
350  GNUNET_assert (NULL != map);
351  ce = &map->next_cache[map->next_cache_off];
353  for (unsigned int i = 0; i < map->map_length; i++)
354  {
355  me = map->map[i];
356  if (map->use_small_entries)
357  {
358  struct SmallMapEntry *sme;
359 
360  ce->sme = me.sme;
361  while (NULL != (sme = ce->sme))
362  {
363  ce->sme = sme->next;
364  if ((NULL != it) && (GNUNET_OK != it (it_cls, sme->key, sme->value)))
365  {
367  return GNUNET_SYSERR;
368  }
369  count++;
370  }
371  }
372  else
373  {
374  struct BigMapEntry *bme;
375 
376  ce->bme = me.bme;
377  while (NULL != (bme = ce->bme))
378  {
379  ce->bme = bme->next;
380  if (NULL != it)
381  {
382  kc = bme->key;
383  if (GNUNET_OK != it (it_cls, &kc, bme->value))
384  {
386  return GNUNET_SYSERR;
387  }
388  }
389  count++;
390  }
391  }
392  }
394  return count;
395 }
396 
397 
405 static void
407  const struct BigMapEntry *bme)
408 {
409  for (unsigned int i = 0; i < map->next_cache_off; i++)
410  if (map->next_cache[i].bme == bme)
411  map->next_cache[i].bme = bme->next;
412 }
413 
414 
422 static void
424  const struct SmallMapEntry *sme)
425 {
426  for (unsigned int i = 0; i < map->next_cache_off; i++)
427  if (map->next_cache[i].sme == sme)
428  map->next_cache[i].sme = sme->next;
429 }
430 
431 
443 int
446  const struct GNUNET_ShortHashCode *key,
447  const void *value)
448 {
449  union MapEntry me;
450  unsigned int i;
451 
452  map->modification_counter++;
453  i = idx_of (map, key);
454  me = map->map[i];
455  if (map->use_small_entries)
456  {
457  struct SmallMapEntry *p = NULL;
458 
459  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
460  {
461  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
462  {
463  if (NULL == p)
464  map->map[i].sme = sme->next;
465  else
466  p->next = sme->next;
467  update_next_cache_sme (map, sme);
468  GNUNET_free (sme);
469  map->size--;
470  return GNUNET_YES;
471  }
472  p = sme;
473  }
474  }
475  else
476  {
477  struct BigMapEntry *p = NULL;
478 
479  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
480  {
481  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
482  {
483  if (NULL == p)
484  map->map[i].bme = bme->next;
485  else
486  p->next = bme->next;
487  update_next_cache_bme (map, bme);
488  GNUNET_free (bme);
489  map->size--;
490  return GNUNET_YES;
491  }
492  p = bme;
493  }
494  }
495  return GNUNET_NO;
496 }
497 
498 
507 int
510  const struct GNUNET_ShortHashCode *key)
511 {
512  union MapEntry me;
513  unsigned int i;
514  int ret;
515 
516  map->modification_counter++;
517 
518  ret = 0;
519  i = idx_of (map, key);
520  me = map->map[i];
521  if (map->use_small_entries)
522  {
523  struct SmallMapEntry *sme;
524  struct SmallMapEntry *p;
525 
526  p = NULL;
527  sme = me.sme;
528  while (NULL != sme)
529  {
530  if (0 == GNUNET_memcmp (key, sme->key))
531  {
532  if (NULL == p)
533  map->map[i].sme = sme->next;
534  else
535  p->next = sme->next;
536  update_next_cache_sme (map, sme);
537  GNUNET_free (sme);
538  map->size--;
539  if (NULL == p)
540  sme = map->map[i].sme;
541  else
542  sme = p->next;
543  ret++;
544  }
545  else
546  {
547  p = sme;
548  sme = sme->next;
549  }
550  }
551  }
552  else
553  {
554  struct BigMapEntry *bme;
555  struct BigMapEntry *p;
556 
557  p = NULL;
558  bme = me.bme;
559  while (NULL != bme)
560  {
561  if (0 == GNUNET_memcmp (key, &bme->key))
562  {
563  if (NULL == p)
564  map->map[i].bme = bme->next;
565  else
566  p->next = bme->next;
567  update_next_cache_bme (map, bme);
568  GNUNET_free (bme);
569  map->size--;
570  if (NULL == p)
571  bme = map->map[i].bme;
572  else
573  bme = p->next;
574  ret++;
575  }
576  else
577  {
578  p = bme;
579  bme = bme->next;
580  }
581  }
582  }
583  return ret;
584 }
585 
586 
596 int
598  const struct GNUNET_CONTAINER_MultiShortmap *map,
599  const struct GNUNET_ShortHashCode *key)
600 {
601  union MapEntry me;
602 
603  me = map->map[idx_of (map, key)];
604  if (map->use_small_entries)
605  {
606  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
607  if (0 == GNUNET_memcmp (key, sme->key))
608  return GNUNET_YES;
609  }
610  else
611  {
612  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
613  if (0 == GNUNET_memcmp (key, &bme->key))
614  return GNUNET_YES;
615  }
616  return GNUNET_NO;
617 }
618 
619 
630 int
632  const struct GNUNET_CONTAINER_MultiShortmap *map,
633  const struct GNUNET_ShortHashCode *key,
634  const void *value)
635 {
636  union MapEntry me;
637 
638  me = map->map[idx_of (map, key)];
639  if (map->use_small_entries)
640  {
641  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
642  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
643  return GNUNET_YES;
644  }
645  else
646  {
647  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
648  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
649  return GNUNET_YES;
650  }
651  return GNUNET_NO;
652 }
653 
654 
660 static void
662 {
663  union MapEntry *old_map;
664  union MapEntry *new_map;
665  unsigned int old_len;
666  unsigned int new_len;
667  unsigned int idx;
668 
669  old_map = map->map;
670  old_len = map->map_length;
671  new_len = old_len * 2;
672  if (0 == new_len) /* 2^31 * 2 == 0 */
673  new_len = old_len; /* never use 0 */
674  if (new_len == old_len)
675  return; /* nothing changed */
676  new_map = GNUNET_malloc_large (new_len * sizeof (union MapEntry));
677  if (NULL == new_map)
678  return; /* grow not possible */
679  map->modification_counter++;
680  map->map_length = new_len;
681  map->map = new_map;
682  for (unsigned int i = 0; i < old_len; i++)
683  {
684  if (map->use_small_entries)
685  {
686  struct SmallMapEntry *sme;
687 
688  while (NULL != (sme = old_map[i].sme))
689  {
690  old_map[i].sme = sme->next;
691  idx = idx_of (map, sme->key);
692  sme->next = new_map[idx].sme;
693  new_map[idx].sme = sme;
694  }
695  }
696  else
697  {
698  struct BigMapEntry *bme;
699 
700  while (NULL != (bme = old_map[i].bme))
701  {
702  old_map[i].bme = bme->next;
703  idx = idx_of (map, &bme->key);
704  bme->next = new_map[idx].bme;
705  new_map[idx].bme = bme;
706  }
707  }
708  }
709  GNUNET_free (old_map);
710 }
711 
712 
725 int
728  const struct GNUNET_ShortHashCode *key,
729  void *value,
731 {
732  union MapEntry me;
733  unsigned int i;
734 
735  i = idx_of (map, key);
738  {
739  me = map->map[i];
740  if (map->use_small_entries)
741  {
742  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
743  if (0 == GNUNET_memcmp (key, sme->key))
744  {
746  return GNUNET_SYSERR;
747  sme->value = value;
748  return GNUNET_NO;
749  }
750  }
751  else
752  {
753  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
754  if (0 == GNUNET_memcmp (key, &bme->key))
755  {
757  return GNUNET_SYSERR;
758  bme->value = value;
759  return GNUNET_NO;
760  }
761  }
762  }
763  if (map->size / 3 >= map->map_length / 4)
764  {
765  grow (map);
766  i = idx_of (map, key);
767  }
768  if (map->use_small_entries)
769  {
770  struct SmallMapEntry *sme;
771 
772  sme = GNUNET_new (struct SmallMapEntry);
773  sme->key = key;
774  sme->value = value;
775  sme->next = map->map[i].sme;
776  map->map[i].sme = sme;
777  }
778  else
779  {
780  struct BigMapEntry *bme;
781 
782  bme = GNUNET_new (struct BigMapEntry);
783  bme->key = *key;
784  bme->value = value;
785  bme->next = map->map[i].bme;
786  map->map[i].bme = bme;
787  }
788  map->size++;
789  return GNUNET_OK;
790 }
791 
792 
803 int
806  const struct GNUNET_ShortHashCode *key,
808  void *it_cls)
809 {
810  int count;
811  union MapEntry me;
812  union MapEntry *ce;
813 
814  ce = &map->next_cache[map->next_cache_off];
816  count = 0;
817  me = map->map[idx_of (map, key)];
818  if (map->use_small_entries)
819  {
820  struct SmallMapEntry *sme;
821 
822  ce->sme = me.sme;
823  while (NULL != (sme = ce->sme))
824  {
825  ce->sme = sme->next;
826  if (0 != GNUNET_memcmp (key, sme->key))
827  continue;
828  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
829  {
831  return GNUNET_SYSERR;
832  }
833  count++;
834  }
835  }
836  else
837  {
838  struct BigMapEntry *bme;
839 
840  ce->bme = me.bme;
841  while (NULL != (bme = ce->bme))
842  {
843  ce->bme = bme->next;
844  if (0 != GNUNET_memcmp (key, &bme->key))
845  continue;
846  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
847  {
849  return GNUNET_SYSERR;
850  }
851  count++;
852  }
853  }
855  return count;
856 }
857 
858 
870 unsigned int
872  const struct GNUNET_CONTAINER_MultiShortmap *map,
874  void *it_cls)
875 {
876  unsigned int off;
877  union MapEntry me;
878 
879  if (0 == map->size)
880  return 0;
881  if (NULL == it)
882  return 1;
884  for (unsigned int idx = 0; idx < map->map_length; idx++)
885  {
886  me = map->map[idx];
887  if (map->use_small_entries)
888  {
889  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
890  {
891  if (0 == off)
892  {
893  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
894  return GNUNET_SYSERR;
895  return 1;
896  }
897  off--;
898  }
899  }
900  else
901  {
902  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
903  {
904  if (0 == off)
905  {
906  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
907  return GNUNET_SYSERR;
908  return 1;
909  }
910  off--;
911  }
912  }
913  }
914  GNUNET_break (0);
915  return GNUNET_SYSERR;
916 }
917 
918 
933  const struct GNUNET_CONTAINER_MultiShortmap *map)
934 {
936 
938  iter->map = map;
940  iter->me = map->map[0];
941  return iter;
942 }
943 
944 
959 int
962  struct GNUNET_ShortHashCode *key,
963  const void **value)
964 {
965  /* make sure the map has not been modified */
967 
968  /* look for the next entry, skipping empty buckets */
969  while (1)
970  {
971  if (iter->idx >= iter->map->map_length)
972  return GNUNET_NO;
973  if (GNUNET_YES == iter->map->use_small_entries)
974  {
975  if (NULL != iter->me.sme)
976  {
977  if (NULL != key)
978  *key = *iter->me.sme->key;
979  if (NULL != value)
980  *value = iter->me.sme->value;
981  iter->me.sme = iter->me.sme->next;
982  return GNUNET_YES;
983  }
984  }
985  else
986  {
987  if (NULL != iter->me.bme)
988  {
989  if (NULL != key)
990  *key = iter->me.bme->key;
991  if (NULL != value)
992  *value = iter->me.bme->value;
993  iter->me.bme = iter->me.bme->next;
994  return GNUNET_YES;
995  }
996  }
997  iter->idx += 1;
998  if (iter->idx < iter->map->map_length)
999  iter->me = iter->map->map[iter->idx];
1000  }
1001 }
1002 
1003 
1009 void
1012 {
1013  GNUNET_free (iter);
1014 }
1015 
1016 
1017 /* end of container_multishortmap.c */
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
GNUNET_CONTAINER_MultiHashMapOption
Options for storing values in the HashMap.
struct SmallMapEntry * next
If there is a hash collision, we create a linked list.
unsigned int map_length
Length of the "map" array.
unsigned int modification_counter
Modification counter as observed on the map when the iterator was created.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
void * value
Value of the entry.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int GNUNET_CONTAINER_multishortmap_get_random(const struct GNUNET_CONTAINER_MultiShortmap *map, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Call it on a random value from the map, or not at all if the map is empty.
union MapEntry me
Position in the bucket &#39;idx&#39;.
int GNUNET_CONTAINER_multishortmap_get_multiple(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
unsigned int idx
Current bucket index.
const struct GNUNET_HashCode * key
Key for the entry.
void GNUNET_CONTAINER_multishortmap_iterator_destroy(struct GNUNET_CONTAINER_MultiShortmapIterator *iter)
Destroy a multishortmap iterator.
#define GNUNET_NO
Definition: gnunet_common.h:81
void * value
Value of the entry.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void update_next_cache_bme(struct GNUNET_CONTAINER_MultiShortmap *map, const struct BigMapEntry *bme)
We are about to free() the bme, make sure it is not in the list of next values for any iterator in th...
const struct GNUNET_CONTAINER_MultiShortmap * map
Map that we are iterating over.
struct SmallMapEntry * sme
Variant used if map entries only contain a pointer to the key.
int(* GNUNET_CONTAINER_ShortmapIterator)(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
Iterator over hash map entries.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_malloc_large(size)
Wrapper around malloc.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct BigMapEntry * next
If there is a hash collision, we create a linked list.
A 256-bit hashcode.
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
int GNUNET_CONTAINER_multishortmap_iterate(struct GNUNET_CONTAINER_MultiShortmap *map, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Iterate over all entries in the map.
static unsigned int idx_of(const struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key)
Compute the index of the bucket for the given key.
Entry in the map.
unsigned int size
Number of entries in the map.
Randomness for IVs etc.
int GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static void grow(struct GNUNET_CONTAINER_MultiShortmap *map)
Grow the given map to a more appropriate size.
struct GNUNET_CONTAINER_MultiShortmapIterator * GNUNET_CONTAINER_multishortmap_iterator_create(const struct GNUNET_CONTAINER_MultiShortmap *map)
Create an iterator for a multishortmap.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multishortmap_remove_all(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key)
Remove all entries for the given key from the map.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int use_small_entries
GNUNET_NO if the map entries are of type &#39;struct BigMapEntry&#39;, GNUNET_YES if the map entries are of t...
unsigned int next_cache_off
Offset of next_cache entries in use, must be smaller than NEXT_CACHE_SIZE.
Internal representation of the hash map.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
const struct GNUNET_ShortHashCode * key
Key for the entry.
#define NEXT_CACHE_SIZE
Maximum recursion depth for callbacks of GNUNET_CONTAINER_multihashmap_get_multiple() themselve s aga...
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
Allow multiple values with the same key.
unsigned int modification_counter
Counts the destructive modifications (grow, remove) to the map, so that iterators can check if they a...
An entry in the hash map with just a pointer to the key.
union MapEntry next_cache[16]
Map entries indicating iteration positions currently in use by GNUNET_CONTAINER_multihashmap_get_mult...
void * GNUNET_CONTAINER_multishortmap_get(const struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key)
Given a key find a value in the map matching the key.
An entry in the hash map with the full key.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct BigMapEntry * bme
Variant used if map entries contain the full key.
static void update_next_cache_sme(struct GNUNET_CONTAINER_MultiShortmap *map, const struct SmallMapEntry *sme)
We are about to free() the sme, make sure it is not in the list of next values for any iterator in th...
int GNUNET_CONTAINER_multishortmap_contains(const struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key)
Check if the map contains any value under the given key (including values that are NULL)...
int GNUNET_CONTAINER_multishortmap_contains_value(const struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Check if the map contains the given value under the given key.
int GNUNET_CONTAINER_multishortmap_iterator_next(struct GNUNET_CONTAINER_MultiShortmapIterator *iter, struct GNUNET_ShortHashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator&#39;s position.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_HashCode key
Key for the entry.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
union MapEntry * map
All of our buckets.