/* void cxml_node_free(CLOG_INFO* info, void * data) { CXMLNODE *node = (CXMLNODE*) data; */ void cxml_node_free(CLOG_INFO* info, CXMLNODE **node) { dnode_t *dn = NULL; if(NULL==node || NULL==*node) { return; } clog( info, CTRACE, "XML: xml_node_free(), free the attributes"); // free the attributes if(NULL!=(*node)->att) { if(!dict_isempty((*node)->att)) { for (dn = dict_first((*node)->att); dn; dn = dict_next((*node)->att, dn)) { char *key=(char*)dnode_getkey(dn); char *data=(char*)dnode_get(dn); if(NULL!=key) free(key); key=NULL; if(NULL!=data) free(data); data=NULL; } } dict_free_nodes((*node)->att); dict_destroy((*node)->att); (*node)->att=NULL; } clog( info, CTRACE, "XML: xml_node_free(), free the name"); // free the name if(NULL!=(*node)->name) cstring_free(&((*node)->name)); clog( info, CTRACE, "XML: xml_node_free(), free the data"); // free the data if(NULL!=(*node)->data) cstring_free(&((*node)->data)); clog( info, CTRACE, "XML: xml_node_free(), free the subs"); // free the children if(NULL!=(*node)->sub) { if(!dict_isempty((*node)->sub)) { for (dn = dict_first((*node)->sub); dn; dn = dict_next((*node)->sub, dn)) { char *key=(char*)dnode_getkey(dn); CXMLNODE *data=(CXMLNODE*)dnode_get(dn); if(NULL!=key) free(key); key=NULL; cxml_node_free(info, &data); } } dict_free_nodes((*node)->sub); dict_destroy((*node)->sub); (*node)->sub=NULL; } free((*node)); (*node)=NULL; node=NULL; }
/* * Free a dynamically allocated dictionary object. Removing the nodes * from the tree before deleting it is required. */ void fc_solve_kaz_tree_destroy(dict_t *dict) { assert (dict_isempty(dict)); fc_solve_compact_allocator_finish(&(dict->dict_allocator)); free(dict); }
dnode_t *dict_delete(dict_t *dict, dnode_t *target) { dnode_t *nil = dict_nil(dict), *child, *delparent = target->parent; /* basic deletion */ assert (!dict_isempty(dict)); assert (dict_contains(dict, target)); /* * If the node being deleted has two children, then we replace it with its * successor (i.e. the leftmost node in the right subtree.) By doing this, * we avoid the traditional algorithm under which the successor's key and * value *only* move to the deleted node and the successor is spliced out * from the tree. We cannot use this approach because the user may hold * pointers to the successor, or nodes may be inextricably tied to some * other structures by way of embedding, etc. So we must splice out the * node we are given, not some other node, and must not move contents from * one node to another behind the user's back. */ if (target->left != nil && target->right != nil) { dnode_t *next = dict_next(dict, target); dnode_t *nextparent = next->parent; dnode_color_t nextcolor = next->color; assert (next != nil); assert (next->parent != nil); assert (next->left == nil); /* * First, splice out the successor from the tree completely, by * moving up its right child into its place. */ child = next->right; child->parent = nextparent; if (nextparent->left == next) { nextparent->left = child; } else { assert (nextparent->right == next); nextparent->right = child; } /* * Now that the successor has been extricated from the tree, install it * in place of the node that we want deleted. */ next->parent = delparent; next->left = target->left; next->right = target->right; next->left->parent = next; next->right->parent = next; next->color = target->color; target->color = nextcolor; if (delparent->left == target) { delparent->left = next; } else { assert (delparent->right == target); delparent->right = next; } } else { assert (target != nil); assert (target->left == nil || target->right == nil); child = (target->left != nil) ? target->left : target->right; child->parent = delparent = target->parent; if (target == delparent->left) { delparent->left = child; } else { assert (target == delparent->right); delparent->right = child; } } target->parent = NULL; target->right = NULL; target->left = NULL; dict->nodecount--; assert (verify_bintree(dict)); /* red-black adjustments */ if (target->color == dnode_black) { dnode_t *parent, *sister; dict_root(dict)->color = dnode_red; while (child->color == dnode_black) { parent = child->parent; if (child == parent->left) { sister = parent->right; assert (sister != nil); if (sister->color == dnode_red) { sister->color = dnode_black; parent->color = dnode_red; rotate_left(parent); sister = parent->right; assert (sister != nil); } if (sister->left->color == dnode_black && sister->right->color == dnode_black) { sister->color = dnode_red; child = parent; } else { if (sister->right->color == dnode_black) { assert (sister->left->color == dnode_red); sister->left->color = dnode_black; sister->color = dnode_red; rotate_right(sister); sister = parent->right; assert (sister != nil); } sister->color = parent->color; sister->right->color = dnode_black; parent->color = dnode_black; rotate_left(parent); break; } } else { /* symmetric case: child == child->parent->right */ assert (child == parent->right); sister = parent->left; assert (sister != nil); if (sister->color == dnode_red) { sister->color = dnode_black; parent->color = dnode_red; rotate_right(parent); sister = parent->left; assert (sister != nil); } if (sister->right->color == dnode_black && sister->left->color == dnode_black) { sister->color = dnode_red; child = parent; } else { if (sister->left->color == dnode_black) { assert (sister->right->color == dnode_red); sister->right->color = dnode_black; sister->color = dnode_red; rotate_left(sister); sister = parent->left; assert (sister != nil); } sister->color = parent->color; sister->left->color = dnode_black; parent->color = dnode_black; rotate_right(parent); break; } } } child->color = dnode_black; dict_root(dict)->color = dnode_black; } assert (dict_verify(dict)); return target; }
/* * Free a dynamically allocated dictionary object. Removing the nodes * from the tree before deleting it is required. */ void dict_destroy(dict_t *dict) { assert (dict_isempty(dict)); free(dict); }
static void construct(dict_t *d) { input_t in; int done = 0; dict_load_t dl; dnode_t *dn; char *tok1, *tok2, *val; const char *key; char *help = "p turn prompt on\n" "q finish construction\n" "a <key> <val> add new entry\n"; if (!dict_isempty(d)) puts("warning: dictionary not empty!"); dict_load_begin(&dl, d); while (!done) { if (prompt) putchar('>'); fflush(stdout); if (!fgets(in, sizeof(input_t), stdin)) break; switch (in[0]) { case '?': puts(help); break; case 'p': prompt = 1; break; case 'q': done = 1; break; case 'a': if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { puts("what?"); break; } key = dupstring(tok1); val = dupstring(tok2); dn = dnode_create(val); if (!key || !val || !dn) { puts("out of memory"); free((void *) key); free(val); if (dn) dnode_destroy(dn); } dict_load_next(&dl, dn, key); break; default: putchar('?'); putchar('\n'); break; } } dict_load_end(&dl); }
void dict_load_begin(dict_load_t *load, dict_t *dict) { assert (dict_isempty(dict)); load_begin_internal(load, dict); }