]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hashmap: introduce hashmap_free_entries
authorEric Wong <e@80x24.org>
Sun, 6 Oct 2019 23:30:40 +0000 (23:30 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Oct 2019 01:20:11 +0000 (10:20 +0900)
`hashmap_free_entries' behaves like `container_of' and passes
the offset of the hashmap_entry struct to the internal
`hashmap_free_' function, allowing the function to free any
struct pointer regardless of where the hashmap_entry field
is located.

`hashmap_free' no longer takes any arguments aside from
the hashmap itself.

Signed-off-by: Eric Wong <e@80x24.org>
Reviewed-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
17 files changed:
blame.c
builtin/fetch.c
config.c
diff.c
diffcore-rename.c
hashmap.c
hashmap.h
merge-recursive.c
name-hash.c
oidmap.c
patch-ids.c
range-diff.c
ref-filter.c
revision.c
sequencer.c
submodule-config.c
t/helper/test-hashmap.c

diff --git a/blame.c b/blame.c
index 3d8accf902ec55e7902cda6b2ee6a6820c4cdbab..f33af0da9ff05a6c8644d2bd81c0abd24256b4c9 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -433,7 +433,7 @@ static void get_fingerprint(struct fingerprint *result,
 
 static void free_fingerprint(struct fingerprint *f)
 {
-       hashmap_free(&f->map, 0);
+       hashmap_free(&f->map);
        free(f->entries);
 }
 
index 476c2416e3b846d0f82b45e9da46c7deb85fe256..09f7170616c25de769a9f92d68fa43e92eb6b700 100644 (file)
@@ -366,7 +366,7 @@ static void find_non_local_tags(const struct ref *refs,
                item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
                string_list_insert(&remote_refs_list, ref->name);
        }
-       hashmap_free(&existing_refs, 1);
+       hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
 
        /*
         * We may have a final lightweight tag that needs to be
@@ -401,7 +401,7 @@ static void find_non_local_tags(const struct ref *refs,
                **tail = rm;
                *tail = &rm->next;
        }
-       hashmap_free(&remote_refs, 1);
+       hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
        string_list_clear(&remote_refs_list, 0);
 }
 
@@ -530,7 +530,7 @@ static struct ref *get_ref_map(struct remote *remote,
                        }
                }
        }
-       hashmap_free(&existing_refs, 1);
+       hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
 
        return ref_map;
 }
index 8433f7437168217124ce55fb785576af0f300100..4d05dbc15a7a6f1b501874774138cb634c81b273 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1948,7 +1948,7 @@ void git_configset_clear(struct config_set *cs)
                free(entry->key);
                string_list_clear(&entry->value_list, 1);
        }
-       hashmap_free(&cs->config_hash, 1);
+       hashmap_free_entries(&cs->config_hash, struct config_set_element, ent);
        cs->hash_initialized = 0;
        free(cs->list.items);
        cs->list.nr = 0;
diff --git a/diff.c b/diff.c
index 5eaf689fccf39bc6f69de5efc1e09d244860b63f..f94d9f96af152e39e9550b9a24a0152fd3311786 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -6236,8 +6236,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
                        if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
                                dim_moved_lines(o);
 
-                       hashmap_free(&add_lines, 1);
-                       hashmap_free(&del_lines, 1);
+                       hashmap_free_entries(&add_lines, struct moved_entry,
+                                               ent);
+                       hashmap_free_entries(&del_lines, struct moved_entry,
+                                               ent);
                }
 
                for (i = 0; i < esm.nr; i++)
index 611b08f463d670862605500036db4942c8fbfef4..994609ed58a512e9621e1882ef899577a0699f4c 100644 (file)
@@ -358,7 +358,7 @@ static int find_exact_renames(struct diff_options *options)
                renames += find_identical_files(&file_table, i, options);
 
        /* Free the hash data structure and entries */
-       hashmap_free(&file_table, 1);
+       hashmap_free_entries(&file_table, struct file_similarity, entry);
 
        return renames;
 }
index 1b60f97cf20344dd798e64305522eab109156875..65b447f6cd75ea5635075e9eba9acc4fb5cf9761 100644 (file)
--- a/hashmap.c
+++ b/hashmap.c
@@ -171,16 +171,21 @@ 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));
index bc3b10e0970ffb145f964ca49f2b779e44b5ba7d..171d6ddb7651362f75b1c3e4b9c5604ccdb22b57 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -96,7 +96,7 @@
  *         }
  *
  *         if (!strcmp("end", action)) {
- *             hashmap_free(&map, 1);
+ *             hashmap_free_entries(&map, struct long2string, ent);
  *             break;
  *         }
  *     }
@@ -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 */
 
index 73c775044825e5961eaab8f3aa046b3287fa224e..34b3d54154d9217c887abcaac742be4f87db1420 100644 (file)
@@ -2633,7 +2633,7 @@ static struct string_list *get_renames(struct merge_options *opt,
                free(e->target_file);
                string_list_clear(&e->source_files, 0);
        }
-       hashmap_free(&collisions, 1);
+       hashmap_free_entries(&collisions, struct collision_entry, ent);
        return renames;
 }
 
@@ -2853,7 +2853,7 @@ static void initial_cleanup_rename(struct diff_queue_struct *pairs,
                strbuf_release(&e->new_dir);
                /* possible_new_dirs already cleared in get_directory_renames */
        }
-       hashmap_free(dir_renames, 1);
+       hashmap_free_entries(dir_renames, struct dir_rename_entry, ent);
        free(dir_renames);
 
        free(pairs->queue);
@@ -3482,7 +3482,8 @@ int merge_trees(struct merge_options *opt,
                string_list_clear(entries, 1);
                free(entries);
 
-               hashmap_free(&opt->current_file_dir_set, 1);
+               hashmap_free_entries(&opt->current_file_dir_set,
+                                       struct path_hashmap_entry, e);
 
                if (clean < 0) {
                        unpack_trees_finish(opt);
index 85a1ce982c2f3fd2590ac7ee1c803d8c25a41c67..c86fe0f1df0b95c125eecc580ee47a0788bd9632 100644 (file)
@@ -728,6 +728,6 @@ void free_name_hash(struct index_state *istate)
                return;
        istate->name_hash_initialized = 0;
 
-       hashmap_free(&istate->name_hash, 0);
-       hashmap_free(&istate->dir_hash, 1);
+       hashmap_free(&istate->name_hash);
+       hashmap_free_entries(&istate->dir_hash, struct dir_entry, ent);
 }
index 4942599391096d0ac016f49ebb081015440327d1..423aa014a33eda2c6b695906eb0c349552d9e2b8 100644 (file)
--- a/oidmap.c
+++ b/oidmap.c
@@ -25,7 +25,9 @@ void oidmap_free(struct oidmap *map, int free_entries)
 {
        if (!map)
                return;
-       hashmap_free(&map->map, free_entries);
+
+       /* TODO: make oidmap itself not depend on struct layouts */
+       hashmap_free_(&map->map, free_entries ? 0 : -1);
 }
 
 void *oidmap_get(const struct oidmap *map, const struct object_id *key)
index 75f8c9f1a11e05e8cd6145241178d3b0cae62e40..af17828e336b2ddb2da9a5b7fbeccabd5bb32282 100644 (file)
@@ -71,7 +71,7 @@ int init_patch_ids(struct repository *r, struct patch_ids *ids)
 
 int free_patch_ids(struct patch_ids *ids)
 {
-       hashmap_free(&ids->patches, 1);
+       hashmap_free_entries(&ids->patches, struct patch_id, ent);
        return 0;
 }
 
index e5e7820bfea79092be469ed7a7bdfcfcf98eeed3..9df53569bbc72e973e0808593979d2d299eada82 100644 (file)
@@ -241,7 +241,7 @@ static void find_exact_matches(struct string_list *a, struct string_list *b)
                }
        }
 
-       hashmap_free(&map, 0);
+       hashmap_free(&map);
 }
 
 static void diffsize_consume(void *data, char *line, unsigned long len)
index 4613df8826818380f2b2554fce7fe409c0de0c56..0950b789e3990d84da998fe5e6b115f5845ac7a9 100644 (file)
@@ -2172,7 +2172,8 @@ void ref_array_clear(struct ref_array *array)
        used_atom_cnt = 0;
 
        if (ref_to_worktree_map.worktrees) {
-               hashmap_free(&(ref_to_worktree_map.map), 1);
+               hashmap_free_entries(&(ref_to_worktree_map.map),
+                                       struct ref_to_worktree_entry, ent);
                free_worktrees(ref_to_worktree_map.worktrees);
                ref_to_worktree_map.worktrees = NULL;
        }
index f28cbe5de85a9374be7c4d07a20aea0de2399f16..8a5f866ae6a7f2757a4f91ed96207c30b3a9c8b8 100644 (file)
@@ -136,7 +136,7 @@ static void paths_and_oids_clear(struct hashmap *map)
                free(entry->path);
        }
 
-       hashmap_free(map, 1);
+       hashmap_free_entries(map, struct path_and_oids_entry, ent);
 }
 
 static void paths_and_oids_insert(struct hashmap *map,
index b3e7319b5547d7a14089e621f693b6cac2a356a4..694b463518394430f542ee2a8b3ce5253f010964 100644 (file)
@@ -4772,7 +4772,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 
        oidmap_free(&commit2todo, 1);
        oidmap_free(&state.commit2label, 1);
-       hashmap_free(&state.labels, 1);
+       hashmap_free_entries(&state.labels, struct labels_entry, entry);
        strbuf_release(&state.buf);
 
        return 0;
@@ -5301,7 +5301,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
        for (i = 0; i < todo_list->nr; i++)
                free(subjects[i]);
        free(subjects);
-       hashmap_free(&subject2item, 1);
+       hashmap_free_entries(&subject2item, struct subject2item_entry, entry);
 
        clear_commit_todo_item(&commit_todo);
 
index a289d195f6ab9476f5b7a36796f5e58b8deb9a4e..5462acc8ecbb204f110941775a5ae696f6e6c7e0 100644 (file)
@@ -103,8 +103,8 @@ static void submodule_cache_clear(struct submodule_cache *cache)
                                struct submodule_entry, ent /* member name */)
                free_one_config(entry);
 
-       hashmap_free(&cache->for_path, 1);
-       hashmap_free(&cache->for_name, 1);
+       hashmap_free_entries(&cache->for_path, struct submodule_entry, ent);
+       hashmap_free_entries(&cache->for_name, struct submodule_entry, ent);
        cache->initialized = 0;
        cache->gitmodules_read = 0;
 }
index 07a93a2aec243afe3bd2d4a3f09a899f4fc8a709..6f2530dcc8ce873651596cf078ca75e34af08a0a 100644 (file)
@@ -109,7 +109,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
                                hashmap_add(&map, &entries[i]->ent);
                        }
 
-                       hashmap_free(&map, 0);
+                       hashmap_free(&map);
                }
        } else {
                /* test map lookups */
@@ -129,7 +129,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
                        }
                }
 
-               hashmap_free(&map, 0);
+               hashmap_free(&map);
        }
 }
 
@@ -266,6 +266,6 @@ int cmd__hashmap(int argc, const char **argv)
        }
 
        strbuf_release(&line);
-       hashmap_free(&map, 1);
+       hashmap_free_entries(&map, struct test_entry, ent);
        return 0;
 }