Use <envar>, not <envvar>.
[platform/upstream/glib.git] / glib / gslist.c
index bcb481f..18e08e4 100644 (file)
@@ -2,23 +2,23 @@
  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 /*
- * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GLib Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
  * MT safe
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include "glib.h"
 
 
+#ifndef DISABLE_MEM_POOLS
 struct _GAllocator /* from gmem.c */
 {
   gchar         *name;
@@ -159,7 +164,7 @@ g_slist_free (GSList *list)
          last_node->data = NULL;
          last_node = last_node->next;
        }
-      last_node->data = NULL
+      last_node->data = NULL;
 #else /* !ENABLE_GC_FRIENDLY */
       list->data = list->next;  
 #endif /* ENABLE_GC_FRIENDLY */
@@ -189,6 +194,40 @@ g_slist_free_1 (GSList *list)
 {
   _g_slist_free_1 (list);
 }
+#else /* DISABLE_MEM_POOLS */
+
+#define _g_slist_alloc g_slist_alloc
+GSList*
+g_slist_alloc (void)
+{
+  GSList *list;
+  
+  list = g_new0 (GSList, 1);
+  
+  return list;
+}
+
+void
+g_slist_free (GSList *list)
+{
+  GSList *last;
+  
+  while (list)
+    {
+      last = list;
+      list = list->next;
+      g_free (last);
+    }
+}
+
+#define _g_slist_free_1 g_slist_free_1
+void
+g_slist_free_1 (GSList *list)
+{
+  g_free (list);
+}
+
+#endif
 
 GSList*
 g_slist_append (GSList   *list,
@@ -268,6 +307,45 @@ g_slist_insert (GSList   *list,
   return list;
 }
 
+GSList*
+g_slist_insert_before (GSList  *slist,
+                      GSList  *sibling,
+                      gpointer data)
+{
+  if (!slist)
+    {
+      slist = g_slist_alloc ();
+      slist->data = data;
+      g_return_val_if_fail (sibling == NULL, slist);
+      return slist;
+    }
+  else
+    {
+      GSList *node, *last = NULL;
+
+      for (node = slist; node; last = node, node = last->next)
+       if (node == sibling)
+         break;
+      if (!last)
+       {
+         node = g_slist_alloc ();
+         node->data = data;
+         node->next = slist;
+
+         return node;
+       }
+      else
+       {
+         node = g_slist_alloc ();
+         node->data = data;
+         node->next = last->next;
+         last->next = node;
+
+         return slist;
+       }
+    }
+}
+
 GSList *
 g_slist_concat (GSList *list1, GSList *list2)
 {
@@ -283,32 +361,57 @@ g_slist_concat (GSList *list1, GSList *list2)
 }
 
 GSList*
-g_slist_remove (GSList   *list,
-               gpointer  data)
+g_slist_remove (GSList        *list,
+               gconstpointer  data)
 {
-  GSList *tmp;
-  GSList *prev;
+  GSList *tmp, *prev = NULL;
 
-  prev = NULL;
   tmp = list;
-
   while (tmp)
     {
       if (tmp->data == data)
        {
          if (prev)
            prev->next = tmp->next;
-         if (list == tmp)
-           list = list->next;
-
-         tmp->next = NULL;
-         g_slist_free (tmp);
+         else
+           list = tmp->next;
 
+         g_slist_free_1 (tmp);
          break;
        }
-
       prev = tmp;
-      tmp = tmp->next;
+      tmp = prev->next;
+    }
+
+  return list;
+}
+
+GSList*
+g_slist_remove_all (GSList        *list,
+                   gconstpointer  data)
+{
+  GSList *tmp, *prev = NULL;
+
+  tmp = list;
+  while (tmp)
+    {
+      if (tmp->data == data)
+       {
+         GSList *next = tmp->next;
+
+         if (prev)
+           prev->next = next;
+         else
+           list = next;
+         
+         g_slist_free_1 (tmp);
+         tmp = next;
+       }
+      else
+       {
+         prev = tmp;
+         tmp = prev->next;
+       }
     }
 
   return list;
@@ -390,11 +493,11 @@ GSList*
 g_slist_reverse (GSList *list)
 {
   GSList *prev = NULL;
-  GSList *next = NULL;
   
   while (list)
     {
-      next = list->next;
+      GSList *next = list->next;
+
       list->next = prev;
       
       prev = list;
@@ -425,8 +528,8 @@ g_slist_nth_data (GSList   *list,
 }
 
 GSList*
-g_slist_find (GSList   *list,
-             gpointer  data)
+g_slist_find (GSList        *list,
+             gconstpointer  data)
 {
   while (list)
     {
@@ -439,9 +542,9 @@ g_slist_find (GSList   *list,
 }
 
 GSList*
-g_slist_find_custom (GSList      *list,
-                    gpointer     data,
-                    GCompareFunc func)
+g_slist_find_custom (GSList        *list,
+                    gconstpointer  data,
+                    GCompareFunc   func)
 {
   g_return_val_if_fail (func != NULL, list);
 
@@ -474,8 +577,8 @@ g_slist_position (GSList *list,
 }
 
 gint
-g_slist_index (GSList   *list,
-              gpointer data)
+g_slist_index (GSList        *list,
+              gconstpointer  data)
 {
   gint i;
 
@@ -525,8 +628,9 @@ g_slist_foreach (GSList   *list,
 {
   while (list)
     {
+      GSList *next = list->next;
       (*func) (list->data, user_data);
-      list = list->next;
+      list = next;
     }
 }
 
@@ -580,18 +684,26 @@ g_slist_insert_sorted (GSList       *list,
     }
 }
 
-static GSList* 
-g_slist_sort_merge  (GSList      *l1, 
-                    GSList      *l2,
-                    GCompareFunc compare_func)
+static GSList *
+g_slist_sort_merge (GSList   *l1, 
+                   GSList   *l2,
+                   GFunc     compare_func,
+                   gboolean  use_data,
+                   gpointer  user_data)
 {
   GSList list, *l;
+  gint cmp;
 
   l=&list;
 
   while (l1 && l2)
     {
-      if (compare_func(l1->data,l2->data) < 0)
+      if (use_data)
+       cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
+      else
+       cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
+
+      if (cmp <= 0)
         {
          l=l->next=l1;
          l1=l1->next;
@@ -607,9 +719,11 @@ g_slist_sort_merge  (GSList      *l1,
   return list.next;
 }
 
-GSList* 
-g_slist_sort (GSList       *list,
-             GCompareFunc compare_func)
+static GSList *
+g_slist_sort_real (GSList   *list,
+                  GFunc     compare_func,
+                  gboolean  use_data,
+                  gpointer  user_data)
 {
   GSList *l1, *l2;
 
@@ -630,7 +744,24 @@ g_slist_sort (GSList       *list,
   l2 = l1->next; 
   l1->next = NULL;
 
-  return g_slist_sort_merge (g_slist_sort (list, compare_func),
-                            g_slist_sort (l2,   compare_func),
-                            compare_func);
+  return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
+                            g_slist_sort_real (l2, compare_func, use_data, user_data),
+                            compare_func,
+                            use_data,
+                            user_data);
+}
+
+GSList *
+g_slist_sort (GSList       *list,
+             GCompareFunc  compare_func)
+{
+  return g_slist_sort_real (list, (GFunc) compare_func, FALSE, NULL);
+}
+
+GSList *
+g_slist_sort_with_data (GSList           *list,
+                       GCompareDataFunc  compare_func,
+                       gpointer          user_data)
+{
+  return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);
 }