Mercurial > repos > blastem
diff tern.c @ 1648:b7ecd0d6a77b mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 25 Dec 2018 11:12:26 -0800 |
parents | 63659fb92db4 |
children | 193b804c9845 |
line wrap: on
line diff
--- a/tern.c Sun Dec 31 10:11:16 2017 -0800 +++ b/tern.c Tue Dec 25 11:12:26 2018 -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"); }