aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-03-04 00:28:04 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-03-04 00:28:39 +0100
commit6f47796dc0761fac359ec59ce26c7af5154e538d (patch)
tree14c5c99605cffc4fc3a68fc473324372029d9a6b
parent37485168b9a9ab870f5d8bf01da8cccb325f6de4 (diff)
Add a deep copy function for the str_table_t helper
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--include/str_table.h2
-rw-r--r--lib/util/str_table.c63
2 files changed, 65 insertions, 0 deletions
diff --git a/include/str_table.h b/include/str_table.h
index 61f8aa5..a843e62 100644
--- a/include/str_table.h
+++ b/include/str_table.h
@@ -33,6 +33,8 @@ SQFS_INTERNAL int str_table_init(str_table_t *table, size_t size);
SQFS_INTERNAL void str_table_cleanup(str_table_t *table);
+SQFS_INTERNAL int str_table_copy(str_table_t *dst, const str_table_t *src);
+
/* Resolve a string to an incremental, unique ID. */
SQFS_INTERNAL
int str_table_get_index(str_table_t *table, const char *str, size_t *idx);
diff --git a/lib/util/str_table.c b/lib/util/str_table.c
index c0a364f..cea34dc 100644
--- a/lib/util/str_table.c
+++ b/lib/util/str_table.c
@@ -62,6 +62,69 @@ int str_table_init(str_table_t *table, size_t size)
return 0;
}
+int str_table_copy(str_table_t *dst, const str_table_t *src)
+{
+ str_bucket_t *bucket, *it, **next;
+ size_t i;
+
+ dst->num_strings = src->num_strings;
+ dst->max_strings = src->max_strings;
+ dst->strings = calloc(sizeof(dst->strings[0]), src->num_strings);
+
+ if (dst->strings == NULL)
+ return -1;
+
+ for (i = 0; i < src->num_strings; ++i) {
+ dst->strings[i] = strdup(src->strings[i]);
+
+ if (dst->strings[i] == NULL)
+ goto fail_str;
+ }
+
+ dst->num_buckets = src->num_buckets;
+ dst->buckets = calloc(sizeof(dst->buckets[0]), src->num_buckets);
+
+ if (dst->buckets == NULL)
+ goto fail_str;
+
+ for (i = 0; i < src->num_buckets; ++i) {
+ next = &(dst->buckets[i]);
+
+ for (it = src->buckets[i]; it != NULL; it = it->next) {
+ bucket = malloc(sizeof(*bucket));
+ if (bucket == NULL)
+ goto fail_buck;
+
+ bucket->next = NULL;
+ bucket->index = it->index;
+ bucket->refcount = it->refcount;
+ bucket->str = dst->strings[bucket->index];
+
+ *next = bucket;
+ next = &(bucket->next);
+ }
+ }
+
+ return 0;
+fail_buck:
+ for (i = 0; i < dst->num_buckets; ++i) {
+ while (dst->buckets[i] != NULL) {
+ bucket = dst->buckets[i];
+ dst->buckets[i] = bucket->next;
+
+ free(bucket);
+ }
+ }
+ free(dst->buckets);
+fail_str:
+ for (i = 0; i < dst->num_strings; ++i)
+ free(dst->strings[i]);
+
+ free(dst->strings);
+ dst->strings = NULL;
+ return -1;
+}
+
void str_table_cleanup(str_table_t *table)
{
str_bucket_t *bucket;