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:
parent
bf0bcef3d4
commit
bbb39579ec
5 changed files with 52 additions and 26 deletions
|
@ -81,5 +81,6 @@ void *hash_iterate(const struct hash_table *head,
|
||||||
struct hash_tbl_node **iterator,
|
struct hash_tbl_node **iterator,
|
||||||
const char **key);
|
const char **key);
|
||||||
void hash_free(struct hash_table *head);
|
void hash_free(struct hash_table *head);
|
||||||
|
void hash_free_all(struct hash_table *head, bool free_keys);
|
||||||
|
|
||||||
#endif /* NASM_HASHTBL_H */
|
#endif /* NASM_HASHTBL_H */
|
||||||
|
|
|
@ -222,7 +222,9 @@ void *hash_iterate(const struct hash_table *head,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free the hash itself. Doesn't free the data elements; use
|
* 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)
|
void hash_free(struct hash_table *head)
|
||||||
{
|
{
|
||||||
|
@ -230,3 +232,25 @@ void hash_free(struct hash_table *head)
|
||||||
head->table = NULL;
|
head->table = NULL;
|
||||||
nasm_free(p);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -55,13 +55,7 @@ void src_init(void)
|
||||||
|
|
||||||
void src_free(void)
|
void src_free(void)
|
||||||
{
|
{
|
||||||
struct hash_tbl_node *iter = NULL;
|
hash_free_all(&filename_hash, false);
|
||||||
void *dp;
|
|
||||||
|
|
||||||
while ((dp = hash_iterate(&filename_hash, &iter, NULL)) != NULL)
|
|
||||||
nasm_free(dp);
|
|
||||||
|
|
||||||
hash_free(&filename_hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -57,30 +57,24 @@ void strtbl_init(struct nasm_strtbl *tbl)
|
||||||
{
|
{
|
||||||
tbl->size = 0;
|
tbl->size = 0;
|
||||||
hash_init(&tbl->hash, HASH_LARGE);
|
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)
|
void strtbl_free(struct nasm_strtbl *tbl)
|
||||||
{
|
{
|
||||||
struct hash_tbl_node *iter = NULL;
|
hash_free_all(&tbl->hash, false);
|
||||||
struct strtbl_entry *se;
|
|
||||||
|
|
||||||
while ((se = hash_iterate(&tbl->hash, &iter, NULL)))
|
|
||||||
nasm_free(se);
|
|
||||||
|
|
||||||
hash_free(&tbl->hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 **sep;
|
||||||
void **dp;
|
|
||||||
struct strtbl_entry *se;
|
struct strtbl_entry *se;
|
||||||
|
struct hash_insert hi;
|
||||||
|
|
||||||
dp = hash_find(&tbl->hash, str, &hi);
|
sep = hash_find(&tbl->hash, str, &hi);
|
||||||
if (dp) {
|
if (sep) {
|
||||||
se = *dp;
|
se = *sep;
|
||||||
} else if (add) {
|
} else {
|
||||||
size_t bytes = strlen(str) + 1;
|
size_t bytes = strlen(str) + 1;
|
||||||
|
|
||||||
se = nasm_malloc(sizeof(struct strtbl_entry)-1+bytes);
|
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);
|
memcpy(se->str, str, bytes);
|
||||||
|
|
||||||
hash_add(&hi, se->str, se);
|
hash_add(&hi, se->str, se);
|
||||||
} else {
|
|
||||||
return STRTBL_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return se->index;
|
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 */
|
/* This create a linearized buffer containing the actual string table */
|
||||||
void *strtbl_generate(const struct nasm_strtbl *tbl)
|
void *strtbl_generate(const struct nasm_strtbl *tbl)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,7 +46,8 @@ struct nasm_strtbl {
|
||||||
|
|
||||||
void strtbl_init(struct nasm_strtbl *tbl);
|
void strtbl_init(struct nasm_strtbl *tbl);
|
||||||
void strtbl_free(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)
|
static inline size_t strtbl_size(const struct nasm_strtbl *tbl)
|
||||||
{
|
{
|
||||||
return tbl->size;
|
return tbl->size;
|
||||||
|
|
Loading…
Reference in a new issue