GTreeNode *left; /* left subtree */
GTreeNode *right; /* right subtree */
GTreeNode *parent; /* parent node */
- guint8 left_child; /* the node has a left child (else left points to the
- previous node in the tree) */
- guint8 right_child; /* the node has a right child (else right points to
- the next node in the tree) */
};
struct _GTreeNodeData
#define left(i) v[i].left
#define right(i) v[i].right
#define parent(i) v[i].parent
-#define left_child(i) v[i].left_child
-#define right_child(i) v[i].right_child
static GTreeNode* g_tree_node_new (GTree *tree,
gpointer key,
node->v[0].left = NULL;
node->v[0].right = NULL;
node->v[0].parent = NULL;
- node->v[0].left_child = FALSE;
- node->v[0].right_child = FALSE;
return node;
}
tmpv = g_tree_node_find_version (tmp = rv->root, version);
- while (tmpv->left_child)
+ while (tmpv->left)
tmpv = g_tree_node_find_version (tmp = tmpv->left, version);
return tmp;
GTreeNodeVersion *nodev, *tmpv;
nodev = g_tree_node_find_version (node, version);
- if (!nodev->left)
- return NULL;
- tmpv = g_tree_node_find_version (tmp = nodev->left, version);
-
- if (nodev->left_child)
- while (tmpv->right_child)
- tmpv = g_tree_node_find_version (tmp = tmpv->right, version);
+ if (nodev->left)
+ {
+ tmpv = g_tree_node_find_version (tmp = nodev->left, version);
+ while (tmpv->right)
+ tmpv = g_tree_node_find_version (tmp = tmpv->right, version);
+ }
+ else
+ {
+ tmp = nodev->parent;
+ while (tmp)
+ {
+ tmpv = g_tree_node_find_version (tmp, version);
+ if (tmpv->right == node)
+ break;
+ node = tmp;
+ nodev = tmpv;
+ tmp = tmpv->parent;
+ }
+ }
return tmp;
}
GTreeNodeVersion *nodev, *tmpv;
nodev = g_tree_node_find_version (node, version);
- if (!nodev->right)
- return NULL;
- tmpv = g_tree_node_find_version (tmp = nodev->right, version);
-
- if (nodev->right_child)
- while (tmpv->left_child)
- tmpv = g_tree_node_find_version (tmp = tmpv->left, version);
+ if (nodev->right)
+ {
+ tmpv = g_tree_node_find_version (tmp = nodev->right, version);
+ while (tmpv->left)
+ tmpv = g_tree_node_find_version (tmp = tmpv->left, version);
+ }
+ else
+ {
+ tmp = nodev->parent;
+ while (tmp)
+ {
+ tmpv = g_tree_node_find_version (tmp, version);
+ if (tmpv->left == node)
+ break;
+ node = tmp;
+ nodev = tmpv;
+ tmp = tmpv->parent;
+ }
+ }
return tmp;
}
-static void
-g_tree_remove_all (GTree *tree)
+static inline void
+g_tree_node_remove (GTree *tree, GTreeNode *node)
{
- GTreeNode *node;
- GTreeNode *next;
-
- g_return_if_fail (tree != NULL);
+ if (!node)
+ return;
- // XXX worry about removing all versions, not just the latest
+ g_tree_node_remove (tree, node->left(NOW));
+ g_tree_node_remove (tree, node->right(NOW));
- node = g_tree_first_node (tree, tree->version);
+ if (tree->key_destroy_func)
+ tree->key_destroy_func (node->data->key);
+ if (tree->value_destroy_func)
+ tree->value_destroy_func (node->data->value);
- while (node)
+ g_slice_free1 (sizeof(GTreeNodeVersion) *
+ (node->version(NOW) == 0 ? 1 : MAX_IN_DEGREE + 1),
+ node->v);
+ if (--node->data->ref_count == 0)
{
- next = g_tree_node_next (node, tree->version);
-
if (tree->key_destroy_func)
- tree->key_destroy_func (node->data->key);
+ tree->key_destroy_func (node->data->key);
if (tree->value_destroy_func)
- tree->value_destroy_func (node->data->value);
- g_slice_free (GTreeNode, node);
-
- node = next;
+ tree->value_destroy_func (node->data->value);
+ g_slice_free (GTreeNodeData, node->data);
}
+ g_slice_free (GTreeNode, node);
+
+}
+
+static void
+g_tree_remove_all (GTree *tree)
+{
+ g_return_if_fail (tree != NULL);
+
+ // XXX worry about removing all versions, not just the latest
+
+ g_tree_node_remove (tree, tree->root(NOW));
tree->roots[0].root = NULL;
tree->nnodes = 0;
prev = g_tree_node_previous (node, tree->version);
next = g_tree_node_next (node, tree->version);
parent = node->parent(NOW);
- if (node->left_child(NOW))
- left = node->left(NOW);
- else
- left = NULL;
- if (node->right_child(NOW))
- right = node->right(NOW);
- else
- right = NULL;
+ left = node->left(NOW);
+ right = node->right(NOW);
if (prev && prev->right(NOW) == node)
{
}
else if (cmp < 0)
{
- if (node->left_child(NOW))
+ if (node->left(NOW))
node = node->left(NOW);
else
{
child = g_tree_node_new (tree, key, value);
-
node = g_tree_node_next_version (tree, node);
- /* child is created at the current version */
- child->v[0].left = node->left(NOW);
- child->v[0].right = node;
child->v[0].parent = node;
-
node->v[0].left = child;
- node->v[0].left_child = TRUE;
tree->nnodes++;
}
else
{
- if (node->right_child(NOW))
+ if (node->right(NOW))
node = node->right(NOW);
else
{
child = g_tree_node_new (tree, key, value);
-
node = g_tree_node_next_version (tree, node);
- /* child is created at the current version */
- child->v[0].right = node->right(NOW);
- child->v[0].left = node;
child->v[0].parent = node;
-
node->v[0].right = child;
- node->v[0].right_child = TRUE;
tree->nnodes++;
break;
else if (cmp < 0)
{
- if (!node->left_child(NOW))
+ if (!node->left(NOW))
return FALSE;
parent = node;
}
else
{
- if (!node->right_child(NOW))
+ if (!node->right(NOW))
return FALSE;
parent = node;
}
/* rotate the node down the tree, maintaining the heap property */
- while (node->left_child(NOW) || node->right_child(NOW))
+ while (node->left(NOW) || node->right(NOW))
{
/* we're changing this node, make sure our pointer will stay valid
when we rotate it */
node = g_tree_node_next_version (tree, node);
- if (!node->left_child(NOW) ||
- (node->right_child(NOW) &&
+ if (!node->left(NOW) ||
+ (node->right(NOW) &&
g_tree_priority (node->left(NOW)) >
g_tree_priority (node->right(NOW))))
{
{
parent = g_tree_node_next_version (tree, parent);
if (is_leftchild)
- {
- parent->v[0].left_child = FALSE;
- parent->v[0].left = node->left(NOW);
- }
+ parent->v[0].left = NULL;
else
- {
- parent->v[0].right_child = FALSE;
- parent->v[0].right = node->right(NOW);
- }
+ parent->v[0].right = NULL;
}
tree->nnodes--;
{
gint l = 0, r = 0;
if (node == NULL) return 0;
- if (node->left_child(NOW)) l = g_tree_node_height (node->left(NOW));
- if (node->right_child(NOW)) r = g_tree_node_height (node->right(NOW));
+ if (node->left(NOW)) l = g_tree_node_height (node->left(NOW));
+ if (node->right(NOW)) r = g_tree_node_height (node->right(NOW));
return 1 + MAX(l, r);
}
GTreeNodeVersion *nodev = g_tree_node_find_version (node, version);
if (search_type == G_TREE_SEARCH_SUCCESSOR)
remember = node;
- if (!nodev->left_child)
+ if (!nodev->left)
return remember;
node = nodev->left;
GTreeNodeVersion *nodev = g_tree_node_find_version (node, version);
if (search_type == G_TREE_SEARCH_PREDECESSOR)
remember = node;
- if (!nodev->right_child)
+ if (!nodev->right)
return remember;
node = nodev->right;
if ((*traverse_func) (node->data->key, node->data->value, data))
return TRUE;
- if (node->left_child(NOW))
+ if (node->left(NOW))
{
if (g_tree_node_pre_order (node->left(NOW), traverse_func, data))
return TRUE;
}
- if (node->right_child(NOW))
+ if (node->right(NOW))
{
if (g_tree_node_pre_order (node->right(NOW), traverse_func, data))
return TRUE;
GTraverseFunc traverse_func,
gpointer data)
{
- if (node->left_child(NOW))
+ if (node->left(NOW))
{
if (g_tree_node_in_order (node->left(NOW), traverse_func, data))
return TRUE;
if ((*traverse_func) (node->data->key, node->data->value, data))
return TRUE;
- if (node->right_child(NOW))
+ if (node->right(NOW))
{
if (g_tree_node_in_order (node->right(NOW), traverse_func, data))
return TRUE;
GTraverseFunc traverse_func,
gpointer data)
{
- if (node->left_child(NOW))
+ if (node->left(NOW))
{
if (g_tree_node_post_order (node->left(NOW), traverse_func, data))
return TRUE;
}
- if (node->right_child(NOW))
+ if (node->right(NOW))
{
if (g_tree_node_post_order (node->right(NOW), traverse_func, data))
return TRUE;
GTreeNodeVersion *nodev = g_tree_node_find_version (node, version);
if (search_type == G_TREE_SEARCH_SUCCESSOR)
remember = node;
- if (!nodev->left_child)
+ if (!nodev->left)
return remember;
node = nodev->left;
GTreeNodeVersion *nodev = g_tree_node_find_version (node, version);
if (search_type == G_TREE_SEARCH_PREDECESSOR)
remember = node;
- if (!nodev->right_child)
+ if (!nodev->right)
return remember;
node = nodev->right;
right = g_tree_node_next_version (tree, node->right(NOW));
- if (right->left_child(NOW))
+ if (right->left(NOW))
{
node->v[0].right = g_tree_node_next_version (tree, right->left(NOW));
node->v[0].right->v[0].parent = node;
}
else
- {
- node->v[0].right_child = FALSE;
- node->v[0].right = right;
- right->v[0].left_child = TRUE;
- }
+ node->v[0].right = NULL;
right->v[0].left = node;
right->v[0].parent = node->parent(NOW);
node->v[0].parent = right;
left = g_tree_node_next_version (tree, node->left(NOW));
- if (left->right_child(NOW))
+ if (left->right(NOW))
{
node->v[0].left = g_tree_node_next_version(tree, left->right(NOW));
node->v[0].left->v[0].parent = node;
}
else
- {
- node->v[0].left_child = FALSE;
- node->v[0].left = left;
- left->v[0].right_child = TRUE;
- }
+ node->v[0].left = NULL;
left->v[0].right = node;
left->v[0].parent = node->v[0].parent;
node->v[0].parent = left;
g_tree_node_check (GTreeNode *node,
guint version)
{
- GTreeNode *tmp;
GTreeNodeVersion *nv, *tmpv;
if (node)
g_assert (nv->left == NULL || nv->left != nv->right);
- if (nv->left_child)
+ if (nv->left)
{
- tmp = g_tree_node_previous (node, version);
- g_assert (g_tree_node_find_version (tmp, version)->right == node);
-
tmpv = g_tree_node_find_version (nv->left, version);
g_assert (tmpv->parent == node);
}
- if (nv->right_child)
+ if (nv->right)
{
- tmp = g_tree_node_next (node, version);
- g_assert (g_tree_node_find_version (tmp, version)->left == node);
-
tmpv = g_tree_node_find_version (nv->right, version);
g_assert (tmpv->parent == node);
}
g_assert (tmpv->left == node || tmpv->right == node);
}
- if (nv->left_child)
+ if (nv->left)
g_tree_node_check (nv->left, version);
- if (nv->right_child)
+ if (nv->right)
g_tree_node_check (nv->right, version);
}
}
g_print ("%*s%c\n", indent, "", *(char *)node->data->key);
- if (nv->left_child)
+ if (nv->left)
g_tree_node_dump (nv->left, version, indent + 2);
- else if (nv->left)
- g_print ("%*s<%c\n", indent + 2, "", *(char *)nv->left->data->key);
+ else if ((node = g_tree_node_previous (node, version)))
+ g_print ("%*s<%c\n", indent + 2, "", *(char *)node->data->key);
- if (nv->right_child)
+ if (nv->right)
g_tree_node_dump (nv->right, version, indent + 2);
- else if (nv->right)
- g_print ("%*s>%c\n", indent + 2, "", *(char *)nv->right->data->key);
+ else if ((node = g_tree_node_next (node, version)))
+ g_print ("%*s>%c\n", indent + 2, "", *(char *)node->data->key);
}