summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2017-04-24 00:41:21 -0700
committerH. Peter Anvin <hpa@zytor.com>2017-04-24 00:54:51 -0700
commitbbb39579ec340aba9cda4c7033dd934b620423ea (patch)
tree94a5e00fc63672d2ec15feab825e3c295bfe4111
parentbf0bcef3d4975ab964d573fecbe2a8b2960b8120 (diff)
downloadnasm-bbb39579ec340aba9cda4c7033dd934b620423ea.tar.gz
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>
-rw-r--r--include/hashtbl.h1
-rw-r--r--nasmlib/hashtbl.c26
-rw-r--r--nasmlib/srcfile.c8
-rw-r--r--output/strtbl.c40
-rw-r--r--output/strtbl.h3
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;