static gpr_avl_node *rotate_right(const gpr_avl_vtable *vtable, void *key, void *value, gpr_avl_node *left, gpr_avl_node *right) { gpr_avl_node *n = new_node( vtable->copy_key(left->key), vtable->copy_value(left->value), ref_node(left->left), new_node(key, value, ref_node(left->right), right)); unref_node(vtable, left); return n; }
/* * get_node() * Return node, either from hash or created from scratch */ struct openfile * get_node(daddr_t d) { struct openfile *o; /* * From hash? */ o = hash_lookup(node_hash, d); if (o) { /* * Yes--add a reference, and return */ ref_node(o); return(o); } /* * Get a new one, and return it */ o = alloc_node(d); if (hash_insert(node_hash, d, o)) { deref_node(o); o = 0; } return(o); }
hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; assert(tparent->child); assert(tchild->parent == tparent); printf("Removing child %p\n", child); if (tchild->parent->child == tchild) { tchild->parent->child = tchild->next; } if (tchild->prev) tchild->prev->next = tchild->next; if (tchild->next) tchild->next->prev = tchild->prev; /* now reset all the child's pointers */ tchild->next = tchild->prev = tchild->parent = NULL; *result = child; ref_node(ctx, *result); return HUBBUB_OK; }
hubbub_error append_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *insert = NULL; tchild->next = tchild->prev = NULL; #ifndef NDEBUG printf("appending (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("to:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif *result = child; if (parent == (void *)1) { if (Document) { insert = Document; } else { Document = tchild; } } else { if (tparent->child == NULL) { tparent->child = tchild; } else { insert = tparent->child; } } if (insert) { while (insert->next != NULL) { insert = insert->next; } if (tchild->type == CHARACTER && insert->type == CHARACTER) { insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { insert->next = tchild; tchild->prev = insert; } } if (*result == child) tchild->parent = tparent; ref_node(ctx, *result); return HUBBUB_OK; }
static gpr_avl_node *add(const gpr_avl_vtable *vtable, gpr_avl_node *node, void *key, void *value) { long cmp; if (node == NULL) { return new_node(key, value, NULL, NULL); } cmp = vtable->compare_keys(node->key, key); if (cmp == 0) { return new_node(key, value, ref_node(node->left), ref_node(node->right)); } else if (cmp > 0) { return rebalance( vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), add(vtable, node->left, key, value), ref_node(node->right)); } else { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), ref_node(node->left), add(vtable, node->right, key, value)); } }
hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) { UNUSED(element_only); *result = ((node_t *)node)->parent; if (*result != NULL) ref_node(ctx, *result); return HUBBUB_OK; }
static gpr_avl_node *remove(const gpr_avl_vtable *vtable, gpr_avl_node *node, void *key) { long cmp; if (node == NULL) { return NULL; } cmp = vtable->compare_keys(node->key, key); if (cmp == 0) { if (node->left == NULL) { return ref_node(node->right); } else if (node->right == NULL) { return ref_node(node->left); } else if (node->left->height < node->right->height) { gpr_avl_node *h = in_order_head(node->right); return rebalance(vtable, vtable->copy_key(h->key), vtable->copy_value(h->value), ref_node(node->left), remove(vtable, node->right, h->key)); } else { gpr_avl_node *h = in_order_tail(node->left); return rebalance( vtable, vtable->copy_key(h->key), vtable->copy_value(h->value), remove(vtable, node->left, h->key), ref_node(node->right)); } } else if (cmp > 0) { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), remove(vtable, node->left, key), ref_node(node->right)); } else { return rebalance(vtable, vtable->copy_key(node->key), vtable->copy_value(node->value), ref_node(node->left), remove(vtable, node->right, key)); } }
/* insert 'child' before 'ref_child', under 'parent' */ hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *tref = ref_child; #ifndef NDEBUG printf("inserting (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("before:\n"); node_print(NULL, tref, 0); printf("under:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif if (tchild->type == CHARACTER && tref->prev && tref->prev->type == CHARACTER) { node_t *insert = tref->prev; insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { tchild->parent = parent; tchild->prev = tref->prev; tchild->next = tref; tref->prev = tchild; if (tchild->prev) tchild->prev->next = tchild; else tparent->child = tchild; *result = child; } ref_node(ctx, *result); return HUBBUB_OK; }
gpr_avl gpr_avl_ref(gpr_avl avl) { ref_node(avl.root); return avl; }