From 6e53fe29e28465a169e6f91941992af5e0ea6d7f Mon Sep 17 00:00:00 2001 From: rexy712 Date: Mon, 13 Jan 2020 13:22:49 -0800 Subject: [PATCH] Fix memory management of trees --- include/tree.h | 7 +- src/tree.c | 184 +++++++++++++++++++++++-------------------------- 2 files changed, 91 insertions(+), 100 deletions(-) diff --git a/include/tree.h b/include/tree.h index 617a997..21f4acc 100644 --- a/include/tree.h +++ b/include/tree.h @@ -23,10 +23,11 @@ struct RJP_tree_node{ }; RJP_tree_node* irjp_new_node(RJP_object_member value); -RJP_tree_node* irjp_insert_value(RJP_tree_node* root, RJP_object_member value, int* status); -RJP_tree_node* irjp_remove_value(RJP_tree_node* root, RJP_object_member value, int* status); -RJP_tree_node* irjp_search_value(RJP_tree_node* root, RJP_object_member value); +RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member value, int* status); +RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, RJP_object_member value, int* status); +RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, RJP_object_member value); RJP_tree_node* irjp_copy_tree(RJP_tree_node* root); +void irjp_free_tree(RJP_tree_node* root); int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root); void irjp_delete_object_iterator(RJP_object_iterator* it); diff --git a/src/tree.c b/src/tree.c index 4ba1192..0b3c4a8 100644 --- a/src/tree.c +++ b/src/tree.c @@ -4,6 +4,8 @@ #include #include +#include "strings.h" + #define BLACK 0 #define RED 1 @@ -12,9 +14,11 @@ #define rjp_malloc malloc #define rjp_free free #define rjp_free_value(x) - +#define irjp_strcpy(dest, src) do{(dest)->value = rjp_malloc((src)->length + 1);strcpy((dest)->value, (src)->value);(dest)->value[(src)->length] = 0;(dest)->length = (src)->length;}while(0); +#define rjp_copy_value(dest, src) ((dest)->integer = (src)->integer) #define RJP_TREE_ITERATOR_STACK_START_SIZE 32 +//Internal use only structs typedef struct RJP_tree_stack{ RJP_tree_node** data; int size; @@ -25,14 +29,22 @@ typedef struct RJP_object_iterator{ RJP_tree_node* current; }RJP_object_iterator; - -static RJP_tree_node* irjp_insert_node(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode); -static RJP_tree_node* irjp_insert_impl(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode); -static RJP_tree_node* irjp_repair_tree(RJP_tree_node* node); -static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src); +//Forward declare static functions +static inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n); +static inline RJP_tree_node* irjp_sibling(RJP_tree_node* n); +static inline RJP_tree_node* irjp_uncle(RJP_tree_node* n); +static inline RJP_tree_node* irjp_rotate_left(RJP_tree_node* pivot); +static inline RJP_tree_node* irjp_rotate_right(RJP_tree_node* pivot); +static inline int irjp_is_inside_left(RJP_tree_node* n); +static inline int irjp_is_inside_right(RJP_tree_node* n); static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restrict child); + +static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src); +static RJP_tree_node* irjp_clone_node(RJP_tree_node* src, RJP_tree_node* parent); +static RJP_tree_node* irjp_copy_node(RJP_tree_node* root, RJP_tree_node* parent); static void irjp_free_node(RJP_tree_node* node); -static RJP_tree_node* irjp_remove_node(RJP_tree_node* target); +static void irjp_delete_node(RJP_tree_node* node); + static int irjp_init_tree_stack(RJP_tree_stack* stack); static void irjp_delete_tree_stack(RJP_tree_stack* stack); static void irjp_resize_tree_stack(RJP_tree_stack* stack); @@ -40,6 +52,13 @@ static void irjp_push_tree_stack(RJP_tree_stack* stack, RJP_tree_node* value); static RJP_tree_node* irjp_pop_tree_stack(RJP_tree_stack* stack); static RJP_tree_node* irjp_peek_tree_stack(RJP_tree_stack* stack); +static RJP_tree_node* irjp_tree_insert_node(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode); +static RJP_tree_node* irjp_tree_insert_impl(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode); +static RJP_tree_node* irjp_tree_repair(RJP_tree_node* node); +static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target); + + +//Tree helpers static inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n){ if(!n->parent) return NULL; @@ -100,9 +119,6 @@ static inline int irjp_is_inside_right(RJP_tree_node* n){ RJP_tree_node* g = irjp_grandparent(n); return n == p->left && p == g->right; } -static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){ - dest->data = src->data; -} static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restrict child){ if(child) child->parent = node->parent; @@ -113,12 +129,8 @@ static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restr else node->parent->right = child; } -static void irjp_free_node(RJP_tree_node* node){ - rjp_free(node->data.name.value); - rjp_free_value(&node->data.value); - rjp_free(node); -} +//Node construction / destruction RJP_tree_node* irjp_new_node(RJP_object_member value){ RJP_tree_node* node = rjp_malloc(sizeof(RJP_tree_node)); node->data.name = value.name; @@ -126,8 +138,37 @@ RJP_tree_node* irjp_new_node(RJP_object_member value){ node->parent = node->left = node->right = NULL; return node; } +static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){ + dest->data = src->data; +} +static RJP_tree_node* irjp_clone_node(RJP_tree_node* src, RJP_tree_node* parent){ + RJP_tree_node* dest = rjp_malloc(sizeof(RJP_tree_node)); + rjp_copy_value(&dest->data.value, &src->data.value); + irjp_strcpy(&dest->data.name, &src->data.name); + dest->parent = parent; + return dest; +} +static RJP_tree_node* irjp_copy_node(RJP_tree_node* root, RJP_tree_node* parent){ + if(!root){ + return NULL; + } + RJP_tree_node* newnode = irjp_clone_node(root, parent); + newnode->left = irjp_copy_node(root->left, newnode); + newnode->right = irjp_copy_node(root->right, newnode); + return newnode; +} +static void irjp_free_node(RJP_tree_node* node){ + irjp_delete_node(node); + rjp_free(node); +} +static void irjp_delete_node(RJP_tree_node* node){ + rjp_free(node->data.name.value); + rjp_free_value(&node->data.value); +} + /* TREE STACK */ +//Stack construction / destruction static int irjp_init_tree_stack(RJP_tree_stack* stack){ stack->data = rjp_malloc(sizeof(RJP_tree_node*)*RJP_TREE_ITERATOR_STACK_START_SIZE); stack->size = RJP_TREE_ITERATOR_STACK_START_SIZE; @@ -147,6 +188,7 @@ static void irjp_resize_tree_stack(RJP_tree_stack* stack){ stack->data = newdata; stack->size = newsize; } +//Stack operations static void irjp_push_tree_stack(RJP_tree_stack* stack, RJP_tree_node* value){ stack->data[stack->pos++] = value; if(stack->pos == stack->size) @@ -160,6 +202,7 @@ static RJP_tree_node* irjp_peek_tree_stack(RJP_tree_stack* stack){ } /* TREE ITERATOR */ +//Iterator construction / destruction int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root){ irjp_init_tree_stack(&it->stack); it->current = root; @@ -173,6 +216,7 @@ int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root){ void irjp_delete_object_iterator(RJP_object_iterator* it){ irjp_delete_tree_stack(&it->stack); } +//Iterator operations RJP_tree_node* irjp_object_iterator_next(RJP_object_iterator* it){ RJP_tree_node* last = irjp_pop_tree_stack(&it->stack); if(last->right){ @@ -185,30 +229,34 @@ RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it){ } /* TREE */ +//Tree construction / destruction RJP_tree_node* irjp_copy_tree(RJP_tree_node* root){ - if(!root) - return NULL; - RJP_tree_node* newnode = irjp_new_node(root->data); - newnode->left = irjp_copy_tree(root->left); - newnode->right = irjp_copy_tree(root->right); - return newnode; + return irjp_copy_node(root, NULL); } -RJP_tree_node* irjp_insert_value(RJP_tree_node* root, RJP_object_member value, int* status){ +void irjp_free_tree(RJP_tree_node* root){ + if(!root) + return; + irjp_free_tree(root->left); + irjp_free_tree(root->right); + irjp_free_node(root); +} +//Tree operations +RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member value, int* status){ *status = RJP_TREE_SUCCESS; if(!root){ root = irjp_new_node(value); return root; } - return irjp_insert_node(root, irjp_new_node(value)); + return irjp_tree_insert_node(root, irjp_new_node(value)); } -static RJP_tree_node* irjp_insert_node(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode){ - irjp_insert_impl(root, newnode); - irjp_repair_tree(newnode); +static RJP_tree_node* irjp_tree_insert_node(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode){ + irjp_tree_insert_impl(root, newnode); + irjp_tree_repair(newnode); while(root->parent) root = root->parent; return root; } -static RJP_tree_node* irjp_insert_impl(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode){ +static RJP_tree_node* irjp_tree_insert_impl(RJP_tree_node *restrict root, RJP_tree_node *restrict newnode){ if(!root){ return newnode; } @@ -236,7 +284,7 @@ static RJP_tree_node* irjp_insert_impl(RJP_tree_node *restrict root, RJP_tree_no } return newnode; } -static RJP_tree_node* irjp_repair_tree(RJP_tree_node* node){ +static RJP_tree_node* irjp_tree_repair(RJP_tree_node* node){ node->color = RED; while(1){ if(!node->parent){ @@ -270,7 +318,7 @@ static RJP_tree_node* irjp_repair_tree(RJP_tree_node* node){ } } -RJP_tree_node* irjp_search_value(RJP_tree_node* root, RJP_object_member value){ +RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, RJP_object_member value){ while(root != NULL){ int cmpval = strcmp(value.name.value, root->data.name.value); if(cmpval < 0){ @@ -283,6 +331,7 @@ RJP_tree_node* irjp_search_value(RJP_tree_node* root, RJP_object_member value){ } return NULL; } +//Debug printouts void irjp_dbg_print_tree(RJP_tree_node* root){ if(!root){ return; @@ -346,21 +395,25 @@ void irjp_dbg_print_tree_bfs(RJP_tree_node* root){ } printf("\n"); } +#undef pop +#undef push -RJP_tree_node* irjp_remove_value(RJP_tree_node* root, RJP_object_member value, int* status){ +RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, RJP_object_member value, int* status){ if(!root){ *status = RJP_TREE_ERR_NULL_ROOT; return root; } - RJP_tree_node* n = irjp_search_value(root, value); + RJP_tree_node* n = irjp_tree_search_value(root, value); if(!n){ *status = RJP_TREE_ERR_NOT_FOUND; return root; } *status = RJP_TREE_SUCCESS; - return irjp_remove_node(n); + return irjp_tree_remove_node(n); } -static RJP_tree_node* irjp_remove_node(RJP_tree_node* target){ +static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target){ + irjp_delete_node(target); + while(target->right && target->left){ irjp_copy_node_data(target, target->right); target = target->right; @@ -454,9 +507,7 @@ static RJP_tree_node* irjp_remove_node(RJP_tree_node* target){ }while(1); irjp_replace_node(to_delete, NULL); - to_delete->data.name.value = NULL; - to_delete->data.value.type = rjp_json_null; - irjp_free_node(to_delete); + rjp_free(to_delete); //return new root if(!retval) @@ -465,65 +516,4 @@ static RJP_tree_node* irjp_remove_node(RJP_tree_node* target){ retval = retval->parent; return retval; } -/*void irjp_handle_del_with_red_sibling(RJP_tree_node* n){ - RJP_tree_node* sibling = irjp_sibling(n); - if(s->color == RED){ - sibling->color = BLACK; - n->parent->color = RED; - if(target == parent->left) - irjp_rotate_left(parent); - else - irjp_rotate_right(parent); - }else{ - irjp_handle_del_with_black_parent_sibling_niblings(n); - } -void irjp_handle_del_with_black_parent_sibling_niblings(RJP_tree_node* n){ - RJP_tree_node* sibling = irjp_sibling(n); - if(n->parent->color == BLACK && sibling->color == BLACK && - ((!sibling->left) || sibling->left->color == BLACK) && - ((!sibling->right) || sibling->right->color == BLACK) - { - sibling->color = RED; - irjp_handle_del_root(n->parent); - }else{ - irjp_handle_del_with_black_sibling_niblings_red_parent(n); - } -} -void irjp_handle_del_with_black_sibling_niblings_red_parent(RJP_tree_node* n){ - RJP_tree_node* sibling = irjp_sibling(n); - if(n->parent->color == RED && sibling->color == BLACK && - ((!sibling->left) || sibling->left->color == BLACK) && - ((!sibling->right) || sibling->right->color == BLACK) - { - sibling->color = RED; - n->parent->color = BLACK; - }else{ - irjp_handle_del_with_black_sibling_rnibling_black_lnibling(n); - } -} -void irjp_handle_del_with_black_sibling_rnibling_black_lnibling(RJP_tree_node* n){ - RJP_tree_node* sibling = irjp_sibling(n); - if((n == n->parent->left) && (sibling->right->color == BLACK) && (sibling->left->color == RED)){ - sibling->color = RED; - s->left->color = BLACK; - irjp_rotate_right(sibling); - }else if((n == n->parent->right) && (sibling->right->color == RED) && (sibling->left->color == BLACK)){ - sibling->color = RED; - s->right->color = BLACK; - irjp_rotate_left(sibling); - } - irjp_handle_del_with_black_sibling_lnibling_black_rnibling_red(n); -} -void irjp_handle_del_with_black_sibling_lnibling_black_rnibling_red(RJP_tree_node* n){ - RJP_tree_node* sibling = irjp_sibling(n); - sibling->color = n->parent->color; - n->parent->color = BLACK; - if(n == n->parent->left){ - sibling->right->color = BLACK; - irjp_rotate_left(n->parent); - }else{ - sibling->left->color = BLACK; - irjp_rotate_right(n->parent); - } -}*/