From 6f47796dc0761fac359ec59ce26c7af5154e538d Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 4 Mar 2020 00:28:04 +0100 Subject: Add a deep copy function for the str_table_t helper Signed-off-by: David Oberhollenzer --- include/str_table.h | 2 ++ lib/util/str_table.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) 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; -- cgit v1.2.3