[patch] adding destroy_notifiers to GTree



Hi,

here's a patch that adds the new functions g_tree_new_full, 
g_tree_replace and g_tree_steal to the GTree API similar to 
the extensions the GHashTable API has seen lately. I'd like 
you to have a look at this and would like to receive an OK 
for commit. Of course I'll add inline docs then.

There's one issue with this patch. GTree used to have 
g_tree_new_with_user_data() defined in the header but there was 
no implementation. Actually there was, but it was called 
g_tree_new_udata(). My patch corrects this error, but I'm not 
sure if it makes sense at all. I'd vote for removing this
feature. If you agree I'll change my patch accordingly.


Salut, Sven

Index: gtree.c
===================================================================
RCS file: /cvs/gnome/glib/gtree.c,v
retrieving revision 1.21
diff -u -r1.21 gtree.c
--- gtree.c	2001/03/08 18:18:16	1.21
+++ gtree.c	2001/04/02 18:03:41
@@ -42,7 +42,9 @@
 {
   GTreeNode *root;
   GCompareDataFunc key_compare;
-  gpointer key_compare_data;
+  GDestroyNotify   key_destroy_func;
+  GDestroyNotify   value_destroy_func;
+  gpointer         key_compare_data;
 };
 
 struct _GTreeNode
@@ -55,47 +57,54 @@
 };
 
 
-static GTreeNode* g_tree_node_new                   (gpointer        key,
-						     gpointer        value);
-static void       g_tree_node_destroy               (GTreeNode      *node);
-static GTreeNode* g_tree_node_insert                (GTreeNode      *node,
-						     GCompareDataFunc compare,
-						     gpointer        comp_data,
-						     gpointer        key,
-						     gpointer        value,
-						     gint           *inserted);
-static GTreeNode* g_tree_node_remove                (GTreeNode      *node,
-						     GCompareDataFunc compare,
-						     gpointer        comp_data,
-						     gconstpointer   key);
-static GTreeNode* g_tree_node_balance               (GTreeNode      *node);
-static GTreeNode* g_tree_node_remove_leftmost       (GTreeNode      *node,
-						     GTreeNode     **leftmost);
-static GTreeNode* g_tree_node_restore_left_balance  (GTreeNode      *node,
-						     gint            old_balance);
-static GTreeNode* g_tree_node_restore_right_balance (GTreeNode      *node,
-						     gint            old_balance);
-static GTreeNode* g_tree_node_lookup                (GTreeNode      *node,
-						     GCompareDataFunc compare,
-						     gpointer        comp_data,
-						     gconstpointer   key);
-static gint       g_tree_node_count                 (GTreeNode      *node);
-static gint       g_tree_node_pre_order             (GTreeNode      *node,
-						     GTraverseFunc   traverse_func,
-						     gpointer        data);
-static gint       g_tree_node_in_order              (GTreeNode      *node,
-						     GTraverseFunc   traverse_func,
-						     gpointer        data);
-static gint       g_tree_node_post_order            (GTreeNode      *node,
-						     GTraverseFunc   traverse_func,
-						     gpointer        data);
-static gpointer   g_tree_node_search                (GTreeNode      *node,
-						     GCompareFunc    search_func,
-						     gconstpointer   data);
-static gint       g_tree_node_height                (GTreeNode      *node);
-static GTreeNode* g_tree_node_rotate_left           (GTreeNode      *node);
-static GTreeNode* g_tree_node_rotate_right          (GTreeNode      *node);
-static void       g_tree_node_check                 (GTreeNode      *node);
+static GTreeNode* g_tree_node_new                   (gpointer          key,
+						     gpointer          value);
+static void       g_tree_node_destroy               (GTreeNode        *node,
+                                                     GDestroyNotify    key_destroy_func,
+						     GDestroyNotify    value_destroy_func);
+static GTreeNode* g_tree_node_insert                (GTreeNode        *node,
+						     GCompareDataFunc  compare,
+						     gpointer          comp_data,
+                                                     GDestroyNotify    key_destroy_func,
+                               			     GDestroyNotify    value_destroy_func,
+						     gpointer          key,
+						     gpointer          value,
+                                                     gboolean          replace,
+						     gboolean         *inserted);
+static GTreeNode* g_tree_node_remove                (GTreeNode        *node,
+						     GCompareDataFunc  compare,
+						     gpointer          comp_data,
+                                                     GDestroyNotify    key_destroy_func,
+                               			     GDestroyNotify    value_destroy_func,
+						     gconstpointer     key);
+static GTreeNode* g_tree_node_balance               (GTreeNode        *node);
+static GTreeNode* g_tree_node_remove_leftmost       (GTreeNode        *node,
+						     GTreeNode       **leftmost);
+static GTreeNode* g_tree_node_restore_left_balance  (GTreeNode        *node,
+						     gint              old_balance);
+static GTreeNode* g_tree_node_restore_right_balance (GTreeNode        *node,
+						     gint              old_balance);
+static GTreeNode* g_tree_node_lookup                (GTreeNode        *node,
+						     GCompareDataFunc  compare,
+						     gpointer          comp_data,
+						     gconstpointer     key);
+static gint       g_tree_node_count                 (GTreeNode        *node);
+static gint       g_tree_node_pre_order             (GTreeNode        *node,
+						     GTraverseFunc     traverse_func,
+						     gpointer          data);
+static gint       g_tree_node_in_order              (GTreeNode        *node,
+						     GTraverseFunc     traverse_func,
+						     gpointer          data);
+static gint       g_tree_node_post_order            (GTreeNode        *node,
+						     GTraverseFunc     traverse_func,
+						     gpointer          data);
+static gpointer   g_tree_node_search                (GTreeNode        *node,
+						     GCompareFunc      search_func,
+						     gconstpointer     data);
+static gint       g_tree_node_height                (GTreeNode        *node);
+static GTreeNode* g_tree_node_rotate_left           (GTreeNode        *node);
+static GTreeNode* g_tree_node_rotate_right          (GTreeNode        *node);
+static void       g_tree_node_check                 (GTreeNode        *node);
 
 
 G_LOCK_DEFINE_STATIC (g_tree_global);
@@ -137,13 +146,22 @@
 }
 
 static void
-g_tree_node_destroy (GTreeNode *node)
+g_tree_node_destroy (GTreeNode      *node,
+		     GDestroyNotify  key_destroy_func,
+		     GDestroyNotify  value_destroy_func)
 {
   if (node)
     {
-      g_tree_node_destroy (node->right);
-      g_tree_node_destroy (node->left);
-
+      g_tree_node_destroy (node->right,
+			   key_destroy_func, value_destroy_func);
+      g_tree_node_destroy (node->left,
+			   key_destroy_func, value_destroy_func);
+
+      if (key_destroy_func)
+	key_destroy_func (node->key);
+      if (value_destroy_func)
+	value_destroy_func (node->value);
+      
 #ifdef ENABLE_GC_FRIENDLY
       node->left = NULL;
       node->key = NULL;
@@ -157,27 +175,44 @@
    }
 }
 
-GTree*	 g_tree_new_udata(GCompareDataFunc key_compare_func,
-                          gpointer        key_compare_data)
+GTree*
+g_tree_new (GCompareFunc key_compare_func)
 {
-  GRealTree *rtree;
-
   g_return_val_if_fail (key_compare_func != NULL, NULL);
-
-  rtree = g_new (GRealTree, 1);
-  rtree->root = NULL;
-  rtree->key_compare = key_compare_func;
-  rtree->key_compare_data = key_compare_data;
 
-  return (GTree*) rtree;
+  return g_tree_new_full ((GCompareDataFunc) key_compare_func, NULL,
+                          NULL, NULL);
 }
-
+ 
 GTree*
-g_tree_new (GCompareFunc key_compare_func)
+g_tree_new_with_data (GCompareDataFunc key_compare_func,
+ 		      gpointer         key_compare_data)
 {
-  return g_tree_new_udata ((GCompareDataFunc) key_compare_func, NULL);
+  g_return_val_if_fail (key_compare_func != NULL, NULL);
+  
+  return g_tree_new_full (key_compare_func, key_compare_data, 
+ 			  NULL, NULL);
 }
 
+GTree*	 
+g_tree_new_full (GCompareDataFunc key_compare_func,
+ 		 gpointer         key_compare_data, 		 
+                 GDestroyNotify   key_destroy_func,
+ 		 GDestroyNotify   value_destroy_func)
+{
+  GRealTree *rtree;
+  
+  g_return_val_if_fail (key_compare_func != NULL, NULL);
+  
+  rtree = g_new (GRealTree, 1);
+  rtree->root               = NULL;
+  rtree->key_compare        = key_compare_func;
+  rtree->key_destroy_func   = key_destroy_func;
+  rtree->value_destroy_func = value_destroy_func;
+  rtree->key_compare_data   = key_compare_data;
+  
+  return (GTree*) rtree;
+}
 
 void
 g_tree_destroy (GTree *tree)
@@ -188,7 +223,10 @@
 
   rtree = (GRealTree*) tree;
 
-  g_tree_node_destroy (rtree->root);
+  g_tree_node_destroy (rtree->root,
+                       rtree->key_destroy_func,
+ 		       rtree->value_destroy_func);
+
   g_free (rtree);
 }
 
@@ -198,19 +236,45 @@
 	       gpointer  value)
 {
   GRealTree *rtree;
-  gint inserted;
+  gboolean   inserted;
 
   g_return_if_fail (tree != NULL);
 
   rtree = (GRealTree*) tree;
 
   inserted = FALSE;
-  rtree->root = g_tree_node_insert (rtree->root, rtree->key_compare,
+  rtree->root = g_tree_node_insert (rtree->root, 
+                                    rtree->key_compare,
 				    rtree->key_compare_data,
-				    key, value, &inserted);
+				    rtree->key_destroy_func,
+				    rtree->value_destroy_func,
+				    key, value, 
+				    FALSE, &inserted);
 }
 
 void
+g_tree_replace (GTree    *tree,
+		gpointer  key,
+		gpointer  value)
+{
+  GRealTree *rtree;
+  gboolean   inserted;
+
+  g_return_if_fail (tree != NULL);
+
+  rtree = (GRealTree*) tree;
+
+  inserted = FALSE;
+  rtree->root = g_tree_node_insert (rtree->root, 
+                                    rtree->key_compare,
+                                    rtree->key_compare_data,
+				    rtree->key_destroy_func,
+				    rtree->value_destroy_func,
+				    key, value, 
+				    TRUE, &inserted);
+}
+
+void
 g_tree_remove (GTree         *tree,
 	       gconstpointer  key)
 {
@@ -219,9 +283,30 @@
   g_return_if_fail (tree != NULL);
 
   rtree = (GRealTree*) tree;
+
+  rtree->root = g_tree_node_remove (rtree->root, 
+                                    rtree->key_compare,
+                                    rtree->key_compare_data, 
+                                    rtree->key_destroy_func, 
+                                    rtree->value_destroy_func,
+                                    key);
+}
+
+void
+g_tree_steal (GTree         *tree,
+              gconstpointer  key)
+{
+  GRealTree *rtree;
+
+  g_return_if_fail (tree != NULL);
+
+  rtree = (GRealTree*) tree;
 
-  rtree->root = g_tree_node_remove (rtree->root, rtree->key_compare,
-                                    rtree->key_compare_data, key);
+  rtree->root = g_tree_node_remove (rtree->root, 
+                                    rtree->key_compare,
+                                    rtree->key_compare_data,
+                                    NULL, NULL,
+                                    key);
 }
 
 gpointer
@@ -354,12 +439,15 @@
 }
 
 static GTreeNode*
-g_tree_node_insert (GTreeNode      *node,
-		    GCompareDataFunc compare,
-		    gpointer        compare_data,
-		    gpointer        key,
-		    gpointer        value,
-		    gint           *inserted)
+g_tree_node_insert (GTreeNode        *node,
+		    GCompareDataFunc  compare,
+		    gpointer          compare_data,
+ 		    GDestroyNotify    key_destroy_func,
+ 		    GDestroyNotify    value_destroy_func,
+		    gpointer          key,
+		    gpointer          value,
+                    gboolean          replace,
+		    gboolean         *inserted)
 {
   gint old_balance;
   gint cmp;
@@ -374,7 +462,26 @@
   if (cmp == 0)
     {
       *inserted = FALSE;
+
+      if (value_destroy_func)
+	value_destroy_func (node->value);
+
       node->value = value;
+      
+      if (replace)
+	{
+	  if (key_destroy_func)
+	    key_destroy_func (node->key);
+
+	  node->key = key;
+	}
+      else
+	{
+	  /* free the passed key */
+	  if (key_destroy_func)
+	    key_destroy_func (key);
+	}
+
       return node;
     }
 
@@ -384,7 +491,10 @@
 	{
 	  old_balance = node->left->balance;
 	  node->left = g_tree_node_insert (node->left, compare, compare_data,
-	                                   key, value, inserted);
+	                                   key_destroy_func, 
+					   value_destroy_func,
+					   key, value,
+					   replace, inserted);
 
 	  if ((old_balance != node->left->balance) && node->left->balance)
 	    node->balance -= 1;
@@ -402,7 +512,10 @@
 	{
 	  old_balance = node->right->balance;
 	  node->right = g_tree_node_insert (node->right, compare, compare_data,
-	                                    key, value, inserted);
+	                                    key_destroy_func, 
+					    value_destroy_func,
+					    key, value, 
+					    replace, inserted);
 
 	  if ((old_balance != node->right->balance) && node->right->balance)
 	    node->balance += 1;
@@ -425,10 +538,12 @@
 }
 
 static GTreeNode*
-g_tree_node_remove (GTreeNode      *node,
-		    GCompareDataFunc compare,
-		    gpointer        compare_data,
-		    gconstpointer   key)
+g_tree_node_remove (GTreeNode        *node,
+		    GCompareDataFunc  compare,
+		    gpointer          compare_data,
+                    GDestroyNotify    key_destroy_func,
+                    GDestroyNotify    value_destroy_func,
+		    gconstpointer     key)
 {
   GTreeNode *new_root;
   gint old_balance;
@@ -458,6 +573,11 @@
 	  node = g_tree_node_restore_right_balance (new_root, old_balance);
 	}
 
+      if (key_destroy_func)
+	key_destroy_func (garbage->key);
+      if (value_destroy_func)
+	value_destroy_func (garbage->value);
+
 #ifdef ENABLE_GC_FRIENDLY
       garbage->left = NULL;
       garbage->key = NULL;
@@ -474,7 +594,11 @@
       if (node->left)
 	{
 	  old_balance = node->left->balance;
-	  node->left = g_tree_node_remove (node->left, compare, compare_data, key);
+	  node->left = g_tree_node_remove (node->left, 
+                                           compare, compare_data, 
+					   key_destroy_func, 
+					   value_destroy_func,
+					   key);
 	  node = g_tree_node_restore_left_balance (node, old_balance);
 	}
     }
@@ -483,7 +607,11 @@
       if (node->right)
 	{
 	  old_balance = node->right->balance;
-	  node->right = g_tree_node_remove (node->right, compare, compare_data, key);
+	  node->right = g_tree_node_remove (node->right, 
+                                            compare, compare_data, 
+                                            key_destroy_func, 
+                                            value_destroy_func, 
+                                            key);
 	  node = g_tree_node_restore_right_balance (node, old_balance);
 	}
     }
@@ -558,10 +686,10 @@
 }
 
 static GTreeNode *
-g_tree_node_lookup (GTreeNode      *node,
-		    GCompareDataFunc compare,
-		    gpointer        compare_data,
-		    gconstpointer   key)
+g_tree_node_lookup (GTreeNode        *node,
+		    GCompareDataFunc  compare,
+		    gpointer          compare_data,
+		    gconstpointer     key)
 {
   gint cmp;
 
Index: gtree.h
===================================================================
RCS file: /cvs/gnome/glib/gtree.h,v
retrieving revision 1.4
diff -u -r1.4 gtree.h
--- gtree.h	2001/03/08 17:51:38	1.4
+++ gtree.h	2001/04/02 18:03:41
@@ -42,11 +42,20 @@
 GTree*   g_tree_new             (GCompareFunc      key_compare_func);
 GTree*   g_tree_new_with_data   (GCompareDataFunc  key_compare_func,
                                  gpointer          user_data);
+GTree*   g_tree_new_full        (GCompareDataFunc  key_compare_func,
+                                 gpointer          user_data,
+                                 GDestroyNotify    key_destroy_func,
+                                 GDestroyNotify    value_destroy_func);
 void     g_tree_destroy         (GTree            *tree);
 void     g_tree_insert          (GTree            *tree,
                                  gpointer          key,
                                  gpointer          value);
+void     g_tree_replace         (GTree            *tree,
+                                 gpointer          key,
+                                 gpointer          value);
 void     g_tree_remove          (GTree            *tree,
+                                 gconstpointer     key);
+void     g_tree_steal           (GTree            *tree,
                                  gconstpointer     key);
 gpointer g_tree_lookup          (GTree            *tree,
                                  gconstpointer     key);




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]