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 <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2017-04-24 00:41:21 -07:00
parent bf0bcef3d4
commit bbb39579ec
5 changed files with 52 additions and 26 deletions

View file

@ -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 */

View file

@ -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);
}

View file

@ -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);
}
/*

View file

@ -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)
{

View file

@ -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;