Coverage Report

Created: 2025-08-03 06:57

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