diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-12-23 23:45:54 +0100 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-12-23 23:45:54 +0100 |
commit | 14e9d7b2299f15efb695b0202f9c1f6a9f7a4ba6 (patch) | |
tree | 31b3d9a6f9f6144b08b852d016b5b4bdfce553ef /src/utils/trie.c | |
parent | 8e62072d91193b4894adda9c40544c18c1a01f57 (diff) | |
download | blogc-14e9d7b2299f15efb695b0202f9c1f6a9f7a4ba6.tar.gz blogc-14e9d7b2299f15efb695b0202f9c1f6a9f7a4ba6.tar.bz2 blogc-14e9d7b2299f15efb695b0202f9c1f6a9f7a4ba6.zip |
Revert "build: removing src/utils and replacing with squareball"
This reverts commit 950e6c9148eca244a89d18a21d4ae4e5c3d1c646.
Diffstat (limited to 'src/utils/trie.c')
-rw-r--r-- | src/utils/trie.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/utils/trie.c b/src/utils/trie.c new file mode 100644 index 0000000..72a62f6 --- /dev/null +++ b/src/utils/trie.c @@ -0,0 +1,199 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdlib.h> +#include "utils.h" + + +b_trie_t* +b_trie_new(b_free_func_t free_func) +{ + b_trie_t *trie = b_malloc(sizeof(b_trie_t)); + trie->root = NULL; + trie->free_func = free_func; + return trie; +} + + +static void +b_trie_free_node(b_trie_t *trie, b_trie_node_t *node) +{ + if (node == NULL) + return; + if (node->data != NULL && trie->free_func != NULL) + trie->free_func(node->data); + b_trie_free_node(trie, node->next); + b_trie_free_node(trie, node->child); + free(node); +} + + +void +b_trie_free(b_trie_t *trie) +{ + if (trie == NULL) + return; + b_trie_free_node(trie, trie->root); + free(trie); +} + + +void +b_trie_insert(b_trie_t *trie, const char *key, void *data) +{ + if (data == NULL || key == NULL) + return; + + b_trie_node_t *parent = NULL; + b_trie_node_t *previous; + b_trie_node_t *current; + b_trie_node_t *tmp; + + while (1) { + + if (trie->root == NULL || (parent != NULL && parent->child == NULL)) { + current = b_malloc(sizeof(b_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + if (trie->root == NULL) + trie->root = current; + else + parent->child = current; + parent = current; + goto clean; + } + + tmp = parent == NULL ? trie->root : parent->child; + previous = NULL; + + while (tmp != NULL && tmp->key != *key) { + previous = tmp; + tmp = tmp->next; + } + + parent = tmp; + + if (previous == NULL || parent != NULL) + goto clean; + + current = b_malloc(sizeof(b_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + previous->next = current; + parent = current; + +clean: + if (*key == '\0') { + if (parent->data != NULL && trie->free_func != NULL) + trie->free_func(parent->data); + parent->data = data; + break; + } + key++; + } +} + + +void* +b_trie_lookup(b_trie_t *trie, const char *key) +{ + if (trie->root == NULL || key == NULL) + return NULL; + + b_trie_node_t *parent = trie->root; + b_trie_node_t *tmp; + while (1) { + for (tmp = parent; tmp != NULL; tmp = tmp->next) { + + if (tmp->key == *key) { + if (tmp->key == '\0') + return tmp->data; + parent = tmp->child; + break; + } + } + if (tmp == NULL) + return NULL; + + if (*key == '\0') + break; + key++; + } + return NULL; +} + + +static void +b_trie_size_node(b_trie_node_t *node, unsigned int *count) +{ + if (node == NULL) + return; + + if (node->key == '\0') + (*count)++; + + b_trie_size_node(node->next, count); + b_trie_size_node(node->child, count); +} + + +unsigned int +b_trie_size(b_trie_t *trie) +{ + if (trie == NULL) + return 0; + + unsigned int count = 0; + b_trie_size_node(trie->root, &count); + return count; +} + + +static void +b_trie_foreach_node(b_trie_node_t *node, b_string_t *str, void (*func)(const char *key, void *data)) +{ + if (node == NULL) + return; + + if (node->key == '\0') { + func(str->str, node->data); + b_string_free(str, true); + } + + if (node->child != NULL) { + b_string_t *child = b_string_new(); + child = b_string_append(child, str->str); + child = b_string_append_c(child, node->key); + b_trie_foreach_node(node->child, child, func); + } + + if (node->next != NULL) + b_trie_foreach_node(node->next, str, func); + + if (node->child != NULL && node->next == NULL) + b_string_free(str, true); +} + + +void +b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data)) +{ + if (trie->root == NULL) + return; + + b_string_t *str = b_string_new(); + b_trie_foreach_node(trie->root, str, func); +} |