Add unit tests for some more methods
[glib.git] / glib / gslist.c
blob47c50416aa205d6b0206eca4095007eb0ef9c517
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
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/.
27 /*
28 * MT safe
31 #include "config.h"
33 #include "glib.h"
34 #include "galias.h"
37 void g_slist_push_allocator (gpointer dummy) { /* present for binary compat only */ }
38 void g_slist_pop_allocator (void) { /* present for binary compat only */ }
40 #define _g_slist_alloc0() g_slice_new0 (GSList)
41 #define _g_slist_alloc() g_slice_new (GSList)
42 #define _g_slist_free1(slist) g_slice_free (GSList, slist)
44 GSList*
45 g_slist_alloc (void)
47 return _g_slist_alloc0 ();
50 /**
51 * g_slist_free:
52 * @list: a #GSList
54 * Frees all of the memory used by a #GSList.
55 * The freed elements are returned to the slice allocator.
57 void
58 g_slist_free (GSList *list)
60 g_slice_free_chain (GSList, list, next);
63 /**
64 * g_slist_free_1:
65 * @list: a #GSList element
67 * Frees one #GSList element.
68 * It is usually used after g_slist_remove_link().
70 void
71 g_slist_free_1 (GSList *list)
73 _g_slist_free1 (list);
76 /**
77 * g_slist_append:
78 * @list: a #GSList
79 * @data: the data for the new element
81 * Adds a new element on to the end of the list.
83 * <note><para>
84 * The return value is the new start of the list, which may
85 * have changed, so make sure you store the new value.
86 * </para></note>
88 * <note><para>
89 * Note that g_slist_append() has to traverse the entire list
90 * to find the end, which is inefficient when adding multiple
91 * elements. A common idiom to avoid the inefficiency is to prepend
92 * the elements and reverse the list when all elements have been added.
93 * </para></note>
95 * |[
96 * /&ast; Notice that these are initialized to the empty list. &ast;/
97 * GSList *list = NULL, *number_list = NULL;
99 * /&ast; This is a list of strings. &ast;/
100 * list = g_slist_append (list, "first");
101 * list = g_slist_append (list, "second");
103 * /&ast; This is a list of integers. &ast;/
104 * number_list = g_slist_append (number_list, GINT_TO_POINTER (27));
105 * number_list = g_slist_append (number_list, GINT_TO_POINTER (14));
106 * ]|
108 * Returns: the new start of the #GSList
110 GSList*
111 g_slist_append (GSList *list,
112 gpointer data)
114 GSList *new_list;
115 GSList *last;
117 new_list = _g_slist_alloc ();
118 new_list->data = data;
119 new_list->next = NULL;
121 if (list)
123 last = g_slist_last (list);
124 /* g_assert (last != NULL); */
125 last->next = new_list;
127 return list;
129 else
130 return new_list;
134 * g_slist_prepend:
135 * @list: a #GSList
136 * @data: the data for the new element
138 * Adds a new element on to the start of the list.
140 * <note><para>
141 * The return value is the new start of the list, which
142 * may have changed, so make sure you store the new value.
143 * </para></note>
145 * |[
146 * /&ast; Notice that it is initialized to the empty list. &ast;/
147 * GSList *list = NULL;
148 * list = g_slist_prepend (list, "last");
149 * list = g_slist_prepend (list, "first");
150 * ]|
152 * Returns: the new start of the #GSList
154 GSList*
155 g_slist_prepend (GSList *list,
156 gpointer data)
158 GSList *new_list;
160 new_list = _g_slist_alloc ();
161 new_list->data = data;
162 new_list->next = list;
164 return new_list;
168 * g_slist_insert:
169 * @list: a #GSList
170 * @data: the data for the new element
171 * @position: the position to insert the element.
172 * If this is negative, or is larger than the number
173 * of elements in the list, the new element is added on
174 * to the end of the list.
176 * Inserts a new element into the list at the given position.
178 * Returns: the new start of the #GSList
180 GSList*
181 g_slist_insert (GSList *list,
182 gpointer data,
183 gint position)
185 GSList *prev_list;
186 GSList *tmp_list;
187 GSList *new_list;
189 if (position < 0)
190 return g_slist_append (list, data);
191 else if (position == 0)
192 return g_slist_prepend (list, data);
194 new_list = _g_slist_alloc ();
195 new_list->data = data;
197 if (!list)
199 new_list->next = NULL;
200 return new_list;
203 prev_list = NULL;
204 tmp_list = list;
206 while ((position-- > 0) && tmp_list)
208 prev_list = tmp_list;
209 tmp_list = tmp_list->next;
212 if (prev_list)
214 new_list->next = prev_list->next;
215 prev_list->next = new_list;
217 else
219 new_list->next = list;
220 list = new_list;
223 return list;
227 * g_slist_insert_before:
228 * @slist: a #GSList
229 * @sibling: node to insert @data before
230 * @data: data to put in the newly-inserted node
232 * Inserts a node before @sibling containing @data.
234 * Returns: the new head of the list.
236 GSList*
237 g_slist_insert_before (GSList *slist,
238 GSList *sibling,
239 gpointer data)
241 if (!slist)
243 slist = _g_slist_alloc ();
244 slist->data = data;
245 slist->next = NULL;
246 g_return_val_if_fail (sibling == NULL, slist);
247 return slist;
249 else
251 GSList *node, *last = NULL;
253 for (node = slist; node; last = node, node = last->next)
254 if (node == sibling)
255 break;
256 if (!last)
258 node = _g_slist_alloc ();
259 node->data = data;
260 node->next = slist;
262 return node;
264 else
266 node = _g_slist_alloc ();
267 node->data = data;
268 node->next = last->next;
269 last->next = node;
271 return slist;
277 * g_slist_concat:
278 * @list1: a #GSList
279 * @list2: the #GSList to add to the end of the first #GSList
281 * Adds the second #GSList onto the end of the first #GSList.
282 * Note that the elements of the second #GSList are not copied.
283 * They are used directly.
285 * Returns: the start of the new #GSList
287 GSList *
288 g_slist_concat (GSList *list1, GSList *list2)
290 if (list2)
292 if (list1)
293 g_slist_last (list1)->next = list2;
294 else
295 list1 = list2;
298 return list1;
302 * g_slist_remove:
303 * @list: a #GSList
304 * @data: the data of the element to remove
306 * Removes an element from a #GSList.
307 * If two elements contain the same data, only the first is removed.
308 * If none of the elements contain the data, the #GSList is unchanged.
310 * Returns: the new start of the #GSList
312 GSList*
313 g_slist_remove (GSList *list,
314 gconstpointer data)
316 GSList *tmp, *prev = NULL;
318 tmp = list;
319 while (tmp)
321 if (tmp->data == data)
323 if (prev)
324 prev->next = tmp->next;
325 else
326 list = tmp->next;
328 g_slist_free_1 (tmp);
329 break;
331 prev = tmp;
332 tmp = prev->next;
335 return list;
339 * g_slist_remove_all:
340 * @list: a #GSList
341 * @data: data to remove
343 * Removes all list nodes with data equal to @data.
344 * Returns the new head of the list. Contrast with
345 * g_slist_remove() which removes only the first node
346 * matching the given data.
348 * Returns: new head of @list
350 GSList*
351 g_slist_remove_all (GSList *list,
352 gconstpointer data)
354 GSList *tmp, *prev = NULL;
356 tmp = list;
357 while (tmp)
359 if (tmp->data == data)
361 GSList *next = tmp->next;
363 if (prev)
364 prev->next = next;
365 else
366 list = next;
368 g_slist_free_1 (tmp);
369 tmp = next;
371 else
373 prev = tmp;
374 tmp = prev->next;
378 return list;
381 static inline GSList*
382 _g_slist_remove_link (GSList *list,
383 GSList *link)
385 GSList *tmp;
386 GSList *prev;
388 prev = NULL;
389 tmp = list;
391 while (tmp)
393 if (tmp == link)
395 if (prev)
396 prev->next = tmp->next;
397 if (list == tmp)
398 list = list->next;
400 tmp->next = NULL;
401 break;
404 prev = tmp;
405 tmp = tmp->next;
408 return list;
412 * g_slist_remove_link:
413 * @list: a #GSList
414 * @link_: an element in the #GSList
416 * Removes an element from a #GSList, without
417 * freeing the element. The removed element's next
418 * link is set to %NULL, so that it becomes a
419 * self-contained list with one element.
421 * Returns: the new start of the #GSList, without the element
423 GSList*
424 g_slist_remove_link (GSList *list,
425 GSList *link_)
427 return _g_slist_remove_link (list, link_);
431 * g_slist_delete_link:
432 * @list: a #GSList
433 * @link_: node to delete
435 * Removes the node link_ from the list and frees it.
436 * Compare this to g_slist_remove_link() which removes the node
437 * without freeing it.
439 * Returns: the new head of @list
441 GSList*
442 g_slist_delete_link (GSList *list,
443 GSList *link_)
445 list = _g_slist_remove_link (list, link_);
446 _g_slist_free1 (link_);
448 return list;
452 * g_slist_copy:
453 * @list: a #GSList
455 * Copies a #GSList.
457 * <note><para>
458 * Note that this is a "shallow" copy. If the list elements
459 * consist of pointers to data, the pointers are copied but
460 * the actual data isn't.
461 * </para></note>
463 * Returns: a copy of @list
465 GSList*
466 g_slist_copy (GSList *list)
468 GSList *new_list = NULL;
470 if (list)
472 GSList *last;
474 new_list = _g_slist_alloc ();
475 new_list->data = list->data;
476 last = new_list;
477 list = list->next;
478 while (list)
480 last->next = _g_slist_alloc ();
481 last = last->next;
482 last->data = list->data;
483 list = list->next;
485 last->next = NULL;
488 return new_list;
492 * g_slist_reverse:
493 * @list: a #GSList
495 * Reverses a #GSList.
497 * Returns: the start of the reversed #GSList
499 GSList*
500 g_slist_reverse (GSList *list)
502 GSList *prev = NULL;
504 while (list)
506 GSList *next = list->next;
508 list->next = prev;
510 prev = list;
511 list = next;
514 return prev;
518 * g_slist_nth:
519 * @list: a #GSList
520 * @n: the position of the element, counting from 0
522 * Gets the element at the given position in a #GSList.
524 * Returns: the element, or %NULL if the position is off
525 * the end of the #GSList
527 GSList*
528 g_slist_nth (GSList *list,
529 guint n)
531 while (n-- > 0 && list)
532 list = list->next;
534 return list;
538 * g_slist_nth_data:
539 * @list: a #GSList
540 * @n: the position of the element
542 * Gets the data of the element at the given position.
544 * Returns: the element's data, or %NULL if the position
545 * is off the end of the #GSList
547 gpointer
548 g_slist_nth_data (GSList *list,
549 guint n)
551 while (n-- > 0 && list)
552 list = list->next;
554 return list ? list->data : NULL;
558 * g_slist_find:
559 * @list: a #GSList
560 * @data: the element data to find
562 * Finds the element in a #GSList which
563 * contains the given data.
565 * Returns: the found #GSList element,
566 * or %NULL if it is not found
568 GSList*
569 g_slist_find (GSList *list,
570 gconstpointer data)
572 while (list)
574 if (list->data == data)
575 break;
576 list = list->next;
579 return list;
584 * g_slist_find_custom:
585 * @list: a #GSList
586 * @data: user data passed to the function
587 * @func: the function to call for each element.
588 * It should return 0 when the desired element is found
590 * Finds an element in a #GSList, using a supplied function to
591 * find the desired element. It iterates over the list, calling
592 * the given function which should return 0 when the desired
593 * element is found. The function takes two #gconstpointer arguments,
594 * the #GSList element's data as the first argument and the
595 * given user data.
597 * Returns: the found #GSList element, or %NULL if it is not found
599 GSList*
600 g_slist_find_custom (GSList *list,
601 gconstpointer data,
602 GCompareFunc func)
604 g_return_val_if_fail (func != NULL, list);
606 while (list)
608 if (! func (list->data, data))
609 return list;
610 list = list->next;
613 return NULL;
617 * g_slist_position:
618 * @list: a #GSList
619 * @llink: an element in the #GSList
621 * Gets the position of the given element
622 * in the #GSList (starting from 0).
624 * Returns: the position of the element in the #GSList,
625 * or -1 if the element is not found
627 gint
628 g_slist_position (GSList *list,
629 GSList *llink)
631 gint i;
633 i = 0;
634 while (list)
636 if (list == llink)
637 return i;
638 i++;
639 list = list->next;
642 return -1;
646 * g_slist_index:
647 * @list: a #GSList
648 * @data: the data to find
650 * Gets the position of the element containing
651 * the given data (starting from 0).
653 * Returns: the index of the element containing the data,
654 * or -1 if the data is not found
656 gint
657 g_slist_index (GSList *list,
658 gconstpointer data)
660 gint i;
662 i = 0;
663 while (list)
665 if (list->data == data)
666 return i;
667 i++;
668 list = list->next;
671 return -1;
675 * g_slist_last:
676 * @list: a #GSList
678 * Gets the last element in a #GSList.
680 * <note><para>
681 * This function iterates over the whole list.
682 * </para></note>
684 * Returns: the last element in the #GSList,
685 * or %NULL if the #GSList has no elements
687 GSList*
688 g_slist_last (GSList *list)
690 if (list)
692 while (list->next)
693 list = list->next;
696 return list;
700 * g_slist_length:
701 * @list: a #GSList
703 * Gets the number of elements in a #GSList.
705 * <note><para>
706 * This function iterates over the whole list to
707 * count its elements.
708 * </para></note>
710 * Returns: the number of elements in the #GSList
712 guint
713 g_slist_length (GSList *list)
715 guint length;
717 length = 0;
718 while (list)
720 length++;
721 list = list->next;
724 return length;
728 * g_slist_foreach:
729 * @list: a #GSList
730 * @func: the function to call with each element's data
731 * @user_data: user data to pass to the function
733 * Calls a function for each element of a #GSList.
735 void
736 g_slist_foreach (GSList *list,
737 GFunc func,
738 gpointer user_data)
740 while (list)
742 GSList *next = list->next;
743 (*func) (list->data, user_data);
744 list = next;
748 static GSList*
749 g_slist_insert_sorted_real (GSList *list,
750 gpointer data,
751 GFunc func,
752 gpointer user_data)
754 GSList *tmp_list = list;
755 GSList *prev_list = NULL;
756 GSList *new_list;
757 gint cmp;
759 g_return_val_if_fail (func != NULL, list);
761 if (!list)
763 new_list = _g_slist_alloc ();
764 new_list->data = data;
765 new_list->next = NULL;
766 return new_list;
769 cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
771 while ((tmp_list->next) && (cmp > 0))
773 prev_list = tmp_list;
774 tmp_list = tmp_list->next;
776 cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
779 new_list = _g_slist_alloc ();
780 new_list->data = data;
782 if ((!tmp_list->next) && (cmp > 0))
784 tmp_list->next = new_list;
785 new_list->next = NULL;
786 return list;
789 if (prev_list)
791 prev_list->next = new_list;
792 new_list->next = tmp_list;
793 return list;
795 else
797 new_list->next = list;
798 return new_list;
803 * g_slist_insert_sorted:
804 * @list: a #GSList
805 * @data: the data for the new element
806 * @func: the function to compare elements in the list.
807 * It should return a number > 0 if the first parameter
808 * comes after the second parameter in the sort order.
810 * Inserts a new element into the list, using the given
811 * comparison function to determine its position.
813 * Returns: the new start of the #GSList
815 GSList*
816 g_slist_insert_sorted (GSList *list,
817 gpointer data,
818 GCompareFunc func)
820 return g_slist_insert_sorted_real (list, data, (GFunc) func, NULL);
824 * g_slist_insert_sorted_with_data:
825 * @list: a #GSList
826 * @data: the data for the new element
827 * @func: the function to compare elements in the list.
828 * It should return a number > 0 if the first parameter
829 * comes after the second parameter in the sort order.
830 * @user_data: data to pass to comparison function
832 * Inserts a new element into the list, using the given
833 * comparison function to determine its position.
835 * Returns: the new start of the #GSList
837 * Since: 2.10
839 GSList*
840 g_slist_insert_sorted_with_data (GSList *list,
841 gpointer data,
842 GCompareDataFunc func,
843 gpointer user_data)
845 return g_slist_insert_sorted_real (list, data, (GFunc) func, user_data);
848 static GSList *
849 g_slist_sort_merge (GSList *l1,
850 GSList *l2,
851 GFunc compare_func,
852 gpointer user_data)
854 GSList list, *l;
855 gint cmp;
857 l=&list;
859 while (l1 && l2)
861 cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
863 if (cmp <= 0)
865 l=l->next=l1;
866 l1=l1->next;
868 else
870 l=l->next=l2;
871 l2=l2->next;
874 l->next= l1 ? l1 : l2;
876 return list.next;
879 static GSList *
880 g_slist_sort_real (GSList *list,
881 GFunc compare_func,
882 gpointer user_data)
884 GSList *l1, *l2;
886 if (!list)
887 return NULL;
888 if (!list->next)
889 return list;
891 l1 = list;
892 l2 = list->next;
894 while ((l2 = l2->next) != NULL)
896 if ((l2 = l2->next) == NULL)
897 break;
898 l1=l1->next;
900 l2 = l1->next;
901 l1->next = NULL;
903 return g_slist_sort_merge (g_slist_sort_real (list, compare_func, user_data),
904 g_slist_sort_real (l2, compare_func, user_data),
905 compare_func,
906 user_data);
910 * g_slist_sort:
911 * @list: a #GSList
912 * @compare_func: the comparison function used to sort the #GSList.
913 * This function is passed the data from 2 elements of the #GSList
914 * and should return 0 if they are equal, a negative value if the
915 * first element comes before the second, or a positive value if
916 * the first element comes after the second.
918 * Sorts a #GSList using the given comparison function.
920 * Returns: the start of the sorted #GSList
922 GSList *
923 g_slist_sort (GSList *list,
924 GCompareFunc compare_func)
926 return g_slist_sort_real (list, (GFunc) compare_func, NULL);
930 * g_slist_sort_with_data:
931 * @list: a #GSList
932 * @compare_func: comparison function
933 * @user_data: data to pass to comparison function
935 * Like g_slist_sort(), but the sort function accepts a user data argument.
937 * Returns: new head of the list
939 GSList *
940 g_slist_sort_with_data (GSList *list,
941 GCompareDataFunc compare_func,
942 gpointer user_data)
944 return g_slist_sort_real (list, (GFunc) compare_func, user_data);
947 #define __G_SLIST_C__
948 #include "galiasdef.c"