diff --git a/include/tree.h b/include/tree.h index 313a72c..617a997 100644 --- a/include/tree.h +++ b/include/tree.h @@ -12,7 +12,7 @@ typedef struct RJP_object_member{ RJP_value value; }RJP_object_member; -struct RJP_tree_node; +typedef struct RJP_object_iterator RJP_object_iterator; typedef struct RJP_tree_node RJP_tree_node; struct RJP_tree_node{ RJP_tree_node* parent; @@ -26,6 +26,13 @@ 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_copy_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); +RJP_tree_node* irjp_object_iterator_next(RJP_object_iterator* it); +RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it); + void irjp_dbg_print_tree(RJP_tree_node* root); void irjp_dbg_print_tree_bfs(RJP_tree_node* root); diff --git a/src/tree.c b/src/tree.c index 00dad9b..4ba1192 100644 --- a/src/tree.c +++ b/src/tree.c @@ -13,13 +13,32 @@ #define rjp_free free #define rjp_free_value(x) +#define RJP_TREE_ITERATOR_STACK_START_SIZE 32 + +typedef struct RJP_tree_stack{ + RJP_tree_node** data; + int size; + int pos; +}RJP_tree_stack; +typedef struct RJP_object_iterator{ + RJP_tree_stack stack; + 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(RJP_tree_node *restrict dest, RJP_tree_node *restrict src); +static void irjp_copy_node_data(RJP_tree_node *restrict dest, RJP_tree_node *restrict src); static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restrict child); -static void irjp_delete_node(RJP_tree_node* node); +static void irjp_free_node(RJP_tree_node* node); static RJP_tree_node* irjp_remove_node(RJP_tree_node* target); +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); +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 inline RJP_tree_node* irjp_grandparent(RJP_tree_node* n){ if(!n->parent) @@ -81,7 +100,7 @@ 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(RJP_tree_node *restrict dest, RJP_tree_node *restrict src){ +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){ @@ -94,7 +113,7 @@ static void irjp_replace_node(RJP_tree_node *restrict node, RJP_tree_node *restr else node->parent->right = child; } -static void irjp_delete_node(RJP_tree_node* node){ +static void irjp_free_node(RJP_tree_node* node){ rjp_free(node->data.name.value); rjp_free_value(&node->data.value); rjp_free(node); @@ -107,6 +126,73 @@ RJP_tree_node* irjp_new_node(RJP_object_member value){ node->parent = node->left = node->right = NULL; return node; } + +/* TREE STACK */ +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; + stack->pos = 0; + return 0; +} +static void irjp_delete_tree_stack(RJP_tree_stack* stack){ + rjp_free(stack->data); +} +static void irjp_resize_tree_stack(RJP_tree_stack* stack){ + int newsize = stack->size*2; + RJP_tree_node** newdata = rjp_malloc(sizeof(RJP_tree_node*)*newsize); + for(int i = 0;i < stack->size;++i){ + newdata[i] = stack->data[i]; + } + rjp_free(stack->data); + stack->data = newdata; + stack->size = newsize; +} +static void irjp_push_tree_stack(RJP_tree_stack* stack, RJP_tree_node* value){ + stack->data[stack->pos++] = value; + if(stack->pos == stack->size) + irjp_resize_tree_stack(stack); +} +static RJP_tree_node* irjp_pop_tree_stack(RJP_tree_stack* stack){ + return stack->data[--stack->pos]; +} +static RJP_tree_node* irjp_peek_tree_stack(RJP_tree_stack* stack){ + return stack->data[stack->pos-1]; +} + +/* TREE ITERATOR */ +int irjp_init_object_iterator(RJP_object_iterator* it, RJP_tree_node* root){ + irjp_init_tree_stack(&it->stack); + it->current = root; + while(it->current){ + irjp_push_tree_stack(&it->stack, it->current); + it->current = it->current->left; + } + it->current = irjp_peek_tree_stack(&it->stack); + return 0; +} +void irjp_delete_object_iterator(RJP_object_iterator* it){ + irjp_delete_tree_stack(&it->stack); +} +RJP_tree_node* irjp_object_iterator_next(RJP_object_iterator* it){ + RJP_tree_node* last = irjp_pop_tree_stack(&it->stack); + if(last->right){ + irjp_push_tree_stack(&it->stack, last->right); + } + return (it->current = irjp_peek_tree_stack(&it->stack)); +} +RJP_tree_node* irjp_object_iterator_current(RJP_object_iterator* it){ + return it->current; +} + +/* TREE */ +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; +} RJP_tree_node* irjp_insert_value(RJP_tree_node* root, RJP_object_member value, int* status){ *status = RJP_TREE_SUCCESS; if(!root){ @@ -276,7 +362,7 @@ RJP_tree_node* irjp_remove_value(RJP_tree_node* root, RJP_object_member value, i } static RJP_tree_node* irjp_remove_node(RJP_tree_node* target){ while(target->right && target->left){ - irjp_copy_node(target, target->right); + irjp_copy_node_data(target, target->right); target = target->right; } RJP_tree_node* retval = target->parent; @@ -370,7 +456,7 @@ static RJP_tree_node* irjp_remove_node(RJP_tree_node* target){ irjp_replace_node(to_delete, NULL); to_delete->data.name.value = NULL; to_delete->data.value.type = rjp_json_null; - irjp_delete_node(to_delete); + irjp_free_node(to_delete); //return new root if(!retval)