diff --git a/include/ref_trie.h b/include/ref_trie.h index 4186075..fea6128 100644 --- a/include/ref_trie.h +++ b/include/ref_trie.h @@ -53,6 +53,14 @@ typedef struct libab_ref_trie_s libab_ref_trie; * @param trie the trie to initialize. */ void libab_ref_trie_init(libab_ref_trie* trie); +/** + * Initializes a new trie with a shallow copy of another. + * @param trie the trie to initialize. + * @param copy_of the trie to copy. + * @return the result of the initialization. + */ +libab_result libab_ref_trie_init_copy(libab_ref_trie* trie, + const libab_ref_trie* copy_of); /** * Stores a reference counted value into the trie. * This releases the reference for the given key, if one diff --git a/src/ref_trie.c b/src/ref_trie.c index ec320d9..72d3b28 100644 --- a/src/ref_trie.c +++ b/src/ref_trie.c @@ -6,6 +6,62 @@ void libab_ref_trie_init(libab_ref_trie* trie) { trie->head = NULL; } +void _libab_ref_trie_free(libab_ref_trie_node* node) { + if (node == NULL) + return; + _libab_ref_trie_free(node->next); + _libab_ref_trie_free(node->child); + libab_ref_free(&node->ref); + free(node); +} + +libab_result _libab_ref_trie_copy(const libab_ref_trie_node* copy_of, + libab_ref_trie_node** copy_into) { + libab_result result = LIBAB_SUCCESS; + + if(copy_of == NULL) { + *copy_into = NULL; + } else if(((*copy_into) = malloc(sizeof(**copy_into)))) { + (*copy_into)->child = NULL; + (*copy_into)->next = NULL; + + result = _libab_ref_trie_copy(copy_of->next, &(*copy_into)->next); + if(result == LIBAB_SUCCESS) { + result = _libab_ref_trie_copy(copy_of->child, &(*copy_into)->child); + } + + if(result == LIBAB_SUCCESS) { + (*copy_into)->key = copy_of->key; + libab_ref_copy(©_of->ref, &(*copy_into)->ref); + } + } else { + result = LIBAB_MALLOC; + } + + if(result != LIBAB_SUCCESS && *copy_into) { + _libab_ref_trie_free((*copy_into)->next); + _libab_ref_trie_free((*copy_into)->child); + free(*copy_into); + *copy_into = NULL; + } + + return result; +} + +libab_result libab_ref_trie_init_copy(libab_ref_trie* trie, + const libab_ref_trie* copy_of) { + libab_result result = LIBAB_SUCCESS; + + libab_ref_trie_init(trie); + result = _libab_ref_trie_copy(copy_of->head, &trie->head); + + if(result != LIBAB_SUCCESS) { + libab_ref_trie_free(trie); + } + + return result; +} + libab_result _libab_ref_trie_put(libab_ref_trie_node** node, const char* key, libab_ref* ref) { libab_result result = LIBAB_SUCCESS; @@ -80,15 +136,6 @@ const libab_ref* libab_ref_trie_get(const libab_ref_trie* trie, return &trie->null_ref; } -void _libab_ref_trie_free(libab_ref_trie_node* node) { - if (node == NULL) - return; - _libab_ref_trie_free(node->next); - _libab_ref_trie_free(node->child); - libab_ref_free(&node->ref); - free(node); -} - void libab_ref_trie_free(libab_ref_trie* trie) { _libab_ref_trie_free(trie->head); libab_ref_free(&trie->null_ref);