summaryrefslogtreecommitdiff
path: root/tern.c
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-07-05 14:21:34 -0700
committerMichael Pavone <pavone@retrodev.com>2015-07-05 14:21:34 -0700
commit0be7e726ad839d36d50db630b24ea0f1dc141c08 (patch)
treed8c8961bc1f6b0103d7c46be085e09377ff402f9 /tern.c
parent249115277c7f488052e07ccbd91f0df9f24f26b7 (diff)
WIP changes to support reading cart memory map from ROM DB
Diffstat (limited to 'tern.c')
-rw-r--r--tern.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/tern.c b/tern.c
index 73ea08d..2929bd6 100644
--- a/tern.c
+++ b/tern.c
@@ -6,6 +6,8 @@
#include "tern.h"
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
tern_node * tern_insert(tern_node * head, char * key, tern_val value)
{
@@ -115,6 +117,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,6 +150,60 @@ 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) {
+ fputs("exceeded maximum key size", stderr);
+ exit(1);
+ }
+ keybuf[pos] = head->el;
+ tern_foreach_int(head->straight.next, fun, data, keybuf, pos+1);
+ }
+ if (head->right) {
+ tern_foreach_int(head->left, 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;
@@ -133,3 +215,8 @@ char * tern_int_key(uint32_t key, char * buf)
*cur = 0;
return buf;
}
+
+tern_node * tern_get_node(tern_val value)
+{
+ return value.intval & 1 ? (tern_node *)(value.intval & ~1) : NULL;
+}