summaryrefslogtreecommitdiff
path: root/tern.c
diff options
context:
space:
mode:
Diffstat (limited to 'tern.c')
-rw-r--r--tern.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/tern.c b/tern.c
index f61e2aa..dda6497 100644
--- a/tern.c
+++ b/tern.c
@@ -6,6 +6,9 @@
#include "tern.h"
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "util.h"
tern_node * tern_insert(tern_node * head, char * key, tern_val value)
{
@@ -105,7 +108,11 @@ void * tern_find_ptr_default(tern_node * head, char * key, void * def)
{
tern_val ret;
if (tern_find(head, key, &ret)) {
- return ret.ptrval;
+ if (ret.intval & 1) {
+ return (void *)(ret.intval & ~1);
+ } else {
+ return ret.ptrval;
+ }
}
return def;
}
@@ -115,6 +122,32 @@ void * tern_find_ptr(tern_node * head, char * key)
return tern_find_ptr_default(head, key, NULL);
}
+tern_val tern_find_path_default(tern_node *head, char *key, tern_val def)
+{
+ tern_val ret;
+ while (*key)
+ {
+ if (!tern_find(head, key, &ret)) {
+ return def;
+ }
+ key = key + strlen(key) + 1;
+ if (*key) {
+ head = tern_get_node(ret);
+ if (!head) {
+ return def;
+ }
+ }
+ }
+ return ret;
+}
+
+tern_val tern_find_path(tern_node *head, char *key)
+{
+ tern_val def;
+ def.ptrval = NULL;
+ return tern_find_path_default(head, key, def);
+}
+
tern_node * tern_insert_ptr(tern_node * head, char * key, void * value)
{
tern_val val;
@@ -122,4 +155,72 @@ tern_node * tern_insert_ptr(tern_node * head, char * key, void * value)
return tern_insert(head, key, val);
}
+tern_node * tern_insert_node(tern_node *head, char *key, tern_node *value)
+{
+ tern_val val;
+ val.intval = ((intptr_t)value) | 1;
+ return tern_insert(head, key, val);
+}
+
+uint32_t tern_count(tern_node *head)
+{
+ uint32_t count = 0;
+ if (head->left) {
+ count += tern_count(head->left);
+ }
+ if (head->right) {
+ count += tern_count(head->right);
+ }
+ if (!head->el) {
+ count++;
+ } else if (head->straight.next) {
+ count += tern_count(head->straight.next);
+ }
+ return count;
+}
+
+#define MAX_ITER_KEY 127
+void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, int pos)
+{
+ if (!head->el) {
+ keybuf[pos] = 0;
+ fun(keybuf, head->straight.value, data);
+ }
+ if (head->left) {
+ tern_foreach_int(head->left, fun, data, keybuf, pos);
+ }
+ if (head->el) {
+ if (pos == MAX_ITER_KEY) {
+ fatal_error("tern_foreach_int: exceeded maximum key size");
+ }
+ keybuf[pos] = head->el;
+ tern_foreach_int(head->straight.next, fun, data, keybuf, pos+1);
+ }
+ if (head->right) {
+ tern_foreach_int(head->right, fun, data, keybuf, pos);
+ }
+}
+void tern_foreach(tern_node *head, iter_fun fun, void *data)
+{
+ //lame, but good enough for my purposes
+ char key[MAX_ITER_KEY+1];
+ tern_foreach_int(head, fun, data, key, 0);
+}
+
+char * tern_int_key(uint32_t key, char * buf)
+{
+ char * cur = buf;
+ while (key)
+ {
+ *(cur++) = (key & 0x7F) + 1;
+ key >>= 7;
+ }
+ *cur = 0;
+ return buf;
+}
+
+tern_node * tern_get_node(tern_val value)
+{
+ return value.intval & 1 ? (tern_node *)(value.intval & ~1) : NULL;
+}