Add a note about casting the results of g_new() and g_new0().
[platform/upstream/glib.git] / glib / glist.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
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 "glib.h"
34 #include "galias.h"
35
36
37 void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ }
38 void g_list_pop_allocator  (void)           { /* present for binary compat only */ }
39
40 #define _g_list_alloc0()        g_slice_new0 (GList)
41 #define _g_list_free1(list)     g_slice_free (GList, list)
42
43 GList*
44 g_list_alloc (void)
45 {
46   return _g_list_alloc0 ();
47 }
48
49 void
50 g_list_free (GList *list)
51 {
52   g_slice_free_chain (GList, list, next);
53 }
54
55 void
56 g_list_free_1 (GList *list)
57 {
58   _g_list_free1 (list);
59 }
60
61 GList*
62 g_list_append (GList    *list,
63                gpointer  data)
64 {
65   GList *new_list;
66   GList *last;
67   
68   new_list = _g_list_alloc0 ();
69   new_list->data = data;
70   
71   if (list)
72     {
73       last = g_list_last (list);
74       /* g_assert (last != NULL); */
75       last->next = new_list;
76       new_list->prev = last;
77
78       return list;
79     }
80   else
81     return new_list;
82 }
83
84 GList*
85 g_list_prepend (GList    *list,
86                 gpointer  data)
87 {
88   GList *new_list;
89   
90   new_list = _g_list_alloc0 ();
91   new_list->data = data;
92   
93   if (list)
94     {
95       if (list->prev)
96         {
97           list->prev->next = new_list;
98           new_list->prev = list->prev;
99         }
100       list->prev = new_list;
101       new_list->next = list;
102     }
103   
104   return new_list;
105 }
106
107 GList*
108 g_list_insert (GList    *list,
109                gpointer  data,
110                gint      position)
111 {
112   GList *new_list;
113   GList *tmp_list;
114   
115   if (position < 0)
116     return g_list_append (list, data);
117   else if (position == 0)
118     return g_list_prepend (list, data);
119   
120   tmp_list = g_list_nth (list, position);
121   if (!tmp_list)
122     return g_list_append (list, data);
123   
124   new_list = _g_list_alloc0 ();
125   new_list->data = data;
126   
127   if (tmp_list->prev)
128     {
129       tmp_list->prev->next = new_list;
130       new_list->prev = tmp_list->prev;
131     }
132   new_list->next = tmp_list;
133   tmp_list->prev = new_list;
134   
135   if (tmp_list == list)
136     return new_list;
137   else
138     return list;
139 }
140
141 GList*
142 g_list_insert_before (GList   *list,
143                       GList   *sibling,
144                       gpointer data)
145 {
146   if (!list)
147     {
148       list = g_list_alloc ();
149       list->data = data;
150       g_return_val_if_fail (sibling == NULL, list);
151       return list;
152     }
153   else if (sibling)
154     {
155       GList *node;
156
157       node = g_list_alloc ();
158       node->data = data;
159       if (sibling->prev)
160         {
161           node->prev = sibling->prev;
162           node->prev->next = node;
163           node->next = sibling;
164           sibling->prev = node;
165           return list;
166         }
167       else
168         {
169           node->next = sibling;
170           sibling->prev = node;
171           g_return_val_if_fail (sibling == list, node);
172           return node;
173         }
174     }
175   else
176     {
177       GList *last;
178
179       last = list;
180       while (last->next)
181         last = last->next;
182
183       last->next = g_list_alloc ();
184       last->next->data = data;
185       last->next->prev = last;
186
187       return list;
188     }
189 }
190
191 GList *
192 g_list_concat (GList *list1, GList *list2)
193 {
194   GList *tmp_list;
195   
196   if (list2)
197     {
198       tmp_list = g_list_last (list1);
199       if (tmp_list)
200         tmp_list->next = list2;
201       else
202         list1 = list2;
203       list2->prev = tmp_list;
204     }
205   
206   return list1;
207 }
208
209 GList*
210 g_list_remove (GList         *list,
211                gconstpointer  data)
212 {
213   GList *tmp;
214   
215   tmp = list;
216   while (tmp)
217     {
218       if (tmp->data != data)
219         tmp = tmp->next;
220       else
221         {
222           if (tmp->prev)
223             tmp->prev->next = tmp->next;
224           if (tmp->next)
225             tmp->next->prev = tmp->prev;
226           
227           if (list == tmp)
228             list = list->next;
229           
230           _g_list_free1 (tmp);
231           
232           break;
233         }
234     }
235   return list;
236 }
237
238 GList*
239 g_list_remove_all (GList        *list,
240                    gconstpointer data)
241 {
242   GList *tmp = list;
243
244   while (tmp)
245     {
246       if (tmp->data != data)
247         tmp = tmp->next;
248       else
249         {
250           GList *next = tmp->next;
251
252           if (tmp->prev)
253             tmp->prev->next = next;
254           else
255             list = next;
256           if (next)
257             next->prev = tmp->prev;
258
259           _g_list_free1 (tmp);
260           tmp = next;
261         }
262     }
263   return list;
264 }
265
266 static inline GList*
267 _g_list_remove_link (GList *list,
268                      GList *link)
269 {
270   if (link)
271     {
272       if (link->prev)
273         link->prev->next = link->next;
274       if (link->next)
275         link->next->prev = link->prev;
276       
277       if (link == list)
278         list = list->next;
279       
280       link->next = NULL;
281       link->prev = NULL;
282     }
283   
284   return list;
285 }
286
287 GList*
288 g_list_remove_link (GList *list,
289                     GList *link)
290 {
291   return _g_list_remove_link (list, link);
292 }
293
294 GList*
295 g_list_delete_link (GList *list,
296                     GList *link)
297 {
298   list = _g_list_remove_link (list, link);
299   _g_list_free1 (link);
300
301   return list;
302 }
303
304 GList*
305 g_list_copy (GList *list)
306 {
307   GList *new_list = NULL;
308
309   if (list)
310     {
311       GList *last;
312
313       new_list = _g_list_alloc0 ();
314       new_list->data = list->data;
315       last = new_list;
316       list = list->next;
317       while (list)
318         {
319           last->next = _g_list_alloc0 ();
320           last->next->prev = last;
321           last = last->next;
322           last->data = list->data;
323           list = list->next;
324         }
325     }
326
327   return new_list;
328 }
329
330 GList*
331 g_list_reverse (GList *list)
332 {
333   GList *last;
334   
335   last = NULL;
336   while (list)
337     {
338       last = list;
339       list = last->next;
340       last->next = last->prev;
341       last->prev = list;
342     }
343   
344   return last;
345 }
346
347 GList*
348 g_list_nth (GList *list,
349             guint  n)
350 {
351   while ((n-- > 0) && list)
352     list = list->next;
353   
354   return list;
355 }
356
357 GList*
358 g_list_nth_prev (GList *list,
359                  guint  n)
360 {
361   while ((n-- > 0) && list)
362     list = list->prev;
363   
364   return list;
365 }
366
367 gpointer
368 g_list_nth_data (GList     *list,
369                  guint      n)
370 {
371   while ((n-- > 0) && list)
372     list = list->next;
373   
374   return list ? list->data : NULL;
375 }
376
377 GList*
378 g_list_find (GList         *list,
379              gconstpointer  data)
380 {
381   while (list)
382     {
383       if (list->data == data)
384         break;
385       list = list->next;
386     }
387   
388   return list;
389 }
390
391 GList*
392 g_list_find_custom (GList         *list,
393                     gconstpointer  data,
394                     GCompareFunc   func)
395 {
396   g_return_val_if_fail (func != NULL, list);
397
398   while (list)
399     {
400       if (! func (list->data, data))
401         return list;
402       list = list->next;
403     }
404
405   return NULL;
406 }
407
408
409 gint
410 g_list_position (GList *list,
411                  GList *link)
412 {
413   gint i;
414
415   i = 0;
416   while (list)
417     {
418       if (list == link)
419         return i;
420       i++;
421       list = list->next;
422     }
423
424   return -1;
425 }
426
427 gint
428 g_list_index (GList         *list,
429               gconstpointer  data)
430 {
431   gint i;
432
433   i = 0;
434   while (list)
435     {
436       if (list->data == data)
437         return i;
438       i++;
439       list = list->next;
440     }
441
442   return -1;
443 }
444
445 GList*
446 g_list_last (GList *list)
447 {
448   if (list)
449     {
450       while (list->next)
451         list = list->next;
452     }
453   
454   return list;
455 }
456
457 GList*
458 g_list_first (GList *list)
459 {
460   if (list)
461     {
462       while (list->prev)
463         list = list->prev;
464     }
465   
466   return list;
467 }
468
469 guint
470 g_list_length (GList *list)
471 {
472   guint length;
473   
474   length = 0;
475   while (list)
476     {
477       length++;
478       list = list->next;
479     }
480   
481   return length;
482 }
483
484 void
485 g_list_foreach (GList    *list,
486                 GFunc     func,
487                 gpointer  user_data)
488 {
489   while (list)
490     {
491       GList *next = list->next;
492       (*func) (list->data, user_data);
493       list = next;
494     }
495 }
496
497 static GList*
498 g_list_insert_sorted_real (GList    *list,
499                            gpointer  data,
500                            GFunc     func,
501                            gpointer  user_data)
502 {
503   GList *tmp_list = list;
504   GList *new_list;
505   gint cmp;
506
507   g_return_val_if_fail (func != NULL, list);
508   
509   if (!list) 
510     {
511       new_list = _g_list_alloc0 ();
512       new_list->data = data;
513       return new_list;
514     }
515   
516   cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
517
518   while ((tmp_list->next) && (cmp > 0))
519     {
520       tmp_list = tmp_list->next;
521
522       cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
523     }
524
525   new_list = _g_list_alloc0 ();
526   new_list->data = data;
527
528   if ((!tmp_list->next) && (cmp > 0))
529     {
530       tmp_list->next = new_list;
531       new_list->prev = tmp_list;
532       return list;
533     }
534    
535   if (tmp_list->prev)
536     {
537       tmp_list->prev->next = new_list;
538       new_list->prev = tmp_list->prev;
539     }
540   new_list->next = tmp_list;
541   tmp_list->prev = new_list;
542  
543   if (tmp_list == list)
544     return new_list;
545   else
546     return list;
547 }
548
549 GList*
550 g_list_insert_sorted (GList        *list,
551                       gpointer      data,
552                       GCompareFunc  func)
553 {
554   return g_list_insert_sorted_real (list, data, (GFunc) func, NULL);
555 }
556
557 GList*
558 g_list_insert_sorted_with_data (GList            *list,
559                                 gpointer          data,
560                                 GCompareDataFunc  func,
561                                 gpointer          user_data)
562 {
563   return g_list_insert_sorted_real (list, data, (GFunc) func, user_data);
564 }
565
566 static GList *
567 g_list_sort_merge (GList     *l1, 
568                    GList     *l2,
569                    GFunc     compare_func,
570                    gpointer  user_data)
571 {
572   GList list, *l, *lprev;
573   gint cmp;
574
575   l = &list; 
576   lprev = NULL;
577
578   while (l1 && l2)
579     {
580       cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
581
582       if (cmp <= 0)
583         {
584           l->next = l1;
585           l1 = l1->next;
586         } 
587       else 
588         {
589           l->next = l2;
590           l2 = l2->next;
591         }
592       l = l->next;
593       l->prev = lprev; 
594       lprev = l;
595     }
596   l->next = l1 ? l1 : l2;
597   l->next->prev = l;
598
599   return list.next;
600 }
601
602 static GList* 
603 g_list_sort_real (GList    *list,
604                   GFunc     compare_func,
605                   gpointer  user_data)
606 {
607   GList *l1, *l2;
608   
609   if (!list) 
610     return NULL;
611   if (!list->next) 
612     return list;
613   
614   l1 = list; 
615   l2 = list->next;
616
617   while ((l2 = l2->next) != NULL)
618     {
619       if ((l2 = l2->next) == NULL) 
620         break;
621       l1 = l1->next;
622     }
623   l2 = l1->next; 
624   l1->next = NULL; 
625
626   return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data),
627                             g_list_sort_real (l2, compare_func, user_data),
628                             compare_func,
629                             user_data);
630 }
631
632 GList *
633 g_list_sort (GList        *list,
634              GCompareFunc  compare_func)
635 {
636   return g_list_sort_real (list, (GFunc) compare_func, NULL);
637                             
638 }
639
640 GList *
641 g_list_sort_with_data (GList            *list,
642                        GCompareDataFunc  compare_func,
643                        gpointer          user_data)
644 {
645   return g_list_sort_real (list, (GFunc) compare_func, user_data);
646 }
647
648 #define __G_LIST_C__
649 #include "galiasdef.c"