After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 538584 - [PATCH] g_slist_foreach_remove() to remove some items in a GSList
[PATCH] g_slist_foreach_remove() to remove some items in a GSList
Status: RESOLVED OBSOLETE
Product: glib
Classification: Platform
Component: glist
2.17.x
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2008-06-16 10:54 UTC by Alban Crequy
Modified: 2018-05-24 11:27 UTC
See Also:
GNOME target: ---
GNOME version: Unversioned Enhancement


Attachments
glib_slist_foreach_remove.patch (5.68 KB, patch)
2008-06-16 10:57 UTC, Alban Crequy
needs-work Details | Review

Description Alban Crequy 2008-06-16 10:54:15 UTC
The patch adds:
- a new function g_slist_foreach_remove(): loop on a GSList and call a callback on each items. If the callback returns TRUE, remove the item from the list.
- a basic unit test for g_slist_foreach_remove()
- add the function in glib/glib.symbols
Comment 1 Alban Crequy 2008-06-16 10:57:49 UTC
Created attachment 112826 [details] [review]
glib_slist_foreach_remove.patch
Comment 2 Owen Taylor 2009-02-24 21:32:54 UTC
Idea of the addition makes a lot of sense to me. (Really needs a g_list_ equivalent - the api's are supposed to be the same))

+GSList *
+g_slist_foreach_remove (GSList *list,
+		     GRemoveFunc func,
+		     gpointer user_data)
+{
+  GSList *ret, *prev, *cur;
+
+  g_return_val_if_fail (list != NULL, NULL);

Filtering a NULL list is valid.

+  g_return_val_if_fail (func != NULL, NULL);
+
+  ret = list;
+  prev = NULL;
+  cur = list;
+
+  while (cur != NULL)
+    {
+      if (func (cur->data, user_data))
+        {
+          GList *tmp;
+
+          /* if we're removing the head of the list, update
+             what we're returning to be the next item */
+          if (ret == cur)
+            {
+              g_assert (prev == NULL);
+              ret = cur->next;
+            }
+          /* otherwise, update the previous element to refer
+             to the next one */
+          else
+            {
+              g_assert (prev != NULL);

I don't see the need for this assert - it's going to segfault immediately anyways.

+              prev->next = cur->next;
+            }
+
+          tmp = cur;
+          cur = cur->next;

I think it's simpler if you have a next local in the loop. Something along the line of (untested):

===
prev = NULL;
for (l = list; l; ) {
     GSList *next = l->next;

     if (func(...)) {
         if (prev)
             prev->next = next;
         else
             list = next;
         g_slist_free_1(l);
     } else {
          prev = l;
     }

     l = next;
  }
===

+          tmp->next = NULL;
+          g_slist_free_1 (tmp);

Nulling out not needed.

+ * Specifies the type of functions passed to g_slist_foreach_remove

g_slist_foreach_remove()

+ * Returns: TRUE to remove the item, FALSE to keep it

%TRUE / %FALSE

+_filter_lt2 (gpointer item, gpointer user_data)

No reason to _prefix local static functions.

+    st = g_slist_nth (slist, i - 2);
+    g_assert (*((gint*) st->data) == i);

There is g_slist_nth_data, probably even better to have a helper get_nth_int() to make the tests more readable and verifiable.
Comment 3 GNOME Infrastructure Team 2018-05-24 11:27:29 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/146.