Fix object member removal

This commit is contained in:
rexy712
2020-01-28 16:53:02 -08:00
parent ff241e2a6f
commit 0dfbbb5a5c
4 changed files with 27 additions and 14 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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){

View File

@@ -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;