diff tern.c @ 1692:5dacaef602a7 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Jan 2019 00:58:08 -0800
parents 63659fb92db4
children 193b804c9845
line wrap: on
line diff
--- a/tern.c	Tue Dec 19 00:49:13 2017 -0800
+++ b/tern.c	Sat Jan 05 00:58:08 2019 -0800
@@ -45,6 +45,12 @@
 		(*cur)->left = NULL;
 		(*cur)->right = NULL;
 		(*cur)->el = 0;
+		(*cur)->valtype = TVAL_NONE;
+	}
+	if ((*cur)->valtype == TVAL_PTR) {
+		//not freeing tern nodes can also cause leaks, but handling freeing those here is problematic
+		//since updating a sub-tree may involve creating a new root node
+		free((*cur)->straight.value.ptrval);
 	}
 	(*cur)->straight.value = value;
 	(*cur)->valtype = valtype;
@@ -132,6 +138,39 @@
 	return NULL;
 }
 
+uint8_t tern_delete(tern_node **head, char const *key, tern_val *out)
+{
+	tern_node *cur = *head, **last = head;
+	while (cur)
+	{
+		if (cur->el == *key) {
+			if (*key) {
+				last = &cur->straight.next;
+				cur = cur->straight.next;
+				key++;
+			} else {
+				break;
+			}
+		} else if (*key < cur->el) {
+			last = &cur->left;
+			cur = cur->left;
+		} else {
+			last = &cur->right;
+			cur = cur->right;
+		}
+	}
+	if (!cur) {
+		return TVAL_NONE;
+	}
+	*last = cur->right;
+	uint8_t valtype = cur->valtype;
+	if (out) {
+		*out = cur->straight.value;
+	}
+	free(cur);
+	return valtype;
+}
+
 tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype)
 {
 	tern_val ret;
@@ -175,6 +214,37 @@
 	return tern_insert(head, key, val, TVAL_NODE);
 }
 
+tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint8_t valtype)
+{
+	const char *next_key = key + strlen(key) + 1;
+	if (*next_key) {
+		tern_node *child = tern_find_node(head, key);
+		child = tern_insert_path(child, next_key, val, valtype);
+		return tern_insert_node(head, key, child);
+	} else {
+		return tern_insert(head, key, val, valtype);
+	}
+}
+
+uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out)
+{
+	const char *next_key = key + strlen(key) + 1;
+	if (*next_key) {
+		tern_node *child = tern_find_node(*head, key);
+		if (!child) {
+			return TVAL_NONE;
+		}
+		tern_node *tmp = child;
+		uint8_t valtype = tern_delete_path(&tmp, next_key, out);
+		if (tmp != child) {
+			*head = tern_insert_node(*head, key, tmp);
+		}
+		return valtype;
+	} else {
+		return tern_delete(head, key, out);
+	}
+}
+
 uint32_t tern_count(tern_node *head)
 {
 	uint32_t count = 0;
@@ -202,7 +272,7 @@
 	if (head->left) {
 		tern_foreach_int(head->left, fun, data, keybuf, pos);
 	}
-	if (head->el) {
+	if (head->el && head->straight.next) {
 		if (pos == MAX_ITER_KEY) {
 			fatal_error("tern_foreach_int: exceeded maximum key size");
 		}