diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 12:56:54 -0300 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 12:56:54 -0300 |
commit | 0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b (patch) | |
tree | 212c4d2ac7e269cc9f03f2240e36f865d4ce2493 /src/utils/trie.c | |
parent | a8e0fedb3f12ed1ceda7879944606c8e1e7d4a08 (diff) | |
download | blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.tar.gz blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.tar.bz2 blogc-0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b.zip |
initial structure
Diffstat (limited to 'src/utils/trie.c')
-rw-r--r-- | src/utils/trie.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/utils/trie.c b/src/utils/trie.c new file mode 100644 index 0000000..f447860 --- /dev/null +++ b/src/utils/trie.c @@ -0,0 +1,193 @@ +/* + * 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 COPYING. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "utils.h" + + +b_trie_t* +b_trie_new(void (*free_func)(void *ptr)) +{ + b_trie_t *trie = 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) +{ + 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 = 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 = 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') { + 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); +} |