| | <@xref{\NODE\, , PBST copy error helper function.>,510}
struct pbst_table * pbst_copy (const struct pbst_table *org, pbst_copy_func *copy,
pbst_item_func *destroy, struct libavl_allocator *allocator) {
struct pbst_table *new;
const struct pbst_node *x;
struct pbst_node *y;
assert (org != NULL);
new = pbst_create (org->pbst_compare, org->pbst_param,
allocator != NULL ? allocator : org->pbst_alloc);
if (new == NULL)
return NULL;
new->pbst_count = org->pbst_count;
if (new->pbst_count == 0)
return new;
x = (const struct pbst_node *) &org->pbst_root;
y = (struct pbst_node *) &new->pbst_root;
for (;;) {
while (x->pbst_link[0] != NULL) {
y->pbst_link[0] = new->pbst_alloc->libavl_malloc (new->pbst_alloc,
sizeof *y->pbst_link[0]);
if (y->pbst_link[0] == NULL) {
if (y != (struct pbst_node *) &new->pbst_root) {
y->pbst_data = NULL;
y->pbst_link[1] = NULL;
}
copy_error_recovery (y, new, destroy);
return NULL;
}
y->pbst_link[0]->pbst_parent = y;
x = x->pbst_link[0];
y = y->pbst_link[0];
}
y->pbst_link[0] = NULL;
for (;;) {
if (copy == NULL)
y->pbst_data = x->pbst_data;
else {
y->pbst_data = copy (x->pbst_data, org->pbst_param);
if (y->pbst_data == NULL) {
y->pbst_link[1] = NULL;
copy_error_recovery (y, new, destroy);
return NULL;
}
}
if (x->pbst_link[1] != NULL) {
y->pbst_link[1] = new->pbst_alloc->libavl_malloc (new->pbst_alloc,
sizeof *y->pbst_link[1]);
if (y->pbst_link[1] == NULL) {
copy_error_recovery (y, new, destroy);
return NULL;
}
y->pbst_link[1]->pbst_parent = y;
x = x->pbst_link[1];
y = y->pbst_link[1];
break;
}
else y->pbst_link[1] = NULL;
for (;;) {
const struct pbst_node *w = x;
x = x->pbst_parent;
if (x == NULL) {
new->pbst_root->pbst_parent = NULL;
return new;
}
y = y->pbst_parent;
if (w == x->pbst_link[0])
break;
}
}
}
}
|