Introduce g_tree_node_modify and g_tree_root_modify, which are used to change the...
authorDana Jansens <danakj@orodu.net>
Thu, 29 Oct 2009 15:34:24 +0000 (11:34 -0400)
committerDana Jansens <danakj@orodu.net>
Thu, 12 Nov 2009 21:54:04 +0000 (16:54 -0500)
glib/gtree.c

index ac076e85e9f05b60c8f066654f26f30a3f4cd92b..a92ec676b32f673f5c9891604d811c16f885c803 100644 (file)
@@ -90,9 +90,9 @@ struct _GTreeNode
 #define left_child(i)  v[i].left_child
 #define right_child(i) v[i].right_child
 
-static GTreeNode* g_tree_node_new                   (gpointer         key,
-                                                    gpointer         value,
-                                                     guint            version);
+static GTreeNode* g_tree_node_new                   (GTree           *tree,
+                                                     gpointer         key,
+                                                    gpointer         value);
 static guint      g_tree_priority                   (GTreeNode       *node);
 static void       g_tree_insert_internal            (GTree           *tree,
                                                     gpointer         key,
@@ -125,9 +125,9 @@ static void       g_tree_node_check                 (GTreeNode       *node);
 #endif
 
 static GTreeNode*
-g_tree_node_new (gpointer key,
-                gpointer value,
-                 guint    version)
+g_tree_node_new (GTree   *tree,
+                 gpointer key,
+                gpointer value)
 {
   GTreeNode *node = g_slice_new (GTreeNode);
 
@@ -139,10 +139,10 @@ g_tree_node_new (gpointer key,
      so that we don't use a lot more memory when persistence isn't even
      being used */
   node->v = g_slice_alloc(sizeof(GTreeNodeVersion) *
-                          (version == 0 ? 1 : MAX_IN_DEGREE + 1));
+                          (tree->version == 0 ? 1 : MAX_IN_DEGREE + 1));
   node->nv = 1;
 
-  node->v[0].version = version;
+  node->v[0].version = tree->version;
   node->v[0].left = NULL;
   node->v[0].right = NULL;
   node->v[0].parent = NULL;
@@ -152,6 +152,48 @@ g_tree_node_new (gpointer key,
   return node;
 }
 
+static GTreeNode*
+g_tree_root_modify (GTree     *tree,
+                    GTreeNode *root)
+{
+  tree->root = root;
+  return root;
+}
+
+static GTreeNode*
+g_tree_node_modify (GTree     *tree,
+                    GTreeNode *node,
+                    GTreeNode *left,
+                    GTreeNode *right,
+                    GTreeNode *parent,
+                    gboolean   left_child,
+                    gboolean   right_child)
+{
+  int i;
+
+  for (i = 0; i < node->nv; ++i)
+    if (node->version(i) == tree->version)
+      break;
+  if (i == node->nv)
+    {
+      /* we filled the node's pointer table and need to make a new GTreeNode */
+      GTreeNode *n = g_slice_new(GTreeNode);
+      n->data = node->data;
+      i = 0;
+      n->v[i].version = tree->version;
+      n->nv = 1;
+      node = n;
+    }
+
+  node->v[i].left = left;
+  node->v[i].right = right;
+  node->v[i].parent = parent;
+  node->v[i].left_child = left_child;
+  node->v[i].right_child = right_child;
+
+  return node;
+}
+
 /**
  * g_tree_new:
  * @key_compare_func: the function used to order the nodes in the #GTree.
@@ -499,7 +541,7 @@ g_tree_insert_internal (GTree    *tree,
 
   if (!tree->root)
     {
-      tree->root = g_tree_node_new (key, value, tree->version);
+      g_tree_root_modify (tree, g_tree_node_new (tree, key, value));
       tree->nnodes++;
       return;
     }
@@ -540,7 +582,7 @@ g_tree_insert_internal (GTree    *tree,
               node = node->left(NOW);
           else
             {
-              child = g_tree_node_new (key, value, tree->version);
+              child = g_tree_node_new (tree, key, value);
 
               child->v[0].left = node->v[0].left;
               child->v[0].right = node;
@@ -560,7 +602,7 @@ g_tree_insert_internal (GTree    *tree,
               node = node->right(NOW);
           else
             {
-              child = g_tree_node_new (key, value, tree->version);
+              child = g_tree_node_new (tree, key, value);
 
               child->v[0].right = node->v[0].right;
               child->v[0].left = node;
@@ -589,7 +631,7 @@ g_tree_insert_internal (GTree    *tree,
         g_tree_node_rotate_left (p);
 
       if (!sp)
-        tree->root = node;
+        g_tree_root_modify (tree, node);
       else if (sp->left(NOW) == p)
         sp->left(NOW) = node;
       else
@@ -714,7 +756,7 @@ g_tree_remove_internal (GTree         *tree,
         {
           /* rotate the right child up */
           if (!parent)
-            parent = tree->root = g_tree_node_rotate_left (node);
+            parent = g_tree_root_modify (tree, g_tree_node_rotate_left (node));
           else if (is_leftchild)
             parent = parent->v[0].left = g_tree_node_rotate_left (node);
           else
@@ -725,7 +767,7 @@ g_tree_remove_internal (GTree         *tree,
         {
           /* rotate the left child up */
           if (!parent)
-            parent = tree->root = g_tree_node_rotate_right (node);
+            parent = g_tree_root_modify(tree, g_tree_node_rotate_right (node));
           else if (is_leftchild)
             parent = parent->v[0].left = g_tree_node_rotate_right (node);
           else
@@ -736,7 +778,7 @@ g_tree_remove_internal (GTree         *tree,
 
   /* remove any pointers to the node in the treap */
   if (!parent)
-    tree->root = NULL;
+    g_tree_root_modify(tree, NULL);
   else if (is_leftchild)
     {
       parent->v[0].left_child = FALSE;