diff tern.c @ 803:236a184bf6f0

Merge
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Jul 2015 16:51:03 -0700
parents 724bbec47f86
children 110251ea369e
line wrap: on
line diff
--- a/tern.c	Sun Jul 26 16:48:25 2015 -0700
+++ b/tern.c	Sun Jul 26 16:51:03 2015 -0700
@@ -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 @@
 {
 	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 @@
 	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 @@
 	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;
+}