Merge pull request #2745 from lambdageek/dev/monoerror-sre-internals
[mono.git] / eglib / src / glist.c
index 77919817ce6cef0bccb9c8a5b26fb4c123d836a3..882fda48ec9b75772bd8f780d2f1fbef9266ab54 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * glist.c: Doubly-linked list implementation
  *
- * Author:
+ * Authors:
  *   Duncan Mak (duncan@novell.com)
+ *   Raja R Harinath (rharinath@novell.com)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -124,6 +125,25 @@ g_list_remove (GList *list, gconstpointer data)
        return list;
 }
 
+GList*
+g_list_remove_all (GList *list, gconstpointer data)
+{
+       GList *current = g_list_find (list, data);
+
+       if (!current)
+               return list;
+
+       while (current) {
+               if (current == list)
+                       list = list->next;
+               g_list_free_1 (disconnect_node (current));
+
+               current = g_list_find (list, data);
+       }
+
+       return list;
+}
+
 GList*
 g_list_remove_link (GList *list, GList *link)
 {
@@ -159,6 +179,22 @@ g_list_find (GList *list, gconstpointer data)
        return NULL;
 }
 
+GList*
+g_list_find_custom (GList *list, gconstpointer data, GCompareFunc func)
+{
+       if (!func)
+               return NULL;
+       
+       while (list) {
+               if (func (list->data, data) == 0)
+                       return list;
+               
+               list = list->next;
+       }
+       
+       return NULL;
+}
+
 GList*
 g_list_reverse (GList *list)
 {
@@ -204,7 +240,8 @@ g_list_insert_sorted (GList *list, gpointer data, GCompareFunc func)
 {
        GList *prev = NULL;
        GList *current;
-       
+       GList *node;
+
        if (!func)
                return list;
 
@@ -215,17 +252,18 @@ g_list_insert_sorted (GList *list, gpointer data, GCompareFunc func)
                prev = current;
        }
 
-       GList *node = new_node (prev, data, current);
+       node = new_node (prev, data, current);
        return list == current ? node : list;
 }
 
 GList*
 g_list_insert_before (GList *list, GList *sibling, gpointer data)
 {
-       if (!sibling)
-               return g_list_append (list, data);
-       GList *node = new_node (sibling->prev, data, sibling);
-       return list == sibling ? node : list;
+       if (sibling) {
+               GList *node = new_node (sibling->prev, data, sibling);
+               return list == sibling ? node : list;
+       }
+       return g_list_append (list, data);
 }
 
 void
@@ -237,12 +275,6 @@ g_list_foreach (GList *list, GFunc func, gpointer user_data)
        }
 }
 
-GList*
-g_list_sort (GList *list, GCompareFunc func)
-{
-       return NULL;
-}
-
 gint
 g_list_index (GList *list, gconstpointer data)
 {
@@ -293,3 +325,21 @@ g_list_copy (GList *list)
        return copy;
 }
 
+typedef GList list_node;
+#include "sort.frag.h"
+
+GList*
+g_list_sort (GList *list, GCompareFunc func)
+{
+       GList *current;
+       if (!list || !list->next)
+               return list;
+       list = do_sort (list, func);
+
+       /* Fixup: do_sort doesn't update 'prev' pointers */
+       list->prev = NULL;
+       for (current = list; current->next; current = current->next)
+               current->next->prev = current;
+
+       return list;
+}