]> git.ipfire.org Git - thirdparty/git.git/blobdiff - hashmap.h
Merge branch 'hw/remove-api-docs-placeholder'
[thirdparty/git.git] / hashmap.h
index bc3b10e0970ffb145f964ca49f2b779e44b5ba7d..bd2701549f55650748c7cfd5afd2dad6c2321f54 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -13,7 +13,7 @@
  *
  * struct hashmap map;
  * struct long2string {
- *     struct hashmap_entry ent; // must be the first member!
+ *     struct hashmap_entry ent;
  *     long key;
  *     char value[FLEX_ARRAY];   // be careful with allocating on stack!
  * };
@@ -63,7 +63,7 @@
  *             k.key = key;
  *
  *             flags &= ~COMPARE_VALUE;
- *             e = hashmap_get_entry(&map, &k, NULL, struct long2string, ent);
+ *             e = hashmap_get_entry(&map, &k, ent, NULL);
  *             if (e) {
  *                 printf("first: %ld %s\n", e->key, e->value);
  *                 while ((e = hashmap_get_next_entry(&map, e,
@@ -96,7 +96,7 @@
  *         }
  *
  *         if (!strcmp("end", action)) {
- *             hashmap_free(&map, 1);
+ *             hashmap_free_entries(&map, struct long2string, ent);
  *             break;
  *         }
  *     }
@@ -141,7 +141,7 @@ static inline unsigned int oidhash(const struct object_id *oid)
 
 /*
  * struct hashmap_entry is an opaque structure representing an entry in the
- * hash table, which must be used as first member of user data structures.
+ * hash table.
  * Ideally it should be followed by an int-sized member to prevent unused
  * memory on 64-bit systems due to alignment.
  */
@@ -232,13 +232,20 @@ void hashmap_init(struct hashmap *map,
                         const void *equals_function_data,
                         size_t initial_size);
 
+/* internal function for freeing hashmap */
+void hashmap_free_(struct hashmap *map, ssize_t offset);
+
 /*
- * Frees a hashmap structure and allocated memory.
- *
- * If `free_entries` is true, each hashmap_entry in the map is freed as well
- * using stdlibs free().
+ * Frees a hashmap structure and allocated memory, leaves entries undisturbed
+ */
+#define hashmap_free(map) hashmap_free_(map, -1)
+
+/*
+ * Frees @map and all entries.  @type is the struct type of the entry
+ * where @member is the hashmap_entry struct used to associate with @map
  */
-void hashmap_free(struct hashmap *map, int free_entries);
+#define hashmap_free_entries(map, type, member) \
+       hashmap_free_(map, offsetof(type, member));
 
 /* hashmap_entry functions */
 
@@ -352,8 +359,17 @@ void hashmap_add(struct hashmap *map, struct hashmap_entry *entry);
 struct hashmap_entry *hashmap_put(struct hashmap *map,
                                struct hashmap_entry *entry);
 
-#define hashmap_put_entry(map, keyvar, type, member) \
-       container_of_or_null(hashmap_put(map, &(keyvar)->member), type, member)
+/*
+ * Adds or replaces a hashmap entry contained within @keyvar,
+ * where @keyvar is a pointer to a struct containing a
+ * "struct hashmap_entry" @member.
+ *
+ * Returns the replaced pointer which is of the same type as @keyvar,
+ * or NULL if not found.
+ */
+#define hashmap_put_entry(map, keyvar, member) \
+       container_of_or_null_offset(hashmap_put(map, &(keyvar)->member), \
+                               OFFSETOF_VAR(keyvar, member))
 
 /*
  * Removes a hashmap entry matching the specified key. If the hashmap contains
@@ -366,9 +382,20 @@ struct hashmap_entry *hashmap_remove(struct hashmap *map,
                                        const struct hashmap_entry *key,
                                        const void *keydata);
 
-#define hashmap_remove_entry(map, keyvar, keydata, type, member) \
-       container_of_or_null(hashmap_remove(map, &(keyvar)->member, keydata), \
-                               type, member)
+/*
+ * Removes a hashmap entry contained within @keyvar,
+ * where @keyvar is a pointer to a struct containing a
+ * "struct hashmap_entry" @member.
+ *
+ * See `hashmap_get` for an explanation of @keydata
+ *
+ * Returns the replaced pointer which is of the same type as @keyvar,
+ * or NULL if not found.
+ */
+#define hashmap_remove_entry(map, keyvar, member, keydata) \
+       container_of_or_null_offset( \
+                       hashmap_remove(map, &(keyvar)->member, keydata), \
+                       OFFSETOF_VAR(keyvar, member))
 
 /*
  * Returns the `bucket` an entry is stored in.
@@ -401,46 +428,63 @@ static inline struct hashmap_entry *hashmap_iter_first(struct hashmap *map,
        return hashmap_iter_next(iter);
 }
 
-#define hashmap_iter_next_entry(iter, type, member) \
-       container_of_or_null(hashmap_iter_next(iter), type, member)
-
+/*
+ * returns the first entry in @map using @iter, where the entry is of
+ * @type (e.g. "struct foo") and @member is the name of the
+ * "struct hashmap_entry" in @type
+ */
 #define hashmap_iter_first_entry(map, iter, type, member) \
        container_of_or_null(hashmap_iter_first(map, iter), type, member)
 
-#define hashmap_for_each_entry(map, iter, var, type, member) \
-       for (var = hashmap_iter_first_entry(map, iter, type, member); \
+/* internal macro for hashmap_for_each_entry */
+#define hashmap_iter_next_entry_offset(iter, offset) \
+       container_of_or_null_offset(hashmap_iter_next(iter), offset)
+
+/* internal macro for hashmap_for_each_entry */
+#define hashmap_iter_first_entry_offset(map, iter, offset) \
+       container_of_or_null_offset(hashmap_iter_first(map, iter), offset)
+
+/*
+ * iterate through @map using @iter, @var is a pointer to a type
+ * containing a @member which is a "struct hashmap_entry"
+ */
+#define hashmap_for_each_entry(map, iter, var, member) \
+       for (var = hashmap_iter_first_entry_offset(map, iter, \
+                                               OFFSETOF_VAR(var, member)); \
                var; \
-               var = hashmap_iter_next_entry(iter, type, member))
+               var = hashmap_iter_next_entry_offset(iter, \
+                                               OFFSETOF_VAR(var, member)))
 
 /*
- * 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
+ * returns a pointer of type matching @keyvar, or NULL if nothing found.
+ * @keyvar is a pointer to a struct containing a
+ * "struct hashmap_entry" @member.
  */
-#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(map, keyvar, member, keydata) \
+       container_of_or_null_offset( \
+                               hashmap_get(map, &(keyvar)->member, keydata), \
+                               OFFSETOF_VAR(keyvar, 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
+ * returns the next equal pointer to @var, or NULL if not found.
+ * @var is a pointer of any type containing "struct hashmap_entry"
+ * @member is the name of the "struct hashmap_entry" field
  */
-#define hashmap_get_next_entry(map, var, type, member) \
-       container_of_or_null(hashmap_get_next(map, &(var)->member), \
-                               type, member)
+#define hashmap_get_next_entry(map, var, member) \
+       container_of_or_null_offset(hashmap_get_next(map, &(var)->member), \
+                               OFFSETOF_VAR(var, 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) \
+#define hashmap_for_each_entry_from(map, var, member) \
        for (; \
                var; \
-               var = hashmap_get_next_entry(map, var, type, member))
+               var = hashmap_get_next_entry(map, var, member))
 
 /*
  * Disable item counting and automatic rehashing when adding/removing items.