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