1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GQueue: Double ended queue implementation, piggy backed on GList.
5 * Copyright (C) 1998 Tim Janik
7 * SPDX-License-Identifier: LGPL-2.1-or-later
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 * @Title: Double-ended Queues
30 * @Short_description: double-ended queue data structure
32 * The #GQueue structure and its associated functions provide a standard
33 * queue data structure. Internally, GQueue uses the same data structure
34 * as #GList to store elements with the same complexity over
35 * insertion/deletion (O(1)) and access/search (O(n)) operations.
37 * The data contained in each element can be either integer values, by
38 * using one of the [Type Conversion Macros][glib-Type-Conversion-Macros],
39 * or simply pointers to any type of data.
41 * As with all other GLib data structures, #GQueue is not thread-safe.
42 * For a thread-safe queue, use #GAsyncQueue.
44 * To create a new GQueue, use g_queue_new().
46 * To initialize a statically-allocated GQueue, use %G_QUEUE_INIT or
49 * To add elements, use g_queue_push_head(), g_queue_push_head_link(),
50 * g_queue_push_tail() and g_queue_push_tail_link().
52 * To remove elements, use g_queue_pop_head() and g_queue_pop_tail().
54 * To free the entire queue, use g_queue_free().
60 #include "gtestutils.h"
66 * Creates a new #GQueue.
68 * Returns: a newly allocated #GQueue
73 return g_slice_new0 (GQueue);
80 * Frees the memory allocated for the #GQueue. Only call this function
81 * if @queue was created with g_queue_new(). If queue elements contain
82 * dynamically-allocated memory, they should be freed first.
84 * If queue elements contain dynamically-allocated memory, you should
85 * either use g_queue_free_full() or free them manually first.
88 g_queue_free (GQueue *queue)
90 g_return_if_fail (queue != NULL);
92 g_list_free (queue->head);
93 g_slice_free (GQueue, queue);
98 * @queue: a pointer to a #GQueue
99 * @free_func: the function to be called to free each element's data
101 * Convenience method, which frees all the memory used by a #GQueue,
102 * and calls the specified destroy function on every element's data.
104 * @free_func should not modify the queue (eg, by removing the freed
110 g_queue_free_full (GQueue *queue,
111 GDestroyNotify free_func)
113 g_queue_foreach (queue, (GFunc) free_func, NULL);
114 g_queue_free (queue);
119 * @queue: an uninitialized #GQueue
121 * A statically-allocated #GQueue must be initialized with this function
122 * before it can be used. Alternatively you can initialize it with
123 * %G_QUEUE_INIT. It is not necessary to initialize queues created with
129 g_queue_init (GQueue *queue)
131 g_return_if_fail (queue != NULL);
133 queue->head = queue->tail = NULL;
141 * Removes all the elements in @queue. If queue elements contain
142 * dynamically-allocated memory, they should be freed first.
147 g_queue_clear (GQueue *queue)
149 g_return_if_fail (queue != NULL);
151 g_list_free (queue->head);
152 g_queue_init (queue);
156 * g_queue_clear_full:
157 * @queue: a pointer to a #GQueue
158 * @free_func: (nullable): the function to be called to free memory allocated
160 * Convenience method, which frees all the memory used by a #GQueue,
161 * and calls the provided @free_func on each item in the #GQueue.
166 g_queue_clear_full (GQueue *queue,
167 GDestroyNotify free_func)
169 g_return_if_fail (queue != NULL);
171 if (free_func != NULL)
172 g_queue_foreach (queue, (GFunc) free_func, NULL);
174 g_queue_clear (queue);
181 * Returns %TRUE if the queue is empty.
183 * Returns: %TRUE if the queue is empty
186 g_queue_is_empty (GQueue *queue)
188 g_return_val_if_fail (queue != NULL, TRUE);
190 return queue->head == NULL;
194 * g_queue_get_length:
197 * Returns the number of items in @queue.
199 * Returns: the number of items in @queue
204 g_queue_get_length (GQueue *queue)
206 g_return_val_if_fail (queue != NULL, 0);
208 return queue->length;
215 * Reverses the order of the items in @queue.
220 g_queue_reverse (GQueue *queue)
222 g_return_if_fail (queue != NULL);
224 queue->tail = queue->head;
225 queue->head = g_list_reverse (queue->head);
232 * Copies a @queue. Note that is a shallow copy. If the elements in the
233 * queue consist of pointers to data, the pointers are copied, but the
234 * actual data is not.
236 * Returns: a copy of @queue
241 g_queue_copy (GQueue *queue)
246 g_return_val_if_fail (queue != NULL, NULL);
248 result = g_queue_new ();
250 for (list = queue->head; list != NULL; list = list->next)
251 g_queue_push_tail (result, list->data);
259 * @func: the function to call for each element's data
260 * @user_data: user data to pass to @func
262 * Calls @func for each element in the queue passing @user_data to the
265 * It is safe for @func to remove the element from @queue, but it must
266 * not modify any part of the queue after that element.
271 g_queue_foreach (GQueue *queue,
277 g_return_if_fail (queue != NULL);
278 g_return_if_fail (func != NULL);
283 GList *next = list->next;
284 func (list->data, user_data);
292 * @data: data to find
294 * Finds the first link in @queue which contains @data.
296 * Returns: the first link in @queue which contains @data
301 g_queue_find (GQueue *queue,
304 g_return_val_if_fail (queue != NULL, NULL);
306 return g_list_find (queue->head, data);
310 * g_queue_find_custom:
312 * @data: user data passed to @func
313 * @func: a #GCompareFunc to call for each element. It should return 0
314 * when the desired element is found
316 * Finds an element in a #GQueue, using a supplied function to find the
317 * desired element. It iterates over the queue, calling the given function
318 * which should return 0 when the desired element is found. The function
319 * takes two gconstpointer arguments, the #GQueue element's data as the
320 * first argument and the given user data as the second argument.
322 * Returns: the found link, or %NULL if it wasn't found
327 g_queue_find_custom (GQueue *queue,
331 g_return_val_if_fail (queue != NULL, NULL);
332 g_return_val_if_fail (func != NULL, NULL);
334 return g_list_find_custom (queue->head, data, func);
340 * @compare_func: the #GCompareDataFunc used to sort @queue. This function
341 * is passed two elements of the queue and should return 0 if they are
342 * equal, a negative value if the first comes before the second, and
343 * a positive value if the second comes before the first.
344 * @user_data: user data passed to @compare_func
346 * Sorts @queue using @compare_func.
351 g_queue_sort (GQueue *queue,
352 GCompareDataFunc compare_func,
355 g_return_if_fail (queue != NULL);
356 g_return_if_fail (compare_func != NULL);
358 queue->head = g_list_sort_with_data (queue->head, compare_func, user_data);
359 queue->tail = g_list_last (queue->head);
365 * @data: the data for the new element.
367 * Adds a new element at the head of the queue.
370 g_queue_push_head (GQueue *queue,
373 g_return_if_fail (queue != NULL);
375 queue->head = g_list_prepend (queue->head, data);
377 queue->tail = queue->head;
384 * @data: the data for the new element
385 * @n: the position to insert the new element. If @n is negative or
386 * larger than the number of elements in the @queue, the element is
387 * added to the end of the queue.
389 * Inserts a new element into @queue at the given position.
394 g_queue_push_nth (GQueue *queue,
398 g_return_if_fail (queue != NULL);
400 if (n < 0 || (guint) n >= queue->length)
402 g_queue_push_tail (queue, data);
406 g_queue_insert_before (queue, g_queue_peek_nth_link (queue, n), data);
410 * g_queue_push_head_link:
412 * @link_: a single #GList element, not a list with more than one element
414 * Adds a new element at the head of the queue.
417 g_queue_push_head_link (GQueue *queue,
420 g_return_if_fail (queue != NULL);
421 g_return_if_fail (link != NULL);
422 g_return_if_fail (link->prev == NULL);
423 g_return_if_fail (link->next == NULL);
425 link->next = queue->head;
427 queue->head->prev = link;
437 * @data: the data for the new element
439 * Adds a new element at the tail of the queue.
442 g_queue_push_tail (GQueue *queue,
445 g_return_if_fail (queue != NULL);
447 queue->tail = g_list_append (queue->tail, data);
448 if (queue->tail->next)
449 queue->tail = queue->tail->next;
451 queue->head = queue->tail;
456 * g_queue_push_tail_link:
458 * @link_: a single #GList element, not a list with more than one element
460 * Adds a new element at the tail of the queue.
463 g_queue_push_tail_link (GQueue *queue,
466 g_return_if_fail (queue != NULL);
467 g_return_if_fail (link != NULL);
468 g_return_if_fail (link->prev == NULL);
469 g_return_if_fail (link->next == NULL);
471 link->prev = queue->tail;
473 queue->tail->next = link;
481 * g_queue_push_nth_link:
483 * @n: the position to insert the link. If this is negative or larger than
484 * the number of elements in @queue, the link is added to the end of
486 * @link_: the link to add to @queue
488 * Inserts @link into @queue at the given position.
493 g_queue_push_nth_link (GQueue *queue,
500 g_return_if_fail (queue != NULL);
501 g_return_if_fail (link_ != NULL);
503 if (n < 0 || (guint) n >= queue->length)
505 g_queue_push_tail_link (queue, link_);
509 g_assert (queue->head);
510 g_assert (queue->tail);
512 next = g_queue_peek_nth_link (queue, n);
522 if (queue->head->prev)
523 queue->head = queue->head->prev;
525 /* The case where we’re pushing @link_ at the end of @queue is handled above
526 * using g_queue_push_tail_link(), so we should never have to manually adjust
528 g_assert (queue->tail->next == NULL);
537 * Removes the first element of the queue and returns its data.
539 * Returns: the data of the first element in the queue, or %NULL
540 * if the queue is empty
543 g_queue_pop_head (GQueue *queue)
545 g_return_val_if_fail (queue != NULL, NULL);
549 GList *node = queue->head;
550 gpointer data = node->data;
552 queue->head = node->next;
554 queue->head->prev = NULL;
557 g_list_free_1 (node);
567 * g_queue_pop_head_link:
570 * Removes and returns the first element of the queue.
572 * Returns: the #GList element at the head of the queue, or %NULL
573 * if the queue is empty
576 g_queue_pop_head_link (GQueue *queue)
578 g_return_val_if_fail (queue != NULL, NULL);
582 GList *node = queue->head;
584 queue->head = node->next;
587 queue->head->prev = NULL;
601 * g_queue_peek_head_link:
604 * Returns the first link in @queue.
606 * Returns: the first link in @queue, or %NULL if @queue is empty
611 g_queue_peek_head_link (GQueue *queue)
613 g_return_val_if_fail (queue != NULL, NULL);
619 * g_queue_peek_tail_link:
622 * Returns the last link in @queue.
624 * Returns: the last link in @queue, or %NULL if @queue is empty
629 g_queue_peek_tail_link (GQueue *queue)
631 g_return_val_if_fail (queue != NULL, NULL);
640 * Removes the last element of the queue and returns its data.
642 * Returns: the data of the last element in the queue, or %NULL
643 * if the queue is empty
646 g_queue_pop_tail (GQueue *queue)
648 g_return_val_if_fail (queue != NULL, NULL);
652 GList *node = queue->tail;
653 gpointer data = node->data;
655 queue->tail = node->prev;
657 queue->tail->next = NULL;
661 g_list_free_1 (node);
672 * @n: the position of the element
674 * Removes the @n'th element of @queue and returns its data.
676 * Returns: the element's data, or %NULL if @n is off the end of @queue
681 g_queue_pop_nth (GQueue *queue,
687 g_return_val_if_fail (queue != NULL, NULL);
689 if (n >= queue->length)
692 nth_link = g_queue_peek_nth_link (queue, n);
693 result = nth_link->data;
695 g_queue_delete_link (queue, nth_link);
701 * g_queue_pop_tail_link:
704 * Removes and returns the last element of the queue.
706 * Returns: the #GList element at the tail of the queue, or %NULL
707 * if the queue is empty
710 g_queue_pop_tail_link (GQueue *queue)
712 g_return_val_if_fail (queue != NULL, NULL);
716 GList *node = queue->tail;
718 queue->tail = node->prev;
721 queue->tail->next = NULL;
735 * g_queue_pop_nth_link:
737 * @n: the link's position
739 * Removes and returns the link at the given position.
741 * Returns: the @n'th link, or %NULL if @n is off the end of @queue
746 g_queue_pop_nth_link (GQueue *queue,
751 g_return_val_if_fail (queue != NULL, NULL);
753 if (n >= queue->length)
756 link = g_queue_peek_nth_link (queue, n);
757 g_queue_unlink (queue, link);
763 * g_queue_peek_nth_link:
765 * @n: the position of the link
767 * Returns the link at the given position
769 * Returns: the link at the @n'th position, or %NULL
770 * if @n is off the end of the list
775 g_queue_peek_nth_link (GQueue *queue,
781 g_return_val_if_fail (queue != NULL, NULL);
783 if (n >= queue->length)
786 if (n > queue->length / 2)
788 n = queue->length - n - 1;
791 for (i = 0; i < n; ++i)
797 for (i = 0; i < n; ++i)
805 * g_queue_link_index:
807 * @link_: a #GList link
809 * Returns the position of @link_ in @queue.
811 * Returns: the position of @link_, or -1 if the link is
817 g_queue_link_index (GQueue *queue,
820 g_return_val_if_fail (queue != NULL, -1);
822 return g_list_position (queue->head, link_);
828 * @link_: a #GList link that must be part of @queue
830 * Unlinks @link_ so that it will no longer be part of @queue.
831 * The link is not freed.
833 * @link_ must be part of @queue.
838 g_queue_unlink (GQueue *queue,
841 g_return_if_fail (queue != NULL);
842 g_return_if_fail (link_ != NULL);
844 if (link_ == queue->tail)
845 queue->tail = queue->tail->prev;
847 queue->head = g_list_remove_link (queue->head, link_);
852 * g_queue_delete_link:
854 * @link_: a #GList link that must be part of @queue
856 * Removes @link_ from @queue and frees it.
858 * @link_ must be part of @queue.
863 g_queue_delete_link (GQueue *queue,
866 g_return_if_fail (queue != NULL);
867 g_return_if_fail (link_ != NULL);
869 g_queue_unlink (queue, link_);
877 * Returns the first element of the queue.
879 * Returns: the data of the first element in the queue, or %NULL
880 * if the queue is empty
883 g_queue_peek_head (GQueue *queue)
885 g_return_val_if_fail (queue != NULL, NULL);
887 return queue->head ? queue->head->data : NULL;
894 * Returns the last element of the queue.
896 * Returns: the data of the last element in the queue, or %NULL
897 * if the queue is empty
900 g_queue_peek_tail (GQueue *queue)
902 g_return_val_if_fail (queue != NULL, NULL);
904 return queue->tail ? queue->tail->data : NULL;
910 * @n: the position of the element
912 * Returns the @n'th element of @queue.
914 * Returns: the data for the @n'th element of @queue,
915 * or %NULL if @n is off the end of @queue
920 g_queue_peek_nth (GQueue *queue,
925 g_return_val_if_fail (queue != NULL, NULL);
927 link = g_queue_peek_nth_link (queue, n);
938 * @data: the data to find
940 * Returns the position of the first element in @queue which contains @data.
942 * Returns: the position of the first element in @queue which
943 * contains @data, or -1 if no element in @queue contains @data
948 g_queue_index (GQueue *queue,
951 g_return_val_if_fail (queue != NULL, -1);
953 return g_list_index (queue->head, data);
959 * @data: the data to remove
961 * Removes the first element in @queue that contains @data.
963 * Returns: %TRUE if @data was found and removed from @queue
968 g_queue_remove (GQueue *queue,
973 g_return_val_if_fail (queue != NULL, FALSE);
975 link = g_list_find (queue->head, data);
978 g_queue_delete_link (queue, link);
980 return (link != NULL);
984 * g_queue_remove_all:
986 * @data: the data to remove
988 * Remove all elements whose data equals @data from @queue.
990 * Returns: the number of elements removed from @queue
995 g_queue_remove_all (GQueue *queue,
1001 g_return_val_if_fail (queue != NULL, 0);
1003 old_length = queue->length;
1008 GList *next = list->next;
1010 if (list->data == data)
1011 g_queue_delete_link (queue, list);
1016 return (old_length - queue->length);
1020 * g_queue_insert_before:
1022 * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
1023 * push at the tail of the queue.
1024 * @data: the data to insert
1026 * Inserts @data into @queue before @sibling.
1028 * @sibling must be part of @queue. Since GLib 2.44 a %NULL sibling pushes the
1029 * data at the tail of the queue.
1034 g_queue_insert_before (GQueue *queue,
1038 g_return_if_fail (queue != NULL);
1040 if (sibling == NULL)
1042 /* We don't use g_list_insert_before() with a NULL sibling because it
1043 * would be a O(n) operation and we would need to update manually the tail
1046 g_queue_push_tail (queue, data);
1050 queue->head = g_list_insert_before (queue->head, sibling, data);
1056 * g_queue_insert_before_link:
1058 * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
1059 * push at the tail of the queue.
1060 * @link_: a #GList link to insert which must not be part of any other list.
1062 * Inserts @link_ into @queue before @sibling.
1064 * @sibling must be part of @queue.
1069 g_queue_insert_before_link (GQueue *queue,
1073 g_return_if_fail (queue != NULL);
1074 g_return_if_fail (link_ != NULL);
1075 g_return_if_fail (link_->prev == NULL);
1076 g_return_if_fail (link_->next == NULL);
1078 if G_UNLIKELY (sibling == NULL)
1080 /* We don't use g_list_insert_before_link() with a NULL sibling because it
1081 * would be a O(n) operation and we would need to update manually the tail
1084 g_queue_push_tail_link (queue, link_);
1088 queue->head = g_list_insert_before_link (queue->head, sibling, link_);
1094 * g_queue_insert_after:
1096 * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
1097 * push at the head of the queue.
1098 * @data: the data to insert
1100 * Inserts @data into @queue after @sibling.
1102 * @sibling must be part of @queue. Since GLib 2.44 a %NULL sibling pushes the
1103 * data at the head of the queue.
1108 g_queue_insert_after (GQueue *queue,
1112 g_return_if_fail (queue != NULL);
1114 if (sibling == NULL)
1115 g_queue_push_head (queue, data);
1117 g_queue_insert_before (queue, sibling->next, data);
1121 * g_queue_insert_after_link:
1123 * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
1124 * push at the head of the queue.
1125 * @link_: a #GList link to insert which must not be part of any other list.
1127 * Inserts @link_ into @queue after @sibling.
1129 * @sibling must be part of @queue.
1134 g_queue_insert_after_link (GQueue *queue,
1138 g_return_if_fail (queue != NULL);
1139 g_return_if_fail (link_ != NULL);
1140 g_return_if_fail (link_->prev == NULL);
1141 g_return_if_fail (link_->next == NULL);
1143 if G_UNLIKELY (sibling == NULL)
1144 g_queue_push_head_link (queue, link_);
1146 g_queue_insert_before_link (queue, sibling->next, link_);
1150 * g_queue_insert_sorted:
1152 * @data: the data to insert
1153 * @func: the #GCompareDataFunc used to compare elements in the queue. It is
1154 * called with two elements of the @queue and @user_data. It should
1155 * return 0 if the elements are equal, a negative value if the first
1156 * element comes before the second, and a positive value if the second
1157 * element comes before the first.
1158 * @user_data: user data passed to @func
1160 * Inserts @data into @queue using @func to determine the new position.
1165 g_queue_insert_sorted (GQueue *queue,
1167 GCompareDataFunc func,
1172 g_return_if_fail (queue != NULL);
1175 while (list && func (list->data, data, user_data) < 0)
1178 g_queue_insert_before (queue, list, data);