summary refs log tree commit diff
path: root/hashmap.h
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-10-06 23:30:35 +0000
committerJunio C Hamano <gitster@pobox.com>2019-10-07 10:20:10 +0900
commitf0e63c41139f8982add435536d39aff6f3d4ca98 (patch)
tree6ed9e3afe2081c8201d6c6c9a0d9b8c9439d3a6e /hashmap.h
parent6bcbdfb277bdc81b5ad6996b3fb005382a35c2ee (diff)
hashmap: use *_entry APIs to wrap container_of
Using `container_of' can be verbose and choosing names for
intermediate "struct hashmap_entry" pointers is a hard problem.
So introduce "*_entry" APIs inspired by similar linked-list
APIs in the Linux kernel.

Unfortunately, `__typeof__' is not portable C, so we need an
extra parameter to specify the type.

Signed-off-by: Eric Wong <e@80x24.org>
Reviewed-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'hashmap.h')
-rw-r--r--hashmap.h40
1 files changed, 34 insertions, 6 deletions
diff --git a/hashmap.h b/hashmap.h
index 21bc8aff2b..cd42dcc15c 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -55,17 +55,15 @@
  *
  *         if (!strcmp("print_all_by_key", action)) {
  *             struct long2string k, *e;
- *             struct hashmap_entry *ent;
  *             hashmap_entry_init(&k->ent, memhash(&key, sizeof(long)));
  *             k.key = key;
  *
  *             flags &= ~COMPARE_VALUE;
- *             ent = hashmap_get(&map, &k, NULL);
- *             if (ent) {
- *                 e = container_of(ent, struct long2string, ent);
+ *             e = hashmap_get_entry(&map, &k, NULL, struct long2string, ent);
+ *             if (e) {
  *                 printf("first: %ld %s\n", e->key, e->value);
- *                 while ((ent = hashmap_get_next(&map, ent))) {
- *                     e = container_of(ent, struct long2string, ent);
+ *                 while ((e = hashmap_get_next_entry(&map, e,
+ *                                              struct long2string, ent))) {
  *                     printf("found more: %ld %s\n", e->key, e->value);
  *                 }
  *             }
@@ -388,6 +386,36 @@ static inline void *hashmap_iter_first(struct hashmap *map,
 }
 
 /*
+ * returns a @pointer of @type matching @keyvar, or NULL if nothing found.
+ * @keyvar is a pointer of @type
+ * @member is the name of the "struct hashmap_entry" field in @type
+ */
+#define hashmap_get_entry(map, keyvar, keydata, type, member) \
+	container_of_or_null(hashmap_get(map, &(keyvar)->member, keydata), \
+				type, member)
+
+#define hashmap_get_entry_from_hash(map, hash, keydata, type, member) \
+	container_of_or_null(hashmap_get_from_hash(map, hash, keydata), \
+				type, member)
+/*
+ * returns the next equal @type pointer to @var, or NULL if not found.
+ * @var is a pointer of @type
+ * @member is the name of the "struct hashmap_entry" field in @type
+ */
+#define hashmap_get_next_entry(map, var, type, member) \
+	container_of_or_null(hashmap_get_next(map, &(var)->member), \
+				type, member)
+
+/*
+ * iterate @map starting from @var, where @var is a pointer of @type
+ * and @member is the name of the "struct hashmap_entry" field in @type
+ */
+#define hashmap_for_each_entry_from(map, var, type, member) \
+	for (; \
+		var; \
+		var = hashmap_get_next_entry(map, var, type, member))
+
+/*
  * Disable item counting and automatic rehashing when adding/removing items.
  *
  * Normally, the hashmap keeps track of the number of items in the map