Minor doc markup fix.
[glib.git] / glib / gslist.c
blob18e08e42dc6ca0f502ae7bd0468e330d382c2f27
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 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include "glib.h"
38 #ifndef DISABLE_MEM_POOLS
39 struct _GAllocator /* from gmem.c */
41 gchar *name;
42 guint16 n_preallocs;
43 guint is_unused : 1;
44 guint type : 4;
45 GAllocator *last;
46 GMemChunk *mem_chunk;
47 GSList *free_lists; /* implementation specific */
50 G_LOCK_DEFINE_STATIC (current_allocator);
51 static GAllocator *current_allocator = NULL;
53 /* HOLDS: current_allocator_lock */
54 static void
55 g_slist_validate_allocator (GAllocator *allocator)
57 g_return_if_fail (allocator != NULL);
58 g_return_if_fail (allocator->is_unused == TRUE);
60 if (allocator->type != G_ALLOCATOR_SLIST)
62 allocator->type = G_ALLOCATOR_SLIST;
63 if (allocator->mem_chunk)
65 g_mem_chunk_destroy (allocator->mem_chunk);
66 allocator->mem_chunk = NULL;
70 if (!allocator->mem_chunk)
72 allocator->mem_chunk = g_mem_chunk_new (allocator->name,
73 sizeof (GSList),
74 sizeof (GSList) * allocator->n_preallocs,
75 G_ALLOC_ONLY);
76 allocator->free_lists = NULL;
79 allocator->is_unused = FALSE;
82 void
83 g_slist_push_allocator (GAllocator *allocator)
85 G_LOCK (current_allocator);
86 g_slist_validate_allocator (allocator);
87 allocator->last = current_allocator;
88 current_allocator = allocator;
89 G_UNLOCK (current_allocator);
92 void
93 g_slist_pop_allocator (void)
95 G_LOCK (current_allocator);
96 if (current_allocator)
98 GAllocator *allocator;
100 allocator = current_allocator;
101 current_allocator = allocator->last;
102 allocator->last = NULL;
103 allocator->is_unused = TRUE;
105 G_UNLOCK (current_allocator);
108 static inline GSList*
109 _g_slist_alloc (void)
111 GSList *list;
113 G_LOCK (current_allocator);
114 if (!current_allocator)
116 GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
117 128);
118 g_slist_validate_allocator (allocator);
119 allocator->last = NULL;
120 current_allocator = allocator;
122 if (!current_allocator->free_lists)
124 list = g_chunk_new (GSList, current_allocator->mem_chunk);
125 list->data = NULL;
127 else
129 if (current_allocator->free_lists->data)
131 list = current_allocator->free_lists->data;
132 current_allocator->free_lists->data = list->next;
133 list->data = NULL;
135 else
137 list = current_allocator->free_lists;
138 current_allocator->free_lists = list->next;
141 G_UNLOCK (current_allocator);
143 list->next = NULL;
145 return list;
148 GSList*
149 g_slist_alloc (void)
151 return _g_slist_alloc ();
154 void
155 g_slist_free (GSList *list)
157 if (list)
159 GSList *last_node = list;
161 #ifdef ENABLE_GC_FRIENDLY
162 while (last_node->next)
164 last_node->data = NULL;
165 last_node = last_node->next;
167 last_node->data = NULL;
168 #else /* !ENABLE_GC_FRIENDLY */
169 list->data = list->next;
170 #endif /* ENABLE_GC_FRIENDLY */
172 G_LOCK (current_allocator);
173 last_node->next = current_allocator->free_lists;
174 current_allocator->free_lists = list;
175 G_UNLOCK (current_allocator);
179 static inline void
180 _g_slist_free_1 (GSList *list)
182 if (list)
184 list->data = NULL;
185 G_LOCK (current_allocator);
186 list->next = current_allocator->free_lists;
187 current_allocator->free_lists = list;
188 G_UNLOCK (current_allocator);
192 void
193 g_slist_free_1 (GSList *list)
195 _g_slist_free_1 (list);
197 #else /* DISABLE_MEM_POOLS */
199 #define _g_slist_alloc g_slist_alloc
200 GSList*
201 g_slist_alloc (void)
203 GSList *list;
205 list = g_new0 (GSList, 1);
207 return list;
210 void
211 g_slist_free (GSList *list)
213 GSList *last;
215 while (list)
217 last = list;
218 list = list->next;
219 g_free (last);
223 #define _g_slist_free_1 g_slist_free_1
224 void
225 g_slist_free_1 (GSList *list)
227 g_free (list);
230 #endif
232 GSList*
233 g_slist_append (GSList *list,
234 gpointer data)
236 GSList *new_list;
237 GSList *last;
239 new_list = _g_slist_alloc ();
240 new_list->data = data;
242 if (list)
244 last = g_slist_last (list);
245 /* g_assert (last != NULL); */
246 last->next = new_list;
248 return list;
250 else
251 return new_list;
254 GSList*
255 g_slist_prepend (GSList *list,
256 gpointer data)
258 GSList *new_list;
260 new_list = _g_slist_alloc ();
261 new_list->data = data;
262 new_list->next = list;
264 return new_list;
267 GSList*
268 g_slist_insert (GSList *list,
269 gpointer data,
270 gint position)
272 GSList *prev_list;
273 GSList *tmp_list;
274 GSList *new_list;
276 if (position < 0)
277 return g_slist_append (list, data);
278 else if (position == 0)
279 return g_slist_prepend (list, data);
281 new_list = _g_slist_alloc ();
282 new_list->data = data;
284 if (!list)
285 return new_list;
287 prev_list = NULL;
288 tmp_list = list;
290 while ((position-- > 0) && tmp_list)
292 prev_list = tmp_list;
293 tmp_list = tmp_list->next;
296 if (prev_list)
298 new_list->next = prev_list->next;
299 prev_list->next = new_list;
301 else
303 new_list->next = list;
304 list = new_list;
307 return list;
310 GSList*
311 g_slist_insert_before (GSList *slist,
312 GSList *sibling,
313 gpointer data)
315 if (!slist)
317 slist = g_slist_alloc ();
318 slist->data = data;
319 g_return_val_if_fail (sibling == NULL, slist);
320 return slist;
322 else
324 GSList *node, *last = NULL;
326 for (node = slist; node; last = node, node = last->next)
327 if (node == sibling)
328 break;
329 if (!last)
331 node = g_slist_alloc ();
332 node->data = data;
333 node->next = slist;
335 return node;
337 else
339 node = g_slist_alloc ();
340 node->data = data;
341 node->next = last->next;
342 last->next = node;
344 return slist;
349 GSList *
350 g_slist_concat (GSList *list1, GSList *list2)
352 if (list2)
354 if (list1)
355 g_slist_last (list1)->next = list2;
356 else
357 list1 = list2;
360 return list1;
363 GSList*
364 g_slist_remove (GSList *list,
365 gconstpointer data)
367 GSList *tmp, *prev = NULL;
369 tmp = list;
370 while (tmp)
372 if (tmp->data == data)
374 if (prev)
375 prev->next = tmp->next;
376 else
377 list = tmp->next;
379 g_slist_free_1 (tmp);
380 break;
382 prev = tmp;
383 tmp = prev->next;
386 return list;
389 GSList*
390 g_slist_remove_all (GSList *list,
391 gconstpointer data)
393 GSList *tmp, *prev = NULL;
395 tmp = list;
396 while (tmp)
398 if (tmp->data == data)
400 GSList *next = tmp->next;
402 if (prev)
403 prev->next = next;
404 else
405 list = next;
407 g_slist_free_1 (tmp);
408 tmp = next;
410 else
412 prev = tmp;
413 tmp = prev->next;
417 return list;
420 static inline GSList*
421 _g_slist_remove_link (GSList *list,
422 GSList *link)
424 GSList *tmp;
425 GSList *prev;
427 prev = NULL;
428 tmp = list;
430 while (tmp)
432 if (tmp == link)
434 if (prev)
435 prev->next = tmp->next;
436 if (list == tmp)
437 list = list->next;
439 tmp->next = NULL;
440 break;
443 prev = tmp;
444 tmp = tmp->next;
447 return list;
450 GSList*
451 g_slist_remove_link (GSList *list,
452 GSList *link)
454 return _g_slist_remove_link (list, link);
457 GSList*
458 g_slist_delete_link (GSList *list,
459 GSList *link)
461 list = _g_slist_remove_link (list, link);
462 _g_slist_free_1 (link);
464 return list;
467 GSList*
468 g_slist_copy (GSList *list)
470 GSList *new_list = NULL;
472 if (list)
474 GSList *last;
476 new_list = _g_slist_alloc ();
477 new_list->data = list->data;
478 last = new_list;
479 list = list->next;
480 while (list)
482 last->next = _g_slist_alloc ();
483 last = last->next;
484 last->data = list->data;
485 list = list->next;
489 return new_list;
492 GSList*
493 g_slist_reverse (GSList *list)
495 GSList *prev = NULL;
497 while (list)
499 GSList *next = list->next;
501 list->next = prev;
503 prev = list;
504 list = next;
507 return prev;
510 GSList*
511 g_slist_nth (GSList *list,
512 guint n)
514 while (n-- > 0 && list)
515 list = list->next;
517 return list;
520 gpointer
521 g_slist_nth_data (GSList *list,
522 guint n)
524 while (n-- > 0 && list)
525 list = list->next;
527 return list ? list->data : NULL;
530 GSList*
531 g_slist_find (GSList *list,
532 gconstpointer data)
534 while (list)
536 if (list->data == data)
537 break;
538 list = list->next;
541 return list;
544 GSList*
545 g_slist_find_custom (GSList *list,
546 gconstpointer data,
547 GCompareFunc func)
549 g_return_val_if_fail (func != NULL, list);
551 while (list)
553 if (! func (list->data, data))
554 return list;
555 list = list->next;
558 return NULL;
561 gint
562 g_slist_position (GSList *list,
563 GSList *link)
565 gint i;
567 i = 0;
568 while (list)
570 if (list == link)
571 return i;
572 i++;
573 list = list->next;
576 return -1;
579 gint
580 g_slist_index (GSList *list,
581 gconstpointer data)
583 gint i;
585 i = 0;
586 while (list)
588 if (list->data == data)
589 return i;
590 i++;
591 list = list->next;
594 return -1;
597 GSList*
598 g_slist_last (GSList *list)
600 if (list)
602 while (list->next)
603 list = list->next;
606 return list;
609 guint
610 g_slist_length (GSList *list)
612 guint length;
614 length = 0;
615 while (list)
617 length++;
618 list = list->next;
621 return length;
624 void
625 g_slist_foreach (GSList *list,
626 GFunc func,
627 gpointer user_data)
629 while (list)
631 GSList *next = list->next;
632 (*func) (list->data, user_data);
633 list = next;
637 GSList*
638 g_slist_insert_sorted (GSList *list,
639 gpointer data,
640 GCompareFunc func)
642 GSList *tmp_list = list;
643 GSList *prev_list = NULL;
644 GSList *new_list;
645 gint cmp;
647 g_return_val_if_fail (func != NULL, list);
649 if (!list)
651 new_list = _g_slist_alloc ();
652 new_list->data = data;
653 return new_list;
656 cmp = (*func) (data, tmp_list->data);
658 while ((tmp_list->next) && (cmp > 0))
660 prev_list = tmp_list;
661 tmp_list = tmp_list->next;
662 cmp = (*func) (data, tmp_list->data);
665 new_list = _g_slist_alloc ();
666 new_list->data = data;
668 if ((!tmp_list->next) && (cmp > 0))
670 tmp_list->next = new_list;
671 return list;
674 if (prev_list)
676 prev_list->next = new_list;
677 new_list->next = tmp_list;
678 return list;
680 else
682 new_list->next = list;
683 return new_list;
687 static GSList *
688 g_slist_sort_merge (GSList *l1,
689 GSList *l2,
690 GFunc compare_func,
691 gboolean use_data,
692 gpointer user_data)
694 GSList list, *l;
695 gint cmp;
697 l=&list;
699 while (l1 && l2)
701 if (use_data)
702 cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
703 else
704 cmp = ((GCompareFunc) compare_func) (l1->data, l2->data);
706 if (cmp <= 0)
708 l=l->next=l1;
709 l1=l1->next;
711 else
713 l=l->next=l2;
714 l2=l2->next;
717 l->next= l1 ? l1 : l2;
719 return list.next;
722 static GSList *
723 g_slist_sort_real (GSList *list,
724 GFunc compare_func,
725 gboolean use_data,
726 gpointer user_data)
728 GSList *l1, *l2;
730 if (!list)
731 return NULL;
732 if (!list->next)
733 return list;
735 l1 = list;
736 l2 = list->next;
738 while ((l2 = l2->next) != NULL)
740 if ((l2 = l2->next) == NULL)
741 break;
742 l1=l1->next;
744 l2 = l1->next;
745 l1->next = NULL;
747 return g_slist_sort_merge (g_slist_sort_real (list, compare_func, use_data, user_data),
748 g_slist_sort_real (l2, compare_func, use_data, user_data),
749 compare_func,
750 use_data,
751 user_data);
754 GSList *
755 g_slist_sort (GSList *list,
756 GCompareFunc compare_func)
758 return g_slist_sort_real (list, (GFunc) compare_func, FALSE, NULL);
761 GSList *
762 g_slist_sort_with_data (GSList *list,
763 GCompareDataFunc compare_func,
764 gpointer user_data)
766 return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);