glib/: fully remove galias hacks
[platform/upstream/glib.git] / glib / gqueue.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GQueue: Double ended queue implementation, piggy backed on GList.
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * MT safe
25  */
26
27 #include "config.h"
28
29 #include "glib.h"
30
31 /**
32  * g_queue_new:
33  *
34  * Creates a new #GQueue. 
35  *
36  * Returns: a new #GQueue.
37  **/
38 GQueue*
39 g_queue_new (void)
40 {
41   return g_slice_new0 (GQueue);
42 }
43
44 /**
45  * g_queue_free:
46  * @queue: a #GQueue.
47  *
48  * Frees the memory allocated for the #GQueue. Only call this function if
49  * @queue was created with g_queue_new(). If queue elements contain
50  * dynamically-allocated memory, they should be freed first.
51  **/
52 void
53 g_queue_free (GQueue *queue)
54 {
55   g_return_if_fail (queue != NULL);
56
57   g_list_free (queue->head);
58   g_slice_free (GQueue, queue);
59 }
60
61 /**
62  * g_queue_init:
63  * @queue: an uninitialized #GQueue
64  *
65  * A statically-allocated #GQueue must be initialized with this function
66  * before it can be used. Alternatively you can initialize it with
67  * #G_QUEUE_INIT. It is not necessary to initialize queues created with
68  * g_queue_new().
69  *
70  * Since: 2.14
71  **/
72 void
73 g_queue_init (GQueue *queue)
74 {
75   g_return_if_fail (queue != NULL);
76
77   queue->head = queue->tail = NULL;
78   queue->length = 0;
79 }
80
81 /**
82  * g_queue_clear:
83  * @queue: a #GQueue
84  *
85  * Removes all the elements in @queue. If queue elements contain
86  * dynamically-allocated memory, they should be freed first.
87  *
88  * Since: 2.14
89  */
90 void
91 g_queue_clear (GQueue *queue)
92 {
93   g_return_if_fail (queue != NULL);
94
95   g_list_free (queue->head);
96   g_queue_init (queue);
97 }
98
99 /**
100  * g_queue_is_empty:
101  * @queue: a #GQueue.
102  *
103  * Returns %TRUE if the queue is empty.
104  *
105  * Returns: %TRUE if the queue is empty.
106  **/
107 gboolean
108 g_queue_is_empty (GQueue *queue)
109 {
110   g_return_val_if_fail (queue != NULL, TRUE);
111
112   return queue->head == NULL;
113 }
114
115 /**
116  * g_queue_get_length:
117  * @queue: a #GQueue
118  * 
119  * Returns the number of items in @queue.
120  * 
121  * Return value: The number of items in @queue.
122  * 
123  * Since: 2.4
124  **/
125 guint
126 g_queue_get_length (GQueue *queue)
127 {
128   g_return_val_if_fail (queue != NULL, 0);
129
130   return queue->length;
131 }
132
133 /**
134  * g_queue_reverse:
135  * @queue: a #GQueue
136  * 
137  * Reverses the order of the items in @queue.
138  * 
139  * Since: 2.4
140  **/
141 void
142 g_queue_reverse (GQueue *queue)
143 {
144   g_return_if_fail (queue != NULL);
145
146   queue->tail = queue->head;
147   queue->head = g_list_reverse (queue->head);
148 }
149
150 /**
151  * g_queue_copy:
152  * @queue: a #GQueue
153  * 
154  * Copies a @queue. Note that is a shallow copy. If the elements in the
155  * queue consist of pointers to data, the pointers are copied, but the
156  * actual data is not.
157  * 
158  * Return value: A copy of @queue
159  * 
160  * Since: 2.4
161  **/
162 GQueue *
163 g_queue_copy (GQueue *queue)
164 {
165   GQueue *result;
166   GList *list;
167
168   g_return_val_if_fail (queue != NULL, NULL);
169
170   result = g_queue_new ();
171
172   for (list = queue->head; list != NULL; list = list->next)
173     g_queue_push_tail (result, list->data);
174
175   return result;
176 }
177
178 /**
179  * g_queue_foreach:
180  * @queue: a #GQueue
181  * @func: the function to call for each element's data
182  * @user_data: user data to pass to @func
183  * 
184  * Calls @func for each element in the queue passing @user_data to the
185  * function.
186  * 
187  * Since: 2.4
188  **/
189 void
190 g_queue_foreach (GQueue   *queue,
191                  GFunc     func,
192                  gpointer  user_data)
193 {
194   GList *list;
195
196   g_return_if_fail (queue != NULL);
197   g_return_if_fail (func != NULL);
198   
199   list = queue->head;
200   while (list)
201     {
202       GList *next = list->next;
203       func (list->data, user_data);
204       list = next;
205     }
206 }
207
208 /**
209  * g_queue_find:
210  * @queue: a #GQueue
211  * @data: data to find
212  * 
213  * Finds the first link in @queue which contains @data.
214  * 
215  * Return value: The first link in @queue which contains @data.
216  * 
217  * Since: 2.4
218  **/
219 GList *
220 g_queue_find (GQueue        *queue,
221               gconstpointer  data)
222 {
223   g_return_val_if_fail (queue != NULL, NULL);
224
225   return g_list_find (queue->head, data);
226 }
227
228 /**
229  * g_queue_find_custom:
230  * @queue: a #GQueue
231  * @data: user data passed to @func
232  * @func: a #GCompareFunc to call for each element. It should return 0
233  * when the desired element is found
234  *
235  * Finds an element in a #GQueue, using a supplied function to find the
236  * desired element. It iterates over the queue, calling the given function
237  * which should return 0 when the desired element is found. The function
238  * takes two gconstpointer arguments, the #GQueue element's data as the
239  * first argument and the given user data as the second argument.
240  * 
241  * Return value: The found link, or %NULL if it wasn't found
242  * 
243  * Since: 2.4
244  **/
245 GList *
246 g_queue_find_custom    (GQueue        *queue,
247                         gconstpointer  data,
248                         GCompareFunc   func)
249 {
250   g_return_val_if_fail (queue != NULL, NULL);
251   g_return_val_if_fail (func != NULL, NULL);
252
253   return g_list_find_custom (queue->head, data, func);
254 }
255
256 /**
257  * g_queue_sort:
258  * @queue: a #GQueue
259  * @compare_func: the #GCompareDataFunc used to sort @queue. This function
260  *     is passed two elements of the queue and should return 0 if they are
261  *     equal, a negative value if the first comes before the second, and
262  *     a positive value if the second comes before the first.
263  * @user_data: user data passed to @compare_func
264  * 
265  * Sorts @queue using @compare_func. 
266  * 
267  * Since: 2.4
268  **/
269 void
270 g_queue_sort (GQueue           *queue,
271               GCompareDataFunc  compare_func,
272               gpointer          user_data)
273 {
274   g_return_if_fail (queue != NULL);
275   g_return_if_fail (compare_func != NULL);
276
277   queue->head = g_list_sort_with_data (queue->head, compare_func, user_data);
278   queue->tail = g_list_last (queue->head);
279 }
280
281 /**
282  * g_queue_push_head:
283  * @queue: a #GQueue.
284  * @data: the data for the new element.
285  *
286  * Adds a new element at the head of the queue.
287  **/
288 void
289 g_queue_push_head (GQueue  *queue,
290                    gpointer data)
291 {
292   g_return_if_fail (queue != NULL);
293
294   queue->head = g_list_prepend (queue->head, data);
295   if (!queue->tail)
296     queue->tail = queue->head;
297   queue->length++;
298 }
299
300 /**
301  * g_queue_push_nth:
302  * @queue: a #GQueue
303  * @data: the data for the new element
304  * @n: the position to insert the new element. If @n is negative or
305  *     larger than the number of elements in the @queue, the element is
306  *     added to the end of the queue.
307  * 
308  * Inserts a new element into @queue at the given position
309  * 
310  * Since: 2.4
311  **/
312 void
313 g_queue_push_nth (GQueue   *queue,
314                   gpointer  data,
315                   gint      n)
316 {
317   g_return_if_fail (queue != NULL);
318
319   if (n < 0 || n >= queue->length)
320     {
321       g_queue_push_tail (queue, data);
322       return;
323     }
324
325   g_queue_insert_before (queue, g_queue_peek_nth_link (queue, n), data);
326 }
327
328 /**
329  * g_queue_push_head_link:
330  * @queue: a #GQueue.
331  * @link_: a single #GList element, <emphasis>not</emphasis> a list with
332  *     more than one element.
333  *
334  * Adds a new element at the head of the queue.
335  **/
336 void
337 g_queue_push_head_link (GQueue *queue,
338                         GList  *link)
339 {
340   g_return_if_fail (queue != NULL);
341   g_return_if_fail (link != NULL);
342   g_return_if_fail (link->prev == NULL);
343   g_return_if_fail (link->next == NULL);
344
345   link->next = queue->head;
346   if (queue->head)
347     queue->head->prev = link;
348   else
349     queue->tail = link;
350   queue->head = link;
351   queue->length++;
352 }
353
354 /**
355  * g_queue_push_tail:
356  * @queue: a #GQueue.
357  * @data: the data for the new element.
358  *
359  * Adds a new element at the tail of the queue.
360  **/
361 void
362 g_queue_push_tail (GQueue  *queue,
363                    gpointer data)
364 {
365   g_return_if_fail (queue != NULL);
366
367   queue->tail = g_list_append (queue->tail, data);
368   if (queue->tail->next)
369     queue->tail = queue->tail->next;
370   else
371     queue->head = queue->tail;
372   queue->length++;
373 }
374
375 /**
376  * g_queue_push_tail_link:
377  * @queue: a #GQueue.
378  * @link_: a single #GList element, <emphasis>not</emphasis> a list with
379  *   more than one element.
380  *
381  * Adds a new element at the tail of the queue.
382  **/
383 void
384 g_queue_push_tail_link (GQueue *queue,
385                         GList  *link)
386 {
387   g_return_if_fail (queue != NULL);
388   g_return_if_fail (link != NULL);
389   g_return_if_fail (link->prev == NULL);
390   g_return_if_fail (link->next == NULL);
391
392   link->prev = queue->tail;
393   if (queue->tail)
394     queue->tail->next = link;
395   else
396     queue->head = link;
397   queue->tail = link;
398   queue->length++;
399 }
400
401 /**
402  * g_queue_push_nth_link:
403  * @queue: a #GQueue
404  * @n: the position to insert the link. If this is negative or larger than
405  *     the number of elements in @queue, the link is added to the end of
406  *     @queue.
407  * @link_: the link to add to @queue
408  * 
409  * Inserts @link into @queue at the given position.
410  * 
411  * Since: 2.4
412  **/
413 void
414 g_queue_push_nth_link  (GQueue  *queue,
415                         gint     n,
416                         GList   *link_)
417 {
418   GList *next;
419   GList *prev;
420   
421   g_return_if_fail (queue != NULL);
422   g_return_if_fail (link_ != NULL);
423
424   if (n < 0 || n >= queue->length)
425     {
426       g_queue_push_tail_link (queue, link_);
427       return;
428     }
429
430   g_assert (queue->head);
431   g_assert (queue->tail);
432
433   next = g_queue_peek_nth_link (queue, n);
434   prev = next->prev;
435
436   if (prev)
437     prev->next = link_;
438   next->prev = link_;
439
440   link_->next = next;
441   link_->prev = prev;
442
443   if (queue->head->prev)
444     queue->head = queue->head->prev;
445
446   if (queue->tail->next)
447     queue->tail = queue->tail->next;
448   
449   queue->length++;
450 }
451
452 /**
453  * g_queue_pop_head:
454  * @queue: a #GQueue.
455  *
456  * Removes the first element of the queue.
457  *
458  * Returns: the data of the first element in the queue, or %NULL if the queue
459  *   is empty.
460  **/
461 gpointer
462 g_queue_pop_head (GQueue *queue)
463 {
464   g_return_val_if_fail (queue != NULL, NULL);
465
466   if (queue->head)
467     {
468       GList *node = queue->head;
469       gpointer data = node->data;
470
471       queue->head = node->next;
472       if (queue->head)
473         queue->head->prev = NULL;
474       else
475         queue->tail = NULL;
476       g_list_free_1 (node);
477       queue->length--;
478
479       return data;
480     }
481
482   return NULL;
483 }
484
485 /**
486  * g_queue_pop_head_link:
487  * @queue: a #GQueue.
488  *
489  * Removes the first element of the queue.
490  *
491  * Returns: the #GList element at the head of the queue, or %NULL if the queue
492  *   is empty.
493  **/
494 GList*
495 g_queue_pop_head_link (GQueue *queue)
496 {
497   g_return_val_if_fail (queue != NULL, NULL);
498
499   if (queue->head)
500     {
501       GList *node = queue->head;
502
503       queue->head = node->next;
504       if (queue->head)
505         {
506           queue->head->prev = NULL;
507           node->next = NULL;
508         }
509       else
510         queue->tail = NULL;
511       queue->length--;
512
513       return node;
514     }
515
516   return NULL;
517 }
518
519 /**
520  * g_queue_peek_head_link:
521  * @queue: a #GQueue
522  * 
523  * Returns the first link in @queue
524  * 
525  * Return value: the first link in @queue, or %NULL if @queue is empty
526  * 
527  * Since: 2.4
528  **/
529 GList*
530 g_queue_peek_head_link (GQueue *queue)
531 {
532   g_return_val_if_fail (queue != NULL, NULL);
533
534   return queue->head;
535 }
536
537 /**
538  * g_queue_peek_tail_link:
539  * @queue: a #GQueue
540  * 
541  * Returns the last link @queue.
542  * 
543  * Return value: the last link in @queue, or %NULL if @queue is empty
544  * 
545  * Since: 2.4
546  **/
547 GList*
548 g_queue_peek_tail_link (GQueue *queue)
549 {
550   g_return_val_if_fail (queue != NULL, NULL);
551
552   return queue->tail;
553 }
554
555 /**
556  * g_queue_pop_tail:
557  * @queue: a #GQueue.
558  *
559  * Removes the last element of the queue.
560  *
561  * Returns: the data of the last element in the queue, or %NULL if the queue
562  *   is empty.
563  **/
564 gpointer
565 g_queue_pop_tail (GQueue *queue)
566 {
567   g_return_val_if_fail (queue != NULL, NULL);
568
569   if (queue->tail)
570     {
571       GList *node = queue->tail;
572       gpointer data = node->data;
573
574       queue->tail = node->prev;
575       if (queue->tail)
576         queue->tail->next = NULL;
577       else
578         queue->head = NULL;
579       queue->length--;
580       g_list_free_1 (node);
581
582       return data;
583     }
584   
585   return NULL;
586 }
587
588 /**
589  * g_queue_pop_nth:
590  * @queue: a #GQueue
591  * @n: the position of the element.
592  * 
593  * Removes the @n'th element of @queue.
594  * 
595  * Return value: the element's data, or %NULL if @n is off the end of @queue.
596  * 
597  * Since: 2.4
598  **/
599 gpointer
600 g_queue_pop_nth (GQueue *queue,
601                  guint   n)
602 {
603   GList *nth_link;
604   gpointer result;
605   
606   g_return_val_if_fail (queue != NULL, NULL);
607
608   if (n >= queue->length)
609     return NULL;
610   
611   nth_link = g_queue_peek_nth_link (queue, n);
612   result = nth_link->data;
613
614   g_queue_delete_link (queue, nth_link);
615
616   return result;
617 }
618
619 /**
620  * g_queue_pop_tail_link:
621  * @queue: a #GQueue.
622  *
623  * Removes the last element of the queue.
624  *
625  * Returns: the #GList element at the tail of the queue, or %NULL if the queue
626  *   is empty.
627  **/
628 GList*
629 g_queue_pop_tail_link (GQueue *queue)
630 {
631   g_return_val_if_fail (queue != NULL, NULL);
632   
633   if (queue->tail)
634     {
635       GList *node = queue->tail;
636       
637       queue->tail = node->prev;
638       if (queue->tail)
639         {
640           queue->tail->next = NULL;
641           node->prev = NULL;
642         }
643       else
644         queue->head = NULL;
645       queue->length--;
646       
647       return node;
648     }
649   
650   return NULL;
651 }
652
653 /**
654  * g_queue_pop_nth_link:
655  * @queue: a #GQueue
656  * @n: the link's position
657  * 
658  * Removes and returns the link at the given position.
659  * 
660  * Return value: The @n'th link, or %NULL if @n is off the end of @queue.
661  * 
662  * Since: 2.4
663  **/
664 GList*
665 g_queue_pop_nth_link (GQueue *queue,
666                       guint   n)
667 {
668   GList *link;
669   
670   g_return_val_if_fail (queue != NULL, NULL);
671
672   if (n >= queue->length)
673     return NULL;
674   
675   link = g_queue_peek_nth_link (queue, n);
676   g_queue_unlink (queue, link);
677
678   return link;
679 }
680
681 /**
682  * g_queue_peek_nth_link:
683  * @queue: a #GQueue
684  * @n: the position of the link
685  * 
686  * Returns the link at the given position
687  * 
688  * Return value: The link at the @n'th position, or %NULL if @n is off the
689  * end of the list
690  * 
691  * Since: 2.4
692  **/
693 GList *
694 g_queue_peek_nth_link (GQueue *queue,
695                        guint   n)
696 {
697   GList *link;
698   gint i;
699   
700   g_return_val_if_fail (queue != NULL, NULL);
701
702   if (n >= queue->length)
703     return NULL;
704   
705   if (n > queue->length / 2)
706     {
707       n = queue->length - n - 1;
708
709       link = queue->tail;
710       for (i = 0; i < n; ++i)
711         link = link->prev;
712     }
713   else
714     {
715       link = queue->head;
716       for (i = 0; i < n; ++i)
717         link = link->next;
718     }
719
720   return link;
721 }
722
723 /**
724  * g_queue_link_index:
725  * @queue: a #Gqueue
726  * @link_: A #GList link
727  * 
728  * Returns the position of @link_ in @queue.
729  * 
730  * Return value: The position of @link_, or -1 if the link is
731  * not part of @queue
732  * 
733  * Since: 2.4
734  **/
735 gint
736 g_queue_link_index (GQueue *queue,
737                     GList  *link_)
738 {
739   g_return_val_if_fail (queue != NULL, -1);
740
741   return g_list_position (queue->head, link_);
742 }
743
744 /**
745  * g_queue_unlink
746  * @queue: a #GQueue
747  * @link_: a #GList link that <emphasis>must</emphasis> be part of @queue
748  *
749  * Unlinks @link_ so that it will no longer be part of @queue. The link is
750  * not freed.
751  *
752  * @link_ must be part of @queue,
753  * 
754  * Since: 2.4
755  **/
756 void
757 g_queue_unlink (GQueue *queue,
758                 GList  *link_)
759 {
760   g_return_if_fail (queue != NULL);
761   g_return_if_fail (link_ != NULL);
762
763   if (link_ == queue->tail)
764     queue->tail = queue->tail->prev;
765   
766   queue->head = g_list_remove_link (queue->head, link_);
767   queue->length--;
768 }
769
770 /**
771  * g_queue_delete_link:
772  * @queue: a #GQueue
773  * @link_: a #GList link that <emphasis>must</emphasis> be part of @queue
774  *
775  * Removes @link_ from @queue and frees it.
776  *
777  * @link_ must be part of @queue.
778  * 
779  * Since: 2.4
780  **/
781 void
782 g_queue_delete_link (GQueue *queue,
783                      GList  *link_)
784 {
785   g_return_if_fail (queue != NULL);
786   g_return_if_fail (link_ != NULL);
787
788   g_queue_unlink (queue, link_);
789   g_list_free (link_);
790 }
791
792 /**
793  * g_queue_peek_head:
794  * @queue: a #GQueue.
795  *
796  * Returns the first element of the queue.
797  *
798  * Returns: the data of the first element in the queue, or %NULL if the queue
799  *   is empty.
800  **/
801 gpointer
802 g_queue_peek_head (GQueue *queue)
803 {
804   g_return_val_if_fail (queue != NULL, NULL);
805
806   return queue->head ? queue->head->data : NULL;
807 }
808
809 /**
810  * g_queue_peek_tail:
811  * @queue: a #GQueue.
812  *
813  * Returns the last element of the queue.
814  *
815  * Returns: the data of the last element in the queue, or %NULL if the queue
816  *   is empty.
817  **/
818 gpointer
819 g_queue_peek_tail (GQueue *queue)
820 {
821   g_return_val_if_fail (queue != NULL, NULL);
822
823   return queue->tail ? queue->tail->data : NULL;
824 }
825
826 /**
827  * g_queue_peek_nth:
828  * @queue: a #GQueue
829  * @n: the position of the element.
830  * 
831  * Returns the @n'th element of @queue. 
832  * 
833  * Return value: The data for the @n'th element of @queue, or %NULL if @n is
834  *   off the end of @queue.
835  * 
836  * Since: 2.4
837  **/
838 gpointer
839 g_queue_peek_nth (GQueue *queue,
840                   guint   n)
841 {
842   GList *link;
843   
844   g_return_val_if_fail (queue != NULL, NULL);
845
846   link = g_queue_peek_nth_link (queue, n);
847
848   if (link)
849     return link->data;
850
851   return NULL;
852 }
853
854 /**
855  * g_queue_index:
856  * @queue: a #GQueue
857  * @data: the data to find.
858  * 
859  * Returns the position of the first element in @queue which contains @data.
860  * 
861  * Return value: The position of the first element in @queue which contains @data, or -1 if no element in @queue contains @data.
862  * 
863  * Since: 2.4
864  **/
865 gint
866 g_queue_index (GQueue        *queue,
867                gconstpointer  data)
868 {
869   g_return_val_if_fail (queue != NULL, -1);
870
871   return g_list_index (queue->head, data);
872 }
873
874 /**
875  * g_queue_remove:
876  * @queue: a #GQueue
877  * @data: data to remove.
878  * 
879  * Removes the first element in @queue that contains @data. 
880  * 
881  * Since: 2.4
882  **/
883 void
884 g_queue_remove (GQueue        *queue,
885                 gconstpointer  data)
886 {
887   GList *link;
888   
889   g_return_if_fail (queue != NULL);
890
891   link = g_list_find (queue->head, data);
892
893   if (link)
894     g_queue_delete_link (queue, link);
895 }
896
897 /**
898  * g_queue_remove_all:
899  * @queue: a #GQueue
900  * @data: data to remove
901  * 
902  * Remove all elemeents in @queue which contains @data.
903  * 
904  * Since: 2.4
905  **/
906 void
907 g_queue_remove_all (GQueue        *queue,
908                     gconstpointer  data)
909 {
910   GList *list;
911   
912   g_return_if_fail (queue != NULL);
913
914   list = queue->head;
915   while (list)
916     {
917       GList *next = list->next;
918
919       if (list->data == data)
920         g_queue_delete_link (queue, list);
921       
922       list = next;
923     }
924 }
925
926 /**
927  * g_queue_insert_before:
928  * @queue: a #GQueue
929  * @sibling: a #GList link that <emphasis>must</emphasis> be part of @queue
930  * @data: the data to insert
931  * 
932  * Inserts @data into @queue before @sibling.
933  *
934  * @sibling must be part of @queue.
935  * 
936  * Since: 2.4
937  **/
938 void
939 g_queue_insert_before (GQueue   *queue,
940                        GList    *sibling,
941                        gpointer  data)
942 {
943   g_return_if_fail (queue != NULL);
944   g_return_if_fail (sibling != NULL);
945
946   queue->head = g_list_insert_before (queue->head, sibling, data);
947   queue->length++;
948 }
949
950 /**
951  * g_queue_insert_after:
952  * @queue: a #GQueue
953  * @sibling: a #GList link that <emphasis>must</emphasis> be part of @queue
954  * @data: the data to insert
955  *
956  * Inserts @data into @queue after @sibling
957  *
958  * @sibling must be part of @queue
959  * 
960  * Since: 2.4
961  **/
962 void
963 g_queue_insert_after (GQueue   *queue,
964                       GList    *sibling,
965                       gpointer  data)
966 {
967   g_return_if_fail (queue != NULL);
968   g_return_if_fail (sibling != NULL);
969
970   if (sibling == queue->tail)
971     g_queue_push_tail (queue, data);
972   else
973     g_queue_insert_before (queue, sibling->next, data);
974 }
975
976 /**
977  * g_queue_insert_sorted:
978  * @queue: a #GQueue
979  * @data: the data to insert
980  * @func: the #GCompareDataFunc used to compare elements in the queue. It is
981  *     called with two elements of the @queue and @user_data. It should
982  *     return 0 if the elements are equal, a negative value if the first
983  *     element comes before the second, and a positive value if the second
984  *     element comes before the first.
985  * @user_data: user data passed to @func.
986  * 
987  * Inserts @data into @queue using @func to determine the new position.
988  * 
989  * Since: 2.4
990  **/
991 void
992 g_queue_insert_sorted (GQueue           *queue,
993                        gpointer          data,
994                        GCompareDataFunc  func,
995                        gpointer          user_data)
996 {
997   GList *list;
998   
999   g_return_if_fail (queue != NULL);
1000
1001   list = queue->head;
1002   while (list && func (list->data, data, user_data) < 0)
1003     list = list->next;
1004
1005   if (list)
1006     g_queue_insert_before (queue, list, data);
1007   else
1008     g_queue_push_tail (queue, data);
1009 }