Fix object member removal
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
16
src/object.c
16
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){
|
||||
|
||||
19
src/tree.c
19
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;
|
||||
|
||||
Reference in New Issue
Block a user