From bbb39579ec340aba9cda4c7033dd934b620423ea Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 24 Apr 2017 00:41:21 -0700 Subject: hashtbl, strtbl: add hash_free_all(), split strtbl_find() Add hash_free_all() to factor common code of iterating over all members of a hash to free them with a single nasm_free(). Split strtbl_find() into strtbl_find() and strtbl_add(). It is very unlikely that the same call site will want to have both of these functionalities, and in the end the code for the two functions are surprisingly different. Signed-off-by: H. Peter Anvin --- include/hashtbl.h | 1 + nasmlib/hashtbl.c | 26 +++++++++++++++++++++++++- nasmlib/srcfile.c | 8 +------- output/strtbl.c | 40 +++++++++++++++++++++++----------------- output/strtbl.h | 3 ++- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/include/hashtbl.h b/include/hashtbl.h index da618c8a..25f2d2d5 100644 --- a/include/hashtbl.h +++ b/include/hashtbl.h @@ -81,5 +81,6 @@ void *hash_iterate(const struct hash_table *head, struct hash_tbl_node **iterator, const char **key); void hash_free(struct hash_table *head); +void hash_free_all(struct hash_table *head, bool free_keys); #endif /* NASM_HASHTBL_H */ diff --git a/nasmlib/hashtbl.c b/nasmlib/hashtbl.c index 7f8fca63..bc0776b8 100644 --- a/nasmlib/hashtbl.c +++ b/nasmlib/hashtbl.c @@ -222,7 +222,9 @@ void *hash_iterate(const struct hash_table *head, /* * Free the hash itself. Doesn't free the data elements; use - * hash_iterate() to do that first, if needed. + * hash_iterate() to do that first, if needed. This function is normally + * used when the hash data entries are either freed separately, or + * compound objects which can't be freed in a single operation. */ void hash_free(struct hash_table *head) { @@ -230,3 +232,25 @@ void hash_free(struct hash_table *head) head->table = NULL; nasm_free(p); } + +/* + * Frees the hash *and* all data elements. This is applicable only in + * the case where the data element is a single allocation. If the + * second argument is false, the key string is part of the data + * allocation or belongs to an allocation which will be freed + * separately, if it is true the keys are also freed. + */ +void hash_free_all(struct hash_table *head, bool free_keys) +{ + struct hash_tbl_node *iter = NULL; + const char *keyp; + void *d; + + while ((d = hash_iterate(head, &iter, &keyp))) { + nasm_free(d); + if (free_keys) + nasm_free((void *)keyp); + } + + hash_free(head); +} diff --git a/nasmlib/srcfile.c b/nasmlib/srcfile.c index 7bee0176..6fbe763f 100644 --- a/nasmlib/srcfile.c +++ b/nasmlib/srcfile.c @@ -55,13 +55,7 @@ void src_init(void) void src_free(void) { - struct hash_tbl_node *iter = NULL; - void *dp; - - while ((dp = hash_iterate(&filename_hash, &iter, NULL)) != NULL) - nasm_free(dp); - - hash_free(&filename_hash); + hash_free_all(&filename_hash, false); } /* diff --git a/output/strtbl.c b/output/strtbl.c index 94dd59b6..23b0d118 100644 --- a/output/strtbl.c +++ b/output/strtbl.c @@ -57,30 +57,24 @@ void strtbl_init(struct nasm_strtbl *tbl) { tbl->size = 0; hash_init(&tbl->hash, HASH_LARGE); - strtbl_find(tbl, "", true); /* Index 0 is always an empty string */ + strtbl_add(tbl, ""); /* Index 0 is always an empty string */ } void strtbl_free(struct nasm_strtbl *tbl) { - struct hash_tbl_node *iter = NULL; - struct strtbl_entry *se; - - while ((se = hash_iterate(&tbl->hash, &iter, NULL))) - nasm_free(se); - - hash_free(&tbl->hash); + hash_free_all(&tbl->hash, false); } -size_t strtbl_find(struct nasm_strtbl *tbl, const char *str, bool add) +size_t strtbl_add(struct nasm_strtbl *tbl, const char *str) { - struct hash_insert hi; - void **dp; + void **sep; struct strtbl_entry *se; + struct hash_insert hi; - dp = hash_find(&tbl->hash, str, &hi); - if (dp) { - se = *dp; - } else if (add) { + sep = hash_find(&tbl->hash, str, &hi); + if (sep) { + se = *sep; + } else { size_t bytes = strlen(str) + 1; se = nasm_malloc(sizeof(struct strtbl_entry)-1+bytes); @@ -90,13 +84,25 @@ size_t strtbl_find(struct nasm_strtbl *tbl, const char *str, bool add) memcpy(se->str, str, bytes); hash_add(&hi, se->str, se); - } else { - return STRTBL_NONE; } return se->index; } +size_t strtbl_find(struct nasm_strtbl *tbl, const char *str) +{ + void **sep; + struct strtbl_entry *se; + + sep = hash_find(&tbl->hash, str, NULL); + if (sep) { + se = *sep; + return se->index; + } else { + return STRTBL_NONE; + } +} + /* This create a linearized buffer containing the actual string table */ void *strtbl_generate(const struct nasm_strtbl *tbl) { diff --git a/output/strtbl.h b/output/strtbl.h index 52a897f5..12771e4e 100644 --- a/output/strtbl.h +++ b/output/strtbl.h @@ -46,7 +46,8 @@ struct nasm_strtbl { void strtbl_init(struct nasm_strtbl *tbl); void strtbl_free(struct nasm_strtbl *tbl); -size_t strtbl_find(struct nasm_strtbl *tbl, const char *str, bool add); +size_t strtbl_find(struct nasm_strtbl *tbl, const char *str); +size_t strtbl_add(struct nasm_strtbl *tbl, const char *str); static inline size_t strtbl_size(const struct nasm_strtbl *tbl) { return tbl->size; -- cgit v1.2.1