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