GNUnet  0.11.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 {
49  void *value;
50 
54  struct BigMapEntry *next;
55 
60 };
61 
62 
66 struct SmallMapEntry
67 {
71  void *value;
72 
76  struct SmallMapEntry *next;
77 
81  const struct GNUNET_ShortHashCode *key;
82 };
83 
84 
88 union MapEntry
89 {
93  struct SmallMapEntry *sme;
94 
98  struct BigMapEntry *bme;
99 };
100 
101 
106 {
110  union MapEntry *map;
111 
115  unsigned int size;
116 
120  unsigned int map_length;
121 
127 
132  unsigned int modification_counter;
133 
139  union MapEntry next_cache[NEXT_CACHE_SIZE];
140 
145  unsigned int next_cache_off;
146 };
147 
148 
154 {
158  union MapEntry me;
159 
163  unsigned int idx;
164 
169  unsigned int modification_counter;
170 
175 };
176 
177 
194 GNUNET_CONTAINER_multishortmap_create (unsigned int len, int do_not_copy_keys)
195 {
197 
198  GNUNET_assert (len > 0);
200  map->map = GNUNET_malloc_large (len * sizeof(union MapEntry));
201  if (NULL == map->map)
202  {
203  GNUNET_free (map);
204  return NULL;
205  }
206  map->map_length = len;
207  map->use_small_entries = do_not_copy_keys;
208  return map;
209 }
210 
211 
218 void
221 {
222  GNUNET_assert (0 == map->next_cache_off);
223  for (unsigned int i = 0; i < map->map_length; i++)
224  {
225  union MapEntry me;
226 
227  me = map->map[i];
228  if (map->use_small_entries)
229  {
230  struct SmallMapEntry *sme;
231  struct SmallMapEntry *nxt;
232 
233  nxt = me.sme;
234  while (NULL != (sme = nxt))
235  {
236  nxt = sme->next;
237  GNUNET_free (sme);
238  }
239  me.sme = NULL;
240  }
241  else
242  {
243  struct BigMapEntry *bme;
244  struct BigMapEntry *nxt;
245 
246  nxt = me.bme;
247  while (NULL != (bme = nxt))
248  {
249  nxt = bme->next;
250  GNUNET_free (bme);
251  }
252  me.bme = NULL;
253  }
254  }
255  GNUNET_free (map->map);
256  GNUNET_free (map);
257 }
258 
259 
267 static unsigned int
269  const struct GNUNET_ShortHashCode *key)
270 {
271  unsigned int kx;
272 
273  GNUNET_assert (NULL != map);
274  GNUNET_memcpy (&kx, key, sizeof(kx));
275  return kx % map->map_length;
276 }
277 
278 
285 unsigned int
287  const struct GNUNET_CONTAINER_MultiShortmap *map)
288 {
289  return map->size;
290 }
291 
292 
303 void *
305  const struct GNUNET_CONTAINER_MultiShortmap *map,
306  const struct GNUNET_ShortHashCode *key)
307 {
308  union MapEntry me;
309 
310  me = map->map[idx_of (map, key)];
311  if (map->use_small_entries)
312  {
313  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
314  if (0 == GNUNET_memcmp (key, sme->key))
315  return sme->value;
316  }
317  else
318  {
319  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
320  if (0 == GNUNET_memcmp (key, &bme->key))
321  return bme->value;
322  }
323  return NULL;
324 }
325 
326 
336 int
340  void *it_cls)
341 {
342  int count;
343  union MapEntry me;
344  union MapEntry *ce;
345  struct GNUNET_ShortHashCode kc;
346 
347  count = 0;
348  GNUNET_assert (NULL != map);
349  ce = &map->next_cache[map->next_cache_off];
351  for (unsigned int i = 0; i < map->map_length; i++)
352  {
353  me = map->map[i];
354  if (map->use_small_entries)
355  {
356  struct SmallMapEntry *sme;
357 
358  ce->sme = me.sme;
359  while (NULL != (sme = ce->sme))
360  {
361  ce->sme = sme->next;
362  if ((NULL != it) && (GNUNET_OK != it (it_cls, sme->key, sme->value)))
363  {
365  return GNUNET_SYSERR;
366  }
367  count++;
368  }
369  }
370  else
371  {
372  struct BigMapEntry *bme;
373 
374  ce->bme = me.bme;
375  while (NULL != (bme = ce->bme))
376  {
377  ce->bme = bme->next;
378  if (NULL != it)
379  {
380  kc = bme->key;
381  if (GNUNET_OK != it (it_cls, &kc, bme->value))
382  {
384  return GNUNET_SYSERR;
385  }
386  }
387  count++;
388  }
389  }
390  }
392  return count;
393 }
394 
395 
403 static void
405  const struct BigMapEntry *bme)
406 {
407  for (unsigned int i = 0; i < map->next_cache_off; i++)
408  if (map->next_cache[i].bme == bme)
409  map->next_cache[i].bme = bme->next;
410 }
411 
412 
420 static void
422  const struct SmallMapEntry *sme)
423 {
424  for (unsigned int i = 0; i < map->next_cache_off; i++)
425  if (map->next_cache[i].sme == sme)
426  map->next_cache[i].sme = sme->next;
427 }
428 
429 
441 int
444  const struct GNUNET_ShortHashCode *key,
445  const void *value)
446 {
447  union MapEntry me;
448  unsigned int i;
449 
450  map->modification_counter++;
451  i = idx_of (map, key);
452  me = map->map[i];
453  if (map->use_small_entries)
454  {
455  struct SmallMapEntry *p = NULL;
456 
457  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
458  {
459  if ((0 == GNUNET_memcmp (key, sme->key)) && (value == sme->value))
460  {
461  if (NULL == p)
462  map->map[i].sme = sme->next;
463  else
464  p->next = sme->next;
465  update_next_cache_sme (map, sme);
466  GNUNET_free (sme);
467  map->size--;
468  return GNUNET_YES;
469  }
470  p = sme;
471  }
472  }
473  else
474  {
475  struct BigMapEntry *p = NULL;
476 
477  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
478  {
479  if ((0 == GNUNET_memcmp (key, &bme->key)) && (value == bme->value))
480  {
481  if (NULL == p)
482  map->map[i].bme = bme->next;
483  else
484  p->next = bme->next;
485  update_next_cache_bme (map, bme);
486  GNUNET_free (bme);
487  map->size--;
488  return GNUNET_YES;
489  }
490  p = bme;
491  }
492  }
493  return GNUNET_NO;
494 }
495 
496 
505 int
508  const struct GNUNET_ShortHashCode *key)
509 {
510  union MapEntry me;
511  unsigned int i;
512  int ret;
513 
514  map->modification_counter++;
515 
516  ret = 0;
517  i = idx_of (map, key);
518  me = map->map[i];
519  if (map->use_small_entries)
520  {
521  struct SmallMapEntry *sme;
522  struct SmallMapEntry *p;
523 
524  p = NULL;
525  sme = me.sme;
526  while (NULL != sme)
527  {
528  if (0 == GNUNET_memcmp (key, sme->key))
529  {
530  if (NULL == p)
531  map->map[i].sme = sme->next;
532  else
533  p->next = sme->next;
534  update_next_cache_sme (map, sme);
535  GNUNET_free (sme);
536  map->size--;
537  if (NULL == p)
538  sme = map->map[i].sme;
539  else
540  sme = p->next;
541  ret++;
542  }
543  else
544  {
545  p = sme;
546  sme = sme->next;
547  }
548  }
549  }
550  else
551  {
552  struct BigMapEntry *bme;
553  struct BigMapEntry *p;
554 
555  p = NULL;
556  bme = me.bme;
557  while (NULL != bme)
558  {
559  if (0 == GNUNET_memcmp (key, &bme->key))
560  {
561  if (NULL == p)
562  map->map[i].bme = bme->next;
563  else
564  p->next = bme->next;
565  update_next_cache_bme (map, bme);
566  GNUNET_free (bme);
567  map->size--;
568  if (NULL == p)
569  bme = map->map[i].bme;
570  else
571  bme = p->next;
572  ret++;
573  }
574  else
575  {
576  p = bme;
577  bme = bme->next;
578  }
579  }
580  }
581  return ret;
582 }
583 
584 
594 int
596  const struct GNUNET_CONTAINER_MultiShortmap *map,
597  const struct GNUNET_ShortHashCode *key)
598 {
599  union MapEntry me;
600 
601  me = map->map[idx_of (map, key)];
602  if (map->use_small_entries)
603  {
604  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
605  if (0 == GNUNET_memcmp (key, sme->key))
606  return GNUNET_YES;
607  }
608  else
609  {
610  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
611  if (0 == GNUNET_memcmp (key, &bme->key))
612  return GNUNET_YES;
613  }
614  return GNUNET_NO;
615 }
616 
617 
628 int
630  const struct GNUNET_CONTAINER_MultiShortmap *map,
631  const struct GNUNET_ShortHashCode *key,
632  const void *value)
633 {
634  union MapEntry me;
635 
636  me = map->map[idx_of (map, key)];
637  if (map->use_small_entries)
638  {
639  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
640  if ((0 == GNUNET_memcmp (key, sme->key)) && (sme->value == value))
641  return GNUNET_YES;
642  }
643  else
644  {
645  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
646  if ((0 == GNUNET_memcmp (key, &bme->key)) && (bme->value == value))
647  return GNUNET_YES;
648  }
649  return GNUNET_NO;
650 }
651 
652 
658 static void
660 {
661  union MapEntry *old_map;
662  union MapEntry *new_map;
663  unsigned int old_len;
664  unsigned int new_len;
665  unsigned int idx;
666 
667  old_map = map->map;
668  old_len = map->map_length;
669  new_len = old_len * 2;
670  if (0 == new_len) /* 2^31 * 2 == 0 */
671  new_len = old_len; /* never use 0 */
672  if (new_len == old_len)
673  return; /* nothing changed */
674  new_map = GNUNET_malloc_large (new_len * sizeof(union MapEntry));
675  if (NULL == new_map)
676  return; /* grow not possible */
677  map->modification_counter++;
678  map->map_length = new_len;
679  map->map = new_map;
680  for (unsigned int i = 0; i < old_len; i++)
681  {
682  if (map->use_small_entries)
683  {
684  struct SmallMapEntry *sme;
685 
686  while (NULL != (sme = old_map[i].sme))
687  {
688  old_map[i].sme = sme->next;
689  idx = idx_of (map, sme->key);
690  sme->next = new_map[idx].sme;
691  new_map[idx].sme = sme;
692  }
693  }
694  else
695  {
696  struct BigMapEntry *bme;
697 
698  while (NULL != (bme = old_map[i].bme))
699  {
700  old_map[i].bme = bme->next;
701  idx = idx_of (map, &bme->key);
702  bme->next = new_map[idx].bme;
703  new_map[idx].bme = bme;
704  }
705  }
706  }
707  GNUNET_free (old_map);
708 }
709 
710 
723 int
726  const struct GNUNET_ShortHashCode *key,
727  void *value,
729 {
730  union MapEntry me;
731  unsigned int i;
732 
733  i = idx_of (map, key);
736  {
737  me = map->map[i];
738  if (map->use_small_entries)
739  {
740  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
741  if (0 == GNUNET_memcmp (key, sme->key))
742  {
744  return GNUNET_SYSERR;
745  sme->value = value;
746  return GNUNET_NO;
747  }
748  }
749  else
750  {
751  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
752  if (0 == GNUNET_memcmp (key, &bme->key))
753  {
755  return GNUNET_SYSERR;
756  bme->value = value;
757  return GNUNET_NO;
758  }
759  }
760  }
761  if (map->size / 3 >= map->map_length / 4)
762  {
763  grow (map);
764  i = idx_of (map, key);
765  }
766  if (map->use_small_entries)
767  {
768  struct SmallMapEntry *sme;
769 
770  sme = GNUNET_new (struct SmallMapEntry);
771  sme->key = key;
772  sme->value = value;
773  sme->next = map->map[i].sme;
774  map->map[i].sme = sme;
775  }
776  else
777  {
778  struct BigMapEntry *bme;
779 
780  bme = GNUNET_new (struct BigMapEntry);
781  bme->key = *key;
782  bme->value = value;
783  bme->next = map->map[i].bme;
784  map->map[i].bme = bme;
785  }
786  map->size++;
787  return GNUNET_OK;
788 }
789 
790 
801 int
804  const struct GNUNET_ShortHashCode *key,
806  void *it_cls)
807 {
808  int count;
809  union MapEntry me;
810  union MapEntry *ce;
811 
812  ce = &map->next_cache[map->next_cache_off];
814  count = 0;
815  me = map->map[idx_of (map, key)];
816  if (map->use_small_entries)
817  {
818  struct SmallMapEntry *sme;
819 
820  ce->sme = me.sme;
821  while (NULL != (sme = ce->sme))
822  {
823  ce->sme = sme->next;
824  if (0 != GNUNET_memcmp (key, sme->key))
825  continue;
826  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, sme->value)))
827  {
829  return GNUNET_SYSERR;
830  }
831  count++;
832  }
833  }
834  else
835  {
836  struct BigMapEntry *bme;
837 
838  ce->bme = me.bme;
839  while (NULL != (bme = ce->bme))
840  {
841  ce->bme = bme->next;
842  if (0 != GNUNET_memcmp (key, &bme->key))
843  continue;
844  if ((NULL != it) && (GNUNET_OK != it (it_cls, key, bme->value)))
845  {
847  return GNUNET_SYSERR;
848  }
849  count++;
850  }
851  }
853  return count;
854 }
855 
856 
868 unsigned int
870  const struct GNUNET_CONTAINER_MultiShortmap *map,
872  void *it_cls)
873 {
874  unsigned int off;
875  union MapEntry me;
876 
877  if (0 == map->size)
878  return 0;
879  if (NULL == it)
880  return 1;
882  for (unsigned int idx = 0; idx < map->map_length; idx++)
883  {
884  me = map->map[idx];
885  if (map->use_small_entries)
886  {
887  for (struct SmallMapEntry *sme = me.sme; NULL != sme; sme = sme->next)
888  {
889  if (0 == off)
890  {
891  if (GNUNET_OK != it (it_cls, sme->key, sme->value))
892  return GNUNET_SYSERR;
893  return 1;
894  }
895  off--;
896  }
897  }
898  else
899  {
900  for (struct BigMapEntry *bme = me.bme; NULL != bme; bme = bme->next)
901  {
902  if (0 == off)
903  {
904  if (GNUNET_OK != it (it_cls, &bme->key, bme->value))
905  return GNUNET_SYSERR;
906  return 1;
907  }
908  off--;
909  }
910  }
911  }
912  GNUNET_break (0);
913  return GNUNET_SYSERR;
914 }
915 
916 
931  const struct GNUNET_CONTAINER_MultiShortmap *map)
932 {
934 
936  iter->map = map;
938  iter->me = map->map[0];
939  return iter;
940 }
941 
942 
957 int
960  struct GNUNET_ShortHashCode *key,
961  const void **value)
962 {
963  /* make sure the map has not been modified */
965 
966  /* look for the next entry, skipping empty buckets */
967  while (1)
968  {
969  if (iter->idx >= iter->map->map_length)
970  return GNUNET_NO;
971  if (GNUNET_YES == iter->map->use_small_entries)
972  {
973  if (NULL != iter->me.sme)
974  {
975  if (NULL != key)
976  *key = *iter->me.sme->key;
977  if (NULL != value)
978  *value = iter->me.sme->value;
979  iter->me.sme = iter->me.sme->next;
980  return GNUNET_YES;
981  }
982  }
983  else
984  {
985  if (NULL != iter->me.bme)
986  {
987  if (NULL != key)
988  *key = iter->me.bme->key;
989  if (NULL != value)
990  *value = iter->me.bme->value;
991  iter->me.bme = iter->me.bme->next;
992  return GNUNET_YES;
993  }
994  }
995  iter->idx += 1;
996  if (iter->idx < iter->map->map_length)
997  iter->me = iter->map->map[iter->idx];
998  }
999 }
1000 
1001 
1007 void
1010 {
1011  GNUNET_free (iter);
1012 }
1013 
1014 
1015 /* 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.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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:78
void * value
Value of the entry.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#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.
#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.
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:76
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:77
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.