From d46183860c1f3f10095e95023adcb79b1896ab0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Fri, 22 Mar 2019 20:11:11 +0100 Subject: Move C and Scheme code into subdirs. --- src/trie.inc.h | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/trie.inc.h (limited to 'src/trie.inc.h') diff --git a/src/trie.inc.h b/src/trie.inc.h new file mode 100644 index 00000000..ffc8ac8e --- /dev/null +++ b/src/trie.inc.h @@ -0,0 +1,228 @@ +#ifndef TYPE +#error "Set TYPE before including self file" +#else + +#include + +#include "err.h" +#include "macro.h" +#include "linked_list.inc.h" +#include "strbuf.h" + +INIT_F ( TRIE(TYPE) ) { + NEW(TRIE_NODE(TYPE), t, '\0'); + self->root = t; + return 0; +} + +INIT_F (TRIE_NODE(TYPE), char c) { + self->c = c; + self->value = NULL; + self->next = NULL; + self->child = NULL; + return 0; +} + +INIT_F (TRIE_NODE(TYPE), + char c, + TRIE_NODE(TYPE)* next, + TRIE_NODE(TYPE)* child ) +{ + self->c = c; + self->next = next; + self->child = child; + return 0; +} + +int PUSH(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key, TYPE* val ) { + TRIE_NODE(TYPE) *cur, *last; + + last = trie->root; + cur = last->child; + + char* subkey = key; + + while (1) { + if (cur == NULL) { + /* Build direct LL for remaining subkey */ + for (char* c = subkey; c[0] != '\0'; c++) { + NEW(TRIE_NODE(TYPE), t, *c); + last->child = t; + last = t; + } + last->value = RESOLVE(TYPE)(last->value, val); + return 0; + } else if (cur->c == subkey[0]) { + /* This node belongs to the key, + * Decend further */ + last = cur; + cur = cur->child; + subkey++; + } else if (subkey[0] == '\0') { + /* Key finished */ + last->value = RESOLVE(TYPE)(last->value, val); + return 0; + } else if (cur->next != NULL) { + /* This node was not part of the set, but it's sibling might */ + cur = cur->next; + /* `last` not set since we aren't moving down */ + } else { + /* No node on self level was part of the set, create a new__ + * sibling and follow down that parse */ + NEW(TRIE_NODE(TYPE), t, *subkey); + cur->next = t; + last = cur; + cur = t; + } + } + + return 0; +} + +/* + * TODO what happens when I give an invalid key? + */ +TYPE* GET(TRIE(TYPE)) ( TRIE(TYPE)* trie, char* key ) { + TRIE_NODE(TYPE)* n = trie->root->child; + char* subkey = key; + + while (n != NULL) { + if (subkey[1] == '\0') { + /* Wanted node found, + * value can however be NULL */ + return n->value; + } else if (subkey[0] == n->c) { + n = n->child; + subkey++; + } else { + n = n->next; + } + } + + /* Position not found */ + return 0; +} + +FREE_F(TRIE_NODE(TYPE)) { + if (self == NULL) return 0; + if (self->value != NULL) FFREE(TYPE, self->value); + if (self->next != NULL) FREE(TRIE_NODE(TYPE))(self->next); + if (self->child != NULL) FREE(TRIE_NODE(TYPE))(self->child); + free (self); + return 0; +} + +FREE_F(TRIE(TYPE)) { + if (self->root->c != '\0') { + // ERR("Invalid trie"); + return 1; + } + return FREE(TRIE_NODE(TYPE))(self->root); +} + +int EMPTY(TRIE(TYPE))(TRIE(TYPE)* self) { + return self->root->child == NULL; +} + +FMT_F(TRIE_NODE(TYPE)) { + + va_list ap; + va_start(ap, buf); + int argc = va_arg(ap, int); + int depth = argc >= 1 + ? va_arg(ap, int) + : 0; + va_end(ap); + + int seek = 0; + + TRIE_NODE(TYPE)* n = self; + + if (n == NULL) { fmtf("\n"); } + while (n != NULL) { + fmtf("|"); + // FOR(int, i, depth) fmtf(" "); + for (int i = 0; i < depth; i++) fmtf(" "); + fmtf("%c ", n->c == '\0' ? '0' : n->c); + if (n->value != NULL) { + seek += FMT(TYPE)(n->value, buf + seek); + fmtf("\n"); + } + + if (n->child != NULL) { + fmtf("\n"); + seek += FMT(TRIE_NODE(TYPE))(n->child, buf + seek, depth + 1); + } + n = n->next; + } + return seek; + +} + +FMT_F(TRIE(TYPE)) { + int seek = 0; + fmtf("Trie: %p: {", self); + if (EMPTY(TRIE(TYPE))(self)) { + fmtf(" [EMPTY] "); + } else { + fmtf("\n"); + seek += FMT(TRIE_NODE(TYPE))(self->root->child, buf + seek); + } + fmtf("}"); + return seek; +} + +int DEEP_COPY(TRIE_NODE(TYPE)) (TRIE_NODE(TYPE)* dest, TRIE_NODE(TYPE)* src) { + dest->c = src->c; + + if (src->value != NULL) { + RENEW(TYPE, dest->value); + DEEP_COPY(TYPE)(dest->value, src->value); + } + + if (src->next != NULL) { + RENEW(TRIE_NODE(TYPE), dest->next, '\0'); + DEEP_COPY(TRIE_NODE(TYPE))(dest->next, src->next); + } + + if (src->child != NULL) { + RENEW(TRIE_NODE(TYPE), dest->child, '\0'); + DEEP_COPY(TRIE_NODE(TYPE))(dest->child, src->child); + } + + return 0; +} + +int DEEP_COPY(TRIE(TYPE)) (TRIE(TYPE)* dest, TRIE(TYPE)* src) { + return DEEP_COPY(TRIE_NODE(TYPE))(dest->root, src->root); +} + +void KEYS(TRIE_NODE(TYPE)) (TRIE_NODE(TYPE)* node, LLIST(strbuf)* list, strbuf* path) { + if (node == NULL) return; + + + if (node->value != NULL) { + strbuf_append(path, node->c); + NEW(strbuf, c); + DEEP_COPY(strbuf)(c, path); + PUSH(LLIST(strbuf))(list, c); + strbuf_pop(path); + } + if (node->next != NULL) { + KEYS(TRIE_NODE(TYPE)) (node->next, list, path); + } + if (node->child != NULL) { + if (node->c != '\0') strbuf_append(path, node->c); + KEYS(TRIE_NODE(TYPE)) (node->child, list, path); + if (node->c != '\0') strbuf_pop(path); + } +} + +LLIST(strbuf)* KEYS(TRIE(TYPE)) (TRIE(TYPE)* trie) { + NEW(LLIST(strbuf), retlist); + SNEW(strbuf, key); + KEYS(TRIE_NODE(TYPE)) (trie->root, retlist, &key); + return retlist; +} + +#endif /* TYPE */ -- cgit v1.2.3