mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-15 09:09:58 +08:00
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
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user