Coverage Report

Created: 2025-12-31 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib/glib/gslist.c
Line
Count
Source
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
/*
21
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22
 * file for a list of people on the GLib Team.  See the ChangeLog
23
 * files for a list of changes.  These files are distributed with
24
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
25
 */
26
27
/*
28
 * MT safe
29
 */
30
31
#include "config.h"
32
33
#include "gslist.h"
34
35
#include "gtestutils.h"
36
#include "gslice.h"
37
38
/**
39
 * GSList:
40
 * @data: holds the element's data, which can be a pointer to any kind
41
 *        of data, or any integer value using the
42
 *        [Type Conversion Macros](conversion-macros.html#conversion-macros)
43
 * @next: contains the link to the next element in the list.
44
 *
45
 * The #GSList struct is used for each element in the singly-linked
46
 * list.
47
 **/
48
49
/**
50
 * g_slist_next:
51
 * @slist: an element in a #GSList.
52
 *
53
 * A convenience macro to get the next element in a #GSList.
54
 * Note that it is considered perfectly acceptable to access
55
 * @slist->next directly.
56
 *
57
 * Returns: the next element, or %NULL if there are no more elements.
58
 **/
59
60
134k
#define _g_slist_alloc0()       g_slice_new0 (GSList)
61
1.69k
#define _g_slist_alloc()        g_slice_new (GSList)
62
137
#define _g_slist_free1(slist)   g_slice_free (GSList, slist)
63
64
/**
65
 * g_slist_alloc:
66
 *
67
 * Allocates space for one #GSList element. It is called by the
68
 * g_slist_append(), g_slist_prepend(), g_slist_insert() and
69
 * g_slist_insert_sorted() functions and so is rarely used on its own.
70
 *
71
 * Returns: a pointer to the newly-allocated #GSList element.
72
 **/
73
GSList*
74
g_slist_alloc (void)
75
134k
{
76
134k
  return _g_slist_alloc0 ();
77
134k
}
78
79
/**
80
 * g_slist_free:
81
 * @list: the first link of a #GSList
82
 *
83
 * Frees all of the memory used by a #GSList.
84
 * The freed elements are returned to the slice allocator.
85
 *
86
 * If list elements contain dynamically-allocated memory,
87
 * you should either use g_slist_free_full() or free them manually
88
 * first.
89
 *
90
 * It can be combined with g_steal_pointer() to ensure the list head pointer
91
 * is not left dangling:
92
 * |[<!-- language="C" -->
93
 * GSList *list_of_borrowed_things = …;  /<!-- -->* (transfer container) *<!-- -->/
94
 * g_slist_free (g_steal_pointer (&list_of_borrowed_things));
95
 * ]|
96
 */
97
void
98
g_slist_free (GSList *list)
99
33.6k
{
100
33.6k
  g_slice_free_chain (GSList, list, next);
101
33.6k
}
102
103
/**
104
 * g_slist_free_1:
105
 * @list: a #GSList element
106
 *
107
 * Frees one #GSList element.
108
 * It is usually used after g_slist_remove_link().
109
 */
110
/**
111
 * g_slist_free1:
112
 *
113
 * A macro which does the same as g_slist_free_1().
114
 *
115
 * Since: 2.10
116
 **/
117
void
118
g_slist_free_1 (GSList *list)
119
137
{
120
137
  _g_slist_free1 (list);
121
137
}
122
123
/**
124
 * g_slist_free_full:
125
 * @list: the first link of a #GSList
126
 * @free_func: the function to be called to free each element's data
127
 *
128
 * Convenience method, which frees all the memory used by a #GSList, and
129
 * calls the specified destroy function on every element's data.
130
 *
131
 * @free_func must not modify the list (eg, by removing the freed
132
 * element from it).
133
 *
134
 * It can be combined with g_steal_pointer() to ensure the list head pointer
135
 * is not left dangling ­— this also has the nice property that the head pointer
136
 * is cleared before any of the list elements are freed, to prevent double frees
137
 * from @free_func:
138
 * |[<!-- language="C" -->
139
 * GSList *list_of_owned_things = …;  /<!-- -->* (transfer full) (element-type GObject) *<!-- -->/
140
 * g_slist_free_full (g_steal_pointer (&list_of_owned_things), g_object_unref);
141
 * ]|
142
 *
143
 * Since: 2.28
144
 **/
145
void
146
g_slist_free_full (GSList         *list,
147
       GDestroyNotify  free_func)
148
17.0k
{
149
17.0k
  g_slist_foreach (list, (GFunc) free_func, NULL);
150
17.0k
  g_slist_free (list);
151
17.0k
}
152
153
/**
154
 * g_slist_append:
155
 * @list: (nullable): a #GSList
156
 * @data: the data for the new element
157
 *
158
 * Adds a new element on to the end of the list.
159
 *
160
 * Note that the return value is the new start of the list
161
 * if @list was empty; make sure you store the new value.
162
 *
163
 * Note that g_slist_append() has to traverse the entire list
164
 * to find the end, which is inefficient when adding multiple
165
 * elements. A common idiom to avoid the inefficiency is to prepend
166
 * the elements and reverse the list when all elements have been added.
167
 *
168
 * |[<!-- language="C" --> 
169
 * // Notice that these are initialized to the empty list.
170
 * GSList *list = NULL, *number_list = NULL;
171
 *
172
 * // This is a list of strings.
173
 * list = g_slist_append (list, "first");
174
 * list = g_slist_append (list, "second");
175
 *
176
 * // This is a list of integers.
177
 * number_list = g_slist_append (number_list, GINT_TO_POINTER (27));
178
 * number_list = g_slist_append (number_list, GINT_TO_POINTER (14));
179
 * ]|
180
 *
181
 * Returns: either @list or the new start of the #GSList if @list was %NULL
182
 */
183
GSList*
184
g_slist_append (GSList   *list,
185
                gpointer  data)
186
1.08k
{
187
1.08k
  GSList *new_list;
188
1.08k
  GSList *last;
189
190
1.08k
  new_list = _g_slist_alloc ();
191
1.08k
  new_list->data = data;
192
1.08k
  new_list->next = NULL;
193
194
1.08k
  if (list)
195
22
    {
196
22
      last = g_slist_last (list);
197
      /* g_assert (last != NULL); */
198
22
      last->next = new_list;
199
200
22
      return list;
201
22
    }
202
1.06k
  else
203
1.06k
    return new_list;
204
1.08k
}
205
206
/**
207
 * g_slist_prepend:
208
 * @list: (nullable): a #GSList
209
 * @data: the data for the new element
210
 *
211
 * Adds a new element on to the start of the list.
212
 *
213
 * Note that the return value is the new start of the list, 
214
 * which will have changed, so make sure you store the new value.
215
 *
216
 * |[<!-- language="C" --> 
217
 * // Notice that it is initialized to the empty list.
218
 * GSList *list = NULL;
219
 * list = g_slist_prepend (list, "last");
220
 * list = g_slist_prepend (list, "first");
221
 * ]|
222
 *
223
 * Returns: a pointer to the newly prepended element, 
224
 * which is the new start of the #GSList
225
 */
226
GSList*
227
g_slist_prepend (GSList   *list,
228
                 gpointer  data)
229
593
{
230
593
  GSList *new_list;
231
232
593
  new_list = _g_slist_alloc ();
233
593
  new_list->data = data;
234
593
  new_list->next = list;
235
236
593
  return new_list;
237
593
}
238
239
/**
240
 * g_slist_insert:
241
 * @list: (nullable): a #GSList
242
 * @data: the data for the new element
243
 * @position: the position to insert the element.
244
 *     If this is negative, or is larger than the number
245
 *     of elements in the list, the new element is added on
246
 *     to the end of the list.
247
 *
248
 * Inserts a new element into the list at the given position.
249
 *
250
 * Returns: the (possibly changed) start of the #GSList
251
 */
252
GSList*
253
g_slist_insert (GSList   *list,
254
                gpointer  data,
255
                gint      position)
256
0
{
257
0
  GSList *prev_list;
258
0
  GSList *tmp_list;
259
0
  GSList *new_list;
260
261
0
  if (position < 0)
262
0
    return g_slist_append (list, data);
263
0
  else if (position == 0)
264
0
    return g_slist_prepend (list, data);
265
266
0
  new_list = _g_slist_alloc ();
267
0
  new_list->data = data;
268
269
0
  if (!list)
270
0
    {
271
0
      new_list->next = NULL;
272
0
      return new_list;
273
0
    }
274
275
0
  prev_list = NULL;
276
0
  tmp_list = list;
277
278
0
  while ((position-- > 0) && tmp_list)
279
0
    {
280
0
      prev_list = tmp_list;
281
0
      tmp_list = tmp_list->next;
282
0
    }
283
284
0
  new_list->next = prev_list->next;
285
0
  prev_list->next = new_list;
286
287
0
  return list;
288
0
}
289
290
/**
291
 * g_slist_insert_before:
292
 * @slist: (nullable): a #GSList
293
 * @sibling: node to insert @data before
294
 * @data: data to put in the newly-inserted node
295
 *
296
 * Inserts a node before @sibling containing @data.
297
 *
298
 * Returns: the new head of the list.
299
 */
300
GSList*
301
g_slist_insert_before (GSList  *slist,
302
                       GSList  *sibling,
303
                       gpointer data)
304
0
{
305
0
  if (!slist)
306
0
    {
307
0
      slist = _g_slist_alloc ();
308
0
      slist->data = data;
309
0
      slist->next = NULL;
310
0
      g_return_val_if_fail (sibling == NULL, slist);
311
0
      return slist;
312
0
    }
313
0
  else
314
0
    {
315
0
      GSList *node, *last = NULL;
316
317
0
      for (node = slist; node; last = node, node = last->next)
318
0
        if (node == sibling)
319
0
          break;
320
0
      if (!last)
321
0
        {
322
0
          node = _g_slist_alloc ();
323
0
          node->data = data;
324
0
          node->next = slist;
325
326
0
          return node;
327
0
        }
328
0
      else
329
0
        {
330
0
          node = _g_slist_alloc ();
331
0
          node->data = data;
332
0
          node->next = last->next;
333
0
          last->next = node;
334
335
0
          return slist;
336
0
        }
337
0
    }
338
0
}
339
340
/**
341
 * g_slist_concat:
342
 * @list1: a #GSList
343
 * @list2: the #GSList to add to the end of the first #GSList
344
 *
345
 * Adds the second #GSList onto the end of the first #GSList.
346
 * Note that the elements of the second #GSList are not copied.
347
 * They are used directly.
348
 *
349
 * Returns: the start of the new #GSList
350
 */
351
GSList *
352
g_slist_concat (GSList *list1, GSList *list2)
353
520k
{
354
520k
  if (list2)
355
446k
    {
356
446k
      if (list1)
357
446k
        g_slist_last (list1)->next = list2;
358
0
      else
359
0
        list1 = list2;
360
446k
    }
361
362
520k
  return list1;
363
520k
}
364
365
static GSList*
366
_g_slist_remove_data (GSList        *list,
367
                      gconstpointer  data,
368
                      gboolean       all)
369
137
{
370
137
  GSList *tmp = NULL;
371
137
  GSList **previous_ptr = &list;
372
373
137
  while (*previous_ptr)
374
137
    {
375
137
      tmp = *previous_ptr;
376
137
      if (tmp->data == data)
377
137
        {
378
137
          *previous_ptr = tmp->next;
379
137
          g_slist_free_1 (tmp);
380
137
          if (!all)
381
137
            break;
382
137
        }
383
0
      else
384
0
        {
385
0
          previous_ptr = &tmp->next;
386
0
        }
387
137
    }
388
389
137
  return list;
390
137
}
391
/**
392
 * g_slist_remove:
393
 * @list: a #GSList
394
 * @data: the data of the element to remove
395
 *
396
 * Removes an element from a #GSList.
397
 * If two elements contain the same data, only the first is removed.
398
 * If none of the elements contain the data, the #GSList is unchanged.
399
 *
400
 * Returns: the new start of the #GSList
401
 */
402
GSList*
403
g_slist_remove (GSList        *list,
404
                gconstpointer  data)
405
137
{
406
137
  return _g_slist_remove_data (list, data, FALSE);
407
137
}
408
409
/**
410
 * g_slist_remove_all:
411
 * @list: a #GSList
412
 * @data: data to remove
413
 *
414
 * Removes all list nodes with data equal to @data.
415
 * Returns the new head of the list. Contrast with
416
 * g_slist_remove() which removes only the first node
417
 * matching the given data.
418
 *
419
 * Returns: new head of @list
420
 */
421
GSList*
422
g_slist_remove_all (GSList        *list,
423
                    gconstpointer  data)
424
0
{
425
0
  return _g_slist_remove_data (list, data, TRUE);
426
0
}
427
428
static inline GSList*
429
_g_slist_remove_link (GSList *list,
430
                      GSList *link)
431
386k
{
432
386k
  GSList *tmp = NULL;
433
386k
  GSList **previous_ptr = &list;
434
435
386k
  while (*previous_ptr)
436
386k
    {
437
386k
      tmp = *previous_ptr;
438
386k
      if (tmp == link)
439
386k
        {
440
386k
          *previous_ptr = tmp->next;
441
386k
          tmp->next = NULL;
442
386k
          break;
443
386k
        }
444
445
0
      previous_ptr = &tmp->next;
446
0
    }
447
448
386k
  return list;
449
386k
}
450
451
/**
452
 * g_slist_remove_link:
453
 * @list: a #GSList
454
 * @link_: an element in the #GSList
455
 *
456
 * Removes an element from a #GSList, without
457
 * freeing the element. The removed element's next
458
 * link is set to %NULL, so that it becomes a
459
 * self-contained list with one element.
460
 *
461
 * Removing arbitrary nodes from a singly-linked list
462
 * requires time that is proportional to the length of the list
463
 * (ie. O(n)). If you find yourself using g_slist_remove_link()
464
 * frequently, you should consider a different data structure,
465
 * such as the doubly-linked #GList.
466
 *
467
 * Returns: the new start of the #GSList, without the element
468
 */
469
GSList*
470
g_slist_remove_link (GSList *list,
471
                     GSList *link_)
472
386k
{
473
386k
  return _g_slist_remove_link (list, link_);
474
386k
}
475
476
/**
477
 * g_slist_delete_link:
478
 * @list: a #GSList
479
 * @link_: node to delete
480
 *
481
 * Removes the node link_ from the list and frees it.
482
 * Compare this to g_slist_remove_link() which removes the node
483
 * without freeing it.
484
 *
485
 * Removing arbitrary nodes from a singly-linked list requires time
486
 * that is proportional to the length of the list (ie. O(n)). If you
487
 * find yourself using g_slist_delete_link() frequently, you should
488
 * consider a different data structure, such as the doubly-linked
489
 * #GList.
490
 *
491
 * Returns: the new head of @list
492
 */
493
GSList*
494
g_slist_delete_link (GSList *list,
495
                     GSList *link_)
496
0
{
497
0
  list = _g_slist_remove_link (list, link_);
498
0
  _g_slist_free1 (link_);
499
500
0
  return list;
501
0
}
502
503
/**
504
 * g_slist_copy:
505
 * @list: a #GSList
506
 *
507
 * Copies a #GSList.
508
 *
509
 * Note that this is a "shallow" copy. If the list elements
510
 * consist of pointers to data, the pointers are copied but
511
 * the actual data isn't. See g_slist_copy_deep() if you need
512
 * to copy the data as well.
513
 *
514
 * Returns: a copy of @list
515
 */
516
GSList*
517
g_slist_copy (GSList *list)
518
24
{
519
24
  return g_slist_copy_deep (list, NULL, NULL);
520
24
}
521
522
/**
523
 * g_slist_copy_deep:
524
 * @list: a #GSList
525
 * @func: (scope call): a copy function used to copy every element in the list
526
 * @user_data: user data passed to the copy function @func, or #NULL
527
 *
528
 * Makes a full (deep) copy of a #GSList.
529
 *
530
 * In contrast with g_slist_copy(), this function uses @func to make a copy of
531
 * each list element, in addition to copying the list container itself.
532
 *
533
 * @func, as a #GCopyFunc, takes two arguments, the data to be copied
534
 * and a @user_data pointer. On common processor architectures, it's safe to
535
 * pass %NULL as @user_data if the copy function takes only one argument. You
536
 * may get compiler warnings from this though if compiling with GCC’s
537
 * `-Wcast-function-type` warning.
538
 *
539
 * For instance, if @list holds a list of GObjects, you can do:
540
 * |[<!-- language="C" --> 
541
 * another_list = g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
542
 * ]|
543
 *
544
 * And, to entirely free the new list, you could do:
545
 * |[<!-- language="C" --> 
546
 * g_slist_free_full (another_list, g_object_unref);
547
 * ]|
548
 *
549
 * Returns: a full copy of @list, use g_slist_free_full() to free it
550
 *
551
 * Since: 2.34
552
 */
553
GSList*
554
g_slist_copy_deep (GSList *list, GCopyFunc func, gpointer user_data)
555
24
{
556
24
  GSList *new_list = NULL;
557
558
24
  if (list)
559
6
    {
560
6
      GSList *last;
561
562
6
      new_list = _g_slist_alloc ();
563
6
      if (func)
564
0
        new_list->data = func (list->data, user_data);
565
6
      else
566
6
        new_list->data = list->data;
567
6
      last = new_list;
568
6
      list = list->next;
569
15
      while (list)
570
9
        {
571
9
          last->next = _g_slist_alloc ();
572
9
          last = last->next;
573
9
          if (func)
574
0
            last->data = func (list->data, user_data);
575
9
          else
576
9
            last->data = list->data;
577
9
          list = list->next;
578
9
        }
579
6
      last->next = NULL;
580
6
    }
581
582
24
  return new_list;
583
24
}
584
585
/**
586
 * g_slist_reverse:
587
 * @list: a #GSList
588
 *
589
 * Reverses a #GSList.
590
 *
591
 * Returns: the start of the reversed #GSList
592
 */
593
GSList*
594
g_slist_reverse (GSList *list)
595
0
{
596
0
  GSList *prev = NULL;
597
598
0
  while (list)
599
0
    {
600
0
      GSList *next = list->next;
601
602
0
      list->next = prev;
603
604
0
      prev = list;
605
0
      list = next;
606
0
    }
607
608
0
  return prev;
609
0
}
610
611
/**
612
 * g_slist_nth:
613
 * @list: a #GSList
614
 * @n: the position of the element, counting from 0
615
 *
616
 * Gets the element at the given position in a #GSList.
617
 *
618
 * Returns: the element, or %NULL if the position is off
619
 *     the end of the #GSList
620
 */
621
GSList*
622
g_slist_nth (GSList *list,
623
             guint   n)
624
0
{
625
0
  while (n-- > 0 && list)
626
0
    list = list->next;
627
628
0
  return list;
629
0
}
630
631
/**
632
 * g_slist_nth_data:
633
 * @list: a #GSList
634
 * @n: the position of the element
635
 *
636
 * Gets the data of the element at the given position.
637
 *
638
 * Returns: the element's data, or %NULL if the position
639
 *     is off the end of the #GSList
640
 */
641
gpointer
642
g_slist_nth_data (GSList   *list,
643
                  guint     n)
644
0
{
645
0
  while (n-- > 0 && list)
646
0
    list = list->next;
647
648
0
  return list ? list->data : NULL;
649
0
}
650
651
/**
652
 * g_slist_find:
653
 * @list: a #GSList
654
 * @data: the element data to find
655
 *
656
 * Finds the element in a #GSList which
657
 * contains the given data.
658
 *
659
 * Returns: the found #GSList element,
660
 *     or %NULL if it is not found
661
 */
662
GSList*
663
g_slist_find (GSList        *list,
664
              gconstpointer  data)
665
137
{
666
161
  while (list)
667
24
    {
668
24
      if (list->data == data)
669
0
        break;
670
24
      list = list->next;
671
24
    }
672
673
137
  return list;
674
137
}
675
676
677
/**
678
 * g_slist_find_custom:
679
 * @list: a #GSList
680
 * @data: user data passed to the function
681
 * @func: (scope call): the function to call for each element.
682
 *     It should return 0 when the desired element is found
683
 *
684
 * Finds an element in a #GSList, using a supplied function to
685
 * find the desired element. It iterates over the list, calling
686
 * the given function which should return 0 when the desired
687
 * element is found. The function takes two #gconstpointer arguments,
688
 * the #GSList element's data as the first argument and the
689
 * given user data.
690
 *
691
 * Returns: the found #GSList element, or %NULL if it is not found
692
 */
693
GSList*
694
g_slist_find_custom (GSList        *list,
695
                     gconstpointer  data,
696
                     GCompareFunc   func)
697
0
{
698
0
  g_return_val_if_fail (func != NULL, list);
699
700
0
  while (list)
701
0
    {
702
0
      if (! func (list->data, data))
703
0
        return list;
704
0
      list = list->next;
705
0
    }
706
707
0
  return NULL;
708
0
}
709
710
/**
711
 * g_slist_position:
712
 * @list: a #GSList
713
 * @llink: an element in the #GSList
714
 *
715
 * Gets the position of the given element
716
 * in the #GSList (starting from 0).
717
 *
718
 * Returns: the position of the element in the #GSList,
719
 *     or -1 if the element is not found
720
 */
721
gint
722
g_slist_position (GSList *list,
723
                  GSList *llink)
724
0
{
725
0
  gint i;
726
727
0
  i = 0;
728
0
  while (list)
729
0
    {
730
0
      if (list == llink)
731
0
        return i;
732
0
      i++;
733
0
      list = list->next;
734
0
    }
735
736
0
  return -1;
737
0
}
738
739
/**
740
 * g_slist_index:
741
 * @list: a #GSList
742
 * @data: the data to find
743
 *
744
 * Gets the position of the element containing
745
 * the given data (starting from 0).
746
 *
747
 * Returns: the index of the element containing the data,
748
 *     or -1 if the data is not found
749
 */
750
gint
751
g_slist_index (GSList        *list,
752
               gconstpointer  data)
753
0
{
754
0
  gint i;
755
756
0
  i = 0;
757
0
  while (list)
758
0
    {
759
0
      if (list->data == data)
760
0
        return i;
761
0
      i++;
762
0
      list = list->next;
763
0
    }
764
765
0
  return -1;
766
0
}
767
768
/**
769
 * g_slist_last:
770
 * @list: a #GSList
771
 *
772
 * Gets the last element in a #GSList.
773
 *
774
 * This function iterates over the whole list.
775
 *
776
 * Returns: the last element in the #GSList,
777
 *     or %NULL if the #GSList has no elements
778
 */
779
GSList*
780
g_slist_last (GSList *list)
781
446k
{
782
446k
  if (list)
783
446k
    {
784
446k
      while (list->next)
785
17
        list = list->next;
786
446k
    }
787
788
446k
  return list;
789
446k
}
790
791
/**
792
 * g_slist_length:
793
 * @list: a #GSList
794
 *
795
 * Gets the number of elements in a #GSList.
796
 *
797
 * This function iterates over the whole list to
798
 * count its elements. To check whether the list is non-empty, it is faster to
799
 * check @list against %NULL.
800
 *
801
 * Returns: the number of elements in the #GSList
802
 */
803
guint
804
g_slist_length (GSList *list)
805
33
{
806
33
  guint length;
807
808
33
  length = 0;
809
48
  while (list)
810
15
    {
811
15
      length++;
812
15
      list = list->next;
813
15
    }
814
815
33
  return length;
816
33
}
817
818
/**
819
 * g_slist_foreach:
820
 * @list: a #GSList
821
 * @func: (scope call): the function to call with each element's data
822
 * @user_data: user data to pass to the function
823
 *
824
 * Calls a function for each element of a #GSList.
825
 *
826
 * It is safe for @func to remove the element from @list, but it must
827
 * not modify any part of the list after that element.
828
 */
829
void
830
g_slist_foreach (GSList   *list,
831
                 GFunc     func,
832
                 gpointer  user_data)
833
17.0k
{
834
130k
  while (list)
835
112k
    {
836
112k
      GSList *next = list->next;
837
112k
      (*func) (list->data, user_data);
838
112k
      list = next;
839
112k
    }
840
17.0k
}
841
842
static GSList*
843
g_slist_insert_sorted_real (GSList   *list,
844
                            gpointer  data,
845
                            GFunc     func,
846
                            gpointer  user_data)
847
0
{
848
0
  GSList *tmp_list = list;
849
0
  GSList *prev_list = NULL;
850
0
  GSList *new_list;
851
0
  gint cmp;
852
853
0
  g_return_val_if_fail (func != NULL, list);
854
855
0
  if (!list)
856
0
    {
857
0
      new_list = _g_slist_alloc ();
858
0
      new_list->data = data;
859
0
      new_list->next = NULL;
860
0
      return new_list;
861
0
    }
862
863
0
  cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
864
865
0
  while ((tmp_list->next) && (cmp > 0))
866
0
    {
867
0
      prev_list = tmp_list;
868
0
      tmp_list = tmp_list->next;
869
870
0
      cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
871
0
    }
872
873
0
  new_list = _g_slist_alloc ();
874
0
  new_list->data = data;
875
876
0
  if ((!tmp_list->next) && (cmp > 0))
877
0
    {
878
0
      tmp_list->next = new_list;
879
0
      new_list->next = NULL;
880
0
      return list;
881
0
    }
882
883
0
  if (prev_list)
884
0
    {
885
0
      prev_list->next = new_list;
886
0
      new_list->next = tmp_list;
887
0
      return list;
888
0
    }
889
0
  else
890
0
    {
891
0
      new_list->next = list;
892
0
      return new_list;
893
0
    }
894
0
}
895
896
/**
897
 * g_slist_insert_sorted:
898
 * @list: a #GSList
899
 * @data: the data for the new element
900
 * @func: (scope call): the function to compare elements in the list.
901
 *     It should return a number > 0 if the first parameter
902
 *     comes after the second parameter in the sort order.
903
 *
904
 * Inserts a new element into the list, using the given
905
 * comparison function to determine its position.
906
 *
907
 * Returns: the new start of the #GSList
908
 */
909
GSList*
910
g_slist_insert_sorted (GSList       *list,
911
                       gpointer      data,
912
                       GCompareFunc  func)
913
0
{
914
0
  return g_slist_insert_sorted_real (list, data, (GFunc) func, NULL);
915
0
}
916
917
/**
918
 * g_slist_insert_sorted_with_data:
919
 * @list: a #GSList
920
 * @data: the data for the new element
921
 * @func: (scope call): the function to compare elements in the list.
922
 *     It should return a number > 0 if the first parameter
923
 *     comes after the second parameter in the sort order.
924
 * @user_data: data to pass to comparison function
925
 *
926
 * Inserts a new element into the list, using the given
927
 * comparison function to determine its position.
928
 *
929
 * Returns: the new start of the #GSList
930
 *
931
 * Since: 2.10
932
 */
933
GSList*
934
g_slist_insert_sorted_with_data (GSList           *list,
935
                                 gpointer          data,
936
                                 GCompareDataFunc  func,
937
                                 gpointer          user_data)
938
0
{
939
0
  return g_slist_insert_sorted_real (list, data, (GFunc) func, user_data);
940
0
}
941
942
static GSList *
943
g_slist_sort_merge (GSList   *l1,
944
                    GSList   *l2,
945
                    GFunc     compare_func,
946
                    gpointer  user_data)
947
0
{
948
0
  GSList list, *l;
949
0
  gint cmp;
950
951
0
  l=&list;
952
953
0
  while (l1 && l2)
954
0
    {
955
0
      cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
956
957
0
      if (cmp <= 0)
958
0
        {
959
0
          l=l->next=l1;
960
0
          l1=l1->next;
961
0
        }
962
0
      else
963
0
        {
964
0
          l=l->next=l2;
965
0
          l2=l2->next;
966
0
        }
967
0
    }
968
0
  l->next= l1 ? l1 : l2;
969
970
0
  return list.next;
971
0
}
972
973
static GSList *
974
g_slist_sort_real (GSList   *list,
975
                   GFunc     compare_func,
976
                   gpointer  user_data)
977
28
{
978
28
  GSList *l1, *l2;
979
980
28
  if (!list)
981
28
    return NULL;
982
0
  if (!list->next)
983
0
    return list;
984
985
0
  l1 = list;
986
0
  l2 = list->next;
987
988
0
  while ((l2 = l2->next) != NULL)
989
0
    {
990
0
      if ((l2 = l2->next) == NULL)
991
0
        break;
992
0
      l1=l1->next;
993
0
    }
994
0
  l2 = l1->next;
995
0
  l1->next = NULL;
996
997
0
  return g_slist_sort_merge (g_slist_sort_real (list, compare_func, user_data),
998
0
                             g_slist_sort_real (l2, compare_func, user_data),
999
0
                             compare_func,
1000
0
                             user_data);
1001
0
}
1002
1003
/**
1004
 * g_slist_sort:
1005
 * @list: a #GSList
1006
 * @compare_func: (scope call): the comparison function used to sort the #GSList.
1007
 *     This function is passed the data from 2 elements of the #GSList
1008
 *     and should return 0 if they are equal, a negative value if the
1009
 *     first element comes before the second, or a positive value if
1010
 *     the first element comes after the second.
1011
 *
1012
 * Sorts a #GSList using the given comparison function. The algorithm
1013
 * used is a stable sort.
1014
 *
1015
 * Returns: the start of the sorted #GSList
1016
 */
1017
GSList *
1018
g_slist_sort (GSList       *list,
1019
              GCompareFunc  compare_func)
1020
28
{
1021
28
  return g_slist_sort_real (list, (GFunc) compare_func, NULL);
1022
28
}
1023
1024
/**
1025
 * g_slist_sort_with_data:
1026
 * @list: a #GSList
1027
 * @compare_func: (scope call): comparison function
1028
 * @user_data: data to pass to comparison function
1029
 *
1030
 * Like g_slist_sort(), but the sort function accepts a user data argument.
1031
 *
1032
 * Returns: new head of the list
1033
 */
1034
GSList *
1035
g_slist_sort_with_data (GSList           *list,
1036
                        GCompareDataFunc  compare_func,
1037
                        gpointer          user_data)
1038
0
{
1039
0
  return g_slist_sort_real (list, (GFunc) compare_func, user_data);
1040
0
}
1041
1042
/**
1043
 * g_clear_slist: (skip)
1044
 * @slist_ptr: (not nullable): a #GSList return location
1045
 * @destroy: (nullable): the function to pass to g_slist_free_full() or %NULL to not free elements
1046
 *
1047
 * Clears a pointer to a #GSList, freeing it and, optionally, freeing its elements using @destroy.
1048
 *
1049
 * @slist_ptr must be a valid pointer. If @slist_ptr points to a null #GSList, this does nothing.
1050
 *
1051
 * Since: 2.64
1052
 */
1053
void
1054
(g_clear_slist) (GSList         **slist_ptr,
1055
                 GDestroyNotify   destroy)
1056
0
{
1057
0
  GSList *slist;
1058
1059
0
  slist = *slist_ptr;
1060
0
  if (slist)
1061
0
    {
1062
0
      *slist_ptr = NULL;
1063
1064
0
      if (destroy)
1065
0
        g_slist_free_full (slist, destroy);
1066
0
      else
1067
0
        g_slist_free (slist);
1068
0
    }
1069
0
}