hashmap: introduce hashmap_free_entries
`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>
This commit is contained in:
parent
8a973d0bb3
commit
c8e424c9c9
2
blame.c
2
blame.c
@ -433,7 +433,7 @@ static void get_fingerprint(struct fingerprint *result,
|
|||||||
|
|
||||||
static void free_fingerprint(struct fingerprint *f)
|
static void free_fingerprint(struct fingerprint *f)
|
||||||
{
|
{
|
||||||
hashmap_free(&f->map, 0);
|
hashmap_free(&f->map);
|
||||||
free(f->entries);
|
free(f->entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
|
||||||
string_list_insert(&remote_refs_list, ref->name);
|
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
|
* 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;
|
||||||
*tail = &rm->next;
|
*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);
|
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;
|
return ref_map;
|
||||||
}
|
}
|
||||||
|
2
config.c
2
config.c
@ -1948,7 +1948,7 @@ void git_configset_clear(struct config_set *cs)
|
|||||||
free(entry->key);
|
free(entry->key);
|
||||||
string_list_clear(&entry->value_list, 1);
|
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;
|
cs->hash_initialized = 0;
|
||||||
free(cs->list.items);
|
free(cs->list.items);
|
||||||
cs->list.nr = 0;
|
cs->list.nr = 0;
|
||||||
|
6
diff.c
6
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)
|
if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
|
||||||
dim_moved_lines(o);
|
dim_moved_lines(o);
|
||||||
|
|
||||||
hashmap_free(&add_lines, 1);
|
hashmap_free_entries(&add_lines, struct moved_entry,
|
||||||
hashmap_free(&del_lines, 1);
|
ent);
|
||||||
|
hashmap_free_entries(&del_lines, struct moved_entry,
|
||||||
|
ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < esm.nr; i++)
|
for (i = 0; i < esm.nr; i++)
|
||||||
|
@ -358,7 +358,7 @@ static int find_exact_renames(struct diff_options *options)
|
|||||||
renames += find_identical_files(&file_table, i, options);
|
renames += find_identical_files(&file_table, i, options);
|
||||||
|
|
||||||
/* Free the hash data structure and entries */
|
/* Free the hash data structure and entries */
|
||||||
hashmap_free(&file_table, 1);
|
hashmap_free_entries(&file_table, struct file_similarity, entry);
|
||||||
|
|
||||||
return renames;
|
return renames;
|
||||||
}
|
}
|
||||||
|
11
hashmap.c
11
hashmap.c
@ -171,16 +171,21 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
|
|||||||
map->do_count_items = 1;
|
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)
|
if (!map || !map->table)
|
||||||
return;
|
return;
|
||||||
if (free_entries) {
|
if (entry_offset >= 0) { /* called by hashmap_free_entries */
|
||||||
struct hashmap_iter iter;
|
struct hashmap_iter iter;
|
||||||
struct hashmap_entry *e;
|
struct hashmap_entry *e;
|
||||||
|
|
||||||
hashmap_iter_init(map, &iter);
|
hashmap_iter_init(map, &iter);
|
||||||
while ((e = hashmap_iter_next(&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);
|
free(map->table);
|
||||||
memset(map, 0, sizeof(*map));
|
memset(map, 0, sizeof(*map));
|
||||||
|
19
hashmap.h
19
hashmap.h
@ -96,7 +96,7 @@
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* if (!strcmp("end", action)) {
|
* if (!strcmp("end", action)) {
|
||||||
* hashmap_free(&map, 1);
|
* hashmap_free_entries(&map, struct long2string, ent);
|
||||||
* break;
|
* break;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@ -232,13 +232,20 @@ void hashmap_init(struct hashmap *map,
|
|||||||
const void *equals_function_data,
|
const void *equals_function_data,
|
||||||
size_t initial_size);
|
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.
|
* Frees a hashmap structure and allocated memory, leaves entries undisturbed
|
||||||
*
|
|
||||||
* If `free_entries` is true, each hashmap_entry in the map is freed as well
|
|
||||||
* using stdlibs free().
|
|
||||||
*/
|
*/
|
||||||
void hashmap_free(struct hashmap *map, int free_entries);
|
#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
|
||||||
|
*/
|
||||||
|
#define hashmap_free_entries(map, type, member) \
|
||||||
|
hashmap_free_(map, offsetof(type, member));
|
||||||
|
|
||||||
/* hashmap_entry functions */
|
/* hashmap_entry functions */
|
||||||
|
|
||||||
|
@ -2633,7 +2633,7 @@ static struct string_list *get_renames(struct merge_options *opt,
|
|||||||
free(e->target_file);
|
free(e->target_file);
|
||||||
string_list_clear(&e->source_files, 0);
|
string_list_clear(&e->source_files, 0);
|
||||||
}
|
}
|
||||||
hashmap_free(&collisions, 1);
|
hashmap_free_entries(&collisions, struct collision_entry, ent);
|
||||||
return renames;
|
return renames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2853,7 +2853,7 @@ static void initial_cleanup_rename(struct diff_queue_struct *pairs,
|
|||||||
strbuf_release(&e->new_dir);
|
strbuf_release(&e->new_dir);
|
||||||
/* possible_new_dirs already cleared in get_directory_renames */
|
/* 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(dir_renames);
|
||||||
|
|
||||||
free(pairs->queue);
|
free(pairs->queue);
|
||||||
@ -3482,7 +3482,8 @@ int merge_trees(struct merge_options *opt,
|
|||||||
string_list_clear(entries, 1);
|
string_list_clear(entries, 1);
|
||||||
free(entries);
|
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) {
|
if (clean < 0) {
|
||||||
unpack_trees_finish(opt);
|
unpack_trees_finish(opt);
|
||||||
|
@ -728,6 +728,6 @@ void free_name_hash(struct index_state *istate)
|
|||||||
return;
|
return;
|
||||||
istate->name_hash_initialized = 0;
|
istate->name_hash_initialized = 0;
|
||||||
|
|
||||||
hashmap_free(&istate->name_hash, 0);
|
hashmap_free(&istate->name_hash);
|
||||||
hashmap_free(&istate->dir_hash, 1);
|
hashmap_free_entries(&istate->dir_hash, struct dir_entry, ent);
|
||||||
}
|
}
|
||||||
|
4
oidmap.c
4
oidmap.c
@ -25,7 +25,9 @@ void oidmap_free(struct oidmap *map, int free_entries)
|
|||||||
{
|
{
|
||||||
if (!map)
|
if (!map)
|
||||||
return;
|
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)
|
void *oidmap_get(const struct oidmap *map, const struct object_id *key)
|
||||||
|
@ -71,7 +71,7 @@ int init_patch_ids(struct repository *r, struct patch_ids *ids)
|
|||||||
|
|
||||||
int free_patch_ids(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
static void diffsize_consume(void *data, char *line, unsigned long len)
|
||||||
|
@ -2172,7 +2172,8 @@ void ref_array_clear(struct ref_array *array)
|
|||||||
used_atom_cnt = 0;
|
used_atom_cnt = 0;
|
||||||
|
|
||||||
if (ref_to_worktree_map.worktrees) {
|
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);
|
free_worktrees(ref_to_worktree_map.worktrees);
|
||||||
ref_to_worktree_map.worktrees = NULL;
|
ref_to_worktree_map.worktrees = NULL;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ static void paths_and_oids_clear(struct hashmap *map)
|
|||||||
free(entry->path);
|
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,
|
static void paths_and_oids_insert(struct hashmap *map,
|
||||||
|
@ -4772,7 +4772,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
|
|||||||
|
|
||||||
oidmap_free(&commit2todo, 1);
|
oidmap_free(&commit2todo, 1);
|
||||||
oidmap_free(&state.commit2label, 1);
|
oidmap_free(&state.commit2label, 1);
|
||||||
hashmap_free(&state.labels, 1);
|
hashmap_free_entries(&state.labels, struct labels_entry, entry);
|
||||||
strbuf_release(&state.buf);
|
strbuf_release(&state.buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -5301,7 +5301,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
|
|||||||
for (i = 0; i < todo_list->nr; i++)
|
for (i = 0; i < todo_list->nr; i++)
|
||||||
free(subjects[i]);
|
free(subjects[i]);
|
||||||
free(subjects);
|
free(subjects);
|
||||||
hashmap_free(&subject2item, 1);
|
hashmap_free_entries(&subject2item, struct subject2item_entry, entry);
|
||||||
|
|
||||||
clear_commit_todo_item(&commit_todo);
|
clear_commit_todo_item(&commit_todo);
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ static void submodule_cache_clear(struct submodule_cache *cache)
|
|||||||
struct submodule_entry, ent /* member name */)
|
struct submodule_entry, ent /* member name */)
|
||||||
free_one_config(entry);
|
free_one_config(entry);
|
||||||
|
|
||||||
hashmap_free(&cache->for_path, 1);
|
hashmap_free_entries(&cache->for_path, struct submodule_entry, ent);
|
||||||
hashmap_free(&cache->for_name, 1);
|
hashmap_free_entries(&cache->for_name, struct submodule_entry, ent);
|
||||||
cache->initialized = 0;
|
cache->initialized = 0;
|
||||||
cache->gitmodules_read = 0;
|
cache->gitmodules_read = 0;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
|
|||||||
hashmap_add(&map, &entries[i]->ent);
|
hashmap_add(&map, &entries[i]->ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
hashmap_free(&map, 0);
|
hashmap_free(&map);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* test map lookups */
|
/* 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);
|
strbuf_release(&line);
|
||||||
hashmap_free(&map, 1);
|
hashmap_free_entries(&map, struct test_entry, ent);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user