]> git.ipfire.org Git - thirdparty/git.git/blobdiff - hashmap.c
Git 2.24
[thirdparty/git.git] / hashmap.c
index d42f01ff5ae6f3494d5b427c64bc64406c35d576..39c13110bc32f05f0cbb4ec1cf22bdc6ea6995b2 100644 (file)
--- a/hashmap.c
+++ b/hashmap.c
@@ -140,8 +140,8 @@ static inline struct hashmap_entry **find_entry_ptr(const struct hashmap *map,
 }
 
 static int always_equal(const void *unused_cmp_data,
-                       const void *unused1,
-                       const void *unused2,
+                       const struct hashmap_entry *unused1,
+                       const struct hashmap_entry *unused2,
                        const void *unused_keydata)
 {
        return 0;
@@ -171,41 +171,49 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
        map->do_count_items = 1;
 }
 
-void hashmap_free(struct hashmap *map, int free_entries)
+void hashmap_free_(struct hashmap *map, ssize_t entry_offset)
 {
        if (!map || !map->table)
                return;
-       if (free_entries) {
+       if (entry_offset >= 0) { /* called by hashmap_free_entries */
                struct hashmap_iter iter;
                struct hashmap_entry *e;
+
                hashmap_iter_init(map, &iter);
                while ((e = hashmap_iter_next(&iter)))
-                       free(e);
+                       /*
+                        * like container_of, but using caller-calculated
+                        * offset (caller being hashmap_free_entries)
+                        */
+                       free((char *)e - entry_offset);
        }
        free(map->table);
        memset(map, 0, sizeof(*map));
 }
 
-void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata)
+struct hashmap_entry *hashmap_get(const struct hashmap *map,
+                               const struct hashmap_entry *key,
+                               const void *keydata)
 {
        return *find_entry_ptr(map, key, keydata);
 }
 
-void *hashmap_get_next(const struct hashmap *map, const void *entry)
+struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
+                       const struct hashmap_entry *entry)
 {
-       struct hashmap_entry *e = ((struct hashmap_entry *) entry)->next;
+       struct hashmap_entry *e = entry->next;
        for (; e; e = e->next)
                if (entry_equals(map, entry, e, NULL))
                        return e;
        return NULL;
 }
 
-void hashmap_add(struct hashmap *map, void *entry)
+void hashmap_add(struct hashmap *map, struct hashmap_entry *entry)
 {
        unsigned int b = bucket(map, entry);
 
        /* add entry */
-       ((struct hashmap_entry *) entry)->next = map->table[b];
+       entry->next = map->table[b];
        map->table[b] = entry;
 
        /* fix size and rehash if appropriate */
@@ -216,7 +224,9 @@ void hashmap_add(struct hashmap *map, void *entry)
        }
 }
 
-void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)
+struct hashmap_entry *hashmap_remove(struct hashmap *map,
+                                       const struct hashmap_entry *key,
+                                       const void *keydata)
 {
        struct hashmap_entry *old;
        struct hashmap_entry **e = find_entry_ptr(map, key, keydata);
@@ -238,7 +248,8 @@ void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)
        return old;
 }
 
-void *hashmap_put(struct hashmap *map, void *entry)
+struct hashmap_entry *hashmap_put(struct hashmap *map,
+                               struct hashmap_entry *entry)
 {
        struct hashmap_entry *old = hashmap_remove(map, entry, NULL);
        hashmap_add(map, entry);
@@ -252,7 +263,7 @@ void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter)
        iter->next = NULL;
 }
 
-void *hashmap_iter_next(struct hashmap_iter *iter)
+struct hashmap_entry *hashmap_iter_next(struct hashmap_iter *iter)
 {
        struct hashmap_entry *current = iter->next;
        for (;;) {
@@ -275,10 +286,15 @@ struct pool_entry {
 };
 
 static int pool_entry_cmp(const void *unused_cmp_data,
-                         const struct pool_entry *e1,
-                         const struct pool_entry *e2,
-                         const unsigned char *keydata)
+                         const struct hashmap_entry *eptr,
+                         const struct hashmap_entry *entry_or_key,
+                         const void *keydata)
 {
+       const struct pool_entry *e1, *e2;
+
+       e1 = container_of(eptr, const struct pool_entry, ent);
+       e2 = container_of(entry_or_key, const struct pool_entry, ent);
+
        return e1->data != keydata &&
               (e1->len != e2->len || memcmp(e1->data, keydata, e1->len));
 }
@@ -290,18 +306,18 @@ const void *memintern(const void *data, size_t len)
 
        /* initialize string pool hashmap */
        if (!map.tablesize)
-               hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, NULL, 0);
+               hashmap_init(&map, pool_entry_cmp, NULL, 0);
 
        /* lookup interned string in pool */
-       hashmap_entry_init(&key, memhash(data, len));
+       hashmap_entry_init(&key.ent, memhash(data, len));
        key.len = len;
-       e = hashmap_get(&map, &key, data);
+       e = hashmap_get_entry(&map, &key, ent, data);
        if (!e) {
                /* not found: create it */
                FLEX_ALLOC_MEM(e, data, data, len);
-               hashmap_entry_init(e, key.ent.hash);
+               hashmap_entry_init(&e->ent, key.ent.hash);
                e->len = len;
-               hashmap_add(&map, e);
+               hashmap_add(&map, &e->ent);
        }
        return e->data;
 }