From 0dfbbb5a5cdbd1c035a00207feaf5eb079b8762a Mon Sep 17 00:00:00 2001 From: rexy712 Date: Tue, 28 Jan 2020 16:53:02 -0800 Subject: [PATCH] Fix object member removal --- include/rjp.h | 2 ++ include/tree.h | 4 ++-- src/object.c | 16 +++++++++++++--- src/tree.c | 19 ++++++++++--------- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/include/rjp.h b/include/rjp.h index d362af1..af3125e 100644 --- a/include/rjp.h +++ b/include/rjp.h @@ -149,6 +149,8 @@ RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* rjp_add_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, RJP_value* value); RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key); RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member); +void rjp_free_member_by_key(RJP_value* obj, const char* key); +void rjp_free_member(RJP_value* obj, RJP_value* member); //add an element to a json array RJP_value* rjp_add_element(RJP_value* dest, RJP_value* value); RJP_value* rjp_new_element(RJP_value* dest, RJP_vinit* value); diff --git a/include/tree.h b/include/tree.h index 70857a6..d299f90 100644 --- a/include/tree.h +++ b/include/tree.h @@ -29,16 +29,16 @@ typedef struct RJP_object_iterator RJP_object_iterator; typedef struct RJP_tree_node RJP_tree_node; struct RJP_tree_node{ + RJP_object_member data; RJP_tree_node* parent; RJP_tree_node* left; RJP_tree_node* right; - RJP_object_member data; unsigned color:1; }; RJP_tree_node* irjp_new_node(RJP_object_member* value); RJP_tree_node* irjp_tree_insert_value(RJP_tree_node* root, RJP_object_member* value, RJP_value** added, int* status); -RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, int* status); +RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, RJP_value** removed_node, int* status); RJP_tree_node* irjp_tree_search_value(RJP_tree_node* root, const char* key); RJP_tree_node* irjp_copy_tree(const RJP_tree_node* root); void irjp_free_tree(RJP_tree_node* root); diff --git a/src/object.c b/src/object.c index 967f3a9..ca8148f 100644 --- a/src/object.c +++ b/src/object.c @@ -173,11 +173,21 @@ RJP_value* rjp_new_member_no_alloc(RJP_value* dest, char* key, RJP_index keylen, } RJP_value* rjp_remove_member_by_key(RJP_value* obj, const char* key){ int status; - return &(obj->object.root = irjp_tree_remove_value(obj->object.root, key, &status))->data.value; + RJP_value* removed; + obj->object.root = irjp_tree_remove_value(obj->object.root, key, &removed, &status); + if(removed) + rjp_free(((RJP_object_member*)removed)->name.value); + return removed; } RJP_value* rjp_remove_member(RJP_value* obj, RJP_value* member){ - int status; - return &(obj->object.root = irjp_tree_remove_value(obj->object.root, ((RJP_object_member*)member)->name.value, &status))->data.value; + return rjp_remove_member_by_key(obj, ((RJP_object_member*)member)->name.value); +} +void rjp_free_member_by_key(RJP_value* obj, const char* key){ + RJP_value* removed = rjp_remove_member_by_key(obj, key); + rjp_free_value(removed); +} +void rjp_free_member(RJP_value* obj, RJP_value* member){ + rjp_free_member_by_key(obj, ((RJP_object_member*)member)->name.value); } void rjp_set_key(RJP_value* dest, const char* key, RJP_index keylen){ diff --git a/src/tree.c b/src/tree.c index fdef773..1db43ee 100644 --- a/src/tree.c +++ b/src/tree.c @@ -49,7 +49,7 @@ static void irjp_delete_node(RJP_tree_node* node); 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); +static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target, RJP_value** removed_node); //Tree helpers @@ -336,29 +336,30 @@ void irjp_dbg_print_tree_bfs(RJP_tree_node* root){ #undef pop #undef push -RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, int* status){ +RJP_tree_node* irjp_tree_remove_value(RJP_tree_node* root, const char* key, RJP_value** removed_node, int* status){ if(!root){ + *removed_node = NULL; *status = RJP_TREE_ERR_NULL_ROOT; return root; } RJP_tree_node* n = irjp_tree_search_value(root, key); if(!n){ + *removed_node = NULL; *status = RJP_TREE_ERR_NOT_FOUND; return root; } *status = RJP_TREE_SUCCESS; - return irjp_tree_remove_node(n); + return irjp_tree_remove_node(n, removed_node); } -static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target){ - irjp_delete_node(target); +static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target, RJP_value** removed_node){ + if(removed_node) + *removed_node = (RJP_value*)target; while(target->right && target->left){ irjp_copy_node_data(target, target->right); target = target->right; } RJP_tree_node* retval = target->parent; - RJP_tree_node* to_delete = target; - do{ RJP_tree_node* child = (target->left) ? target->left : target->right; @@ -372,6 +373,8 @@ static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target){ child->color = BLACK; } irjp_replace_node(target, child); + if(!retval) + retval = child; break; } if(!target->parent){ @@ -449,8 +452,6 @@ static RJP_tree_node* irjp_tree_remove_node(RJP_tree_node* target){ } }while(1); - rjp_free(to_delete); - //return new root if(!retval) return NULL;