(root)/
glib-2.79.0/
gobject/
gvaluearray.c
       1  /* GObject - GLib Type, Object, Parameter and Signal Library
       2   * Copyright (C) 2001 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General
      17   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   */
      19  
      20  /*
      21   * MT safe
      22   */
      23  
      24  #include "config.h"
      25  
      26  #include <string.h>
      27  #include <stdlib.h>  /* qsort() */
      28  
      29  #include "gvaluearray.h"
      30  
      31  
      32  /**
      33   * GValueArray:
      34   * @n_values: number of values contained in the array
      35   * @values: array of values
      36   *
      37   * A `GValueArray` is a container structure to hold an array of generic values.
      38   *
      39   * The prime purpose of a `GValueArray` is for it to be used as an
      40   * object property that holds an array of values. A `GValueArray` wraps
      41   * an array of `GValue` elements in order for it to be used as a boxed
      42   * type through `G_TYPE_VALUE_ARRAY`.
      43   *
      44   * `GValueArray` is deprecated in favour of `GArray` since GLib 2.32.
      45   * It is possible to create a `GArray` that behaves like a `GValueArray`
      46   * by using the size of `GValue` as the element size, and by setting
      47   * [method@GObject.Value.unset] as the clear function using
      48   * [func@GLib.Array.set_clear_func], for instance, the following code:
      49   *
      50   * ```c
      51   *   GValueArray *array = g_value_array_new (10);
      52   * ```
      53   *
      54   * can be replaced by:
      55   *
      56   * ```c
      57   *   GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (GValue), 10);
      58   *   g_array_set_clear_func (array, (GDestroyNotify) g_value_unset);
      59   * ```
      60   *
      61   * Deprecated: 2.32: Use `GArray` instead, if possible for the given use case,
      62   *    as described above.
      63   */
      64  
      65  #define	GROUP_N_VALUES	(8)	/* power of 2 !! */
      66  
      67  
      68  /* --- functions --- */
      69  /**
      70   * g_value_array_get_nth:
      71   * @value_array: #GValueArray to get a value from
      72   * @index_: index of the value of interest
      73   *
      74   * Return a pointer to the value at @index_ containd in @value_array.
      75   *
      76   * Returns: (transfer none): pointer to a value at @index_ in @value_array
      77   *
      78   * Deprecated: 2.32: Use g_array_index() instead.
      79   */
      80  GValue*
      81  g_value_array_get_nth (GValueArray *value_array,
      82  		       guint        index)
      83  {
      84    g_return_val_if_fail (value_array != NULL, NULL);
      85    g_return_val_if_fail (index < value_array->n_values, NULL);
      86  
      87    return value_array->values + index;
      88  }
      89  
      90  static inline void
      91  value_array_grow (GValueArray *value_array,
      92  		  guint        n_values,
      93  		  gboolean     zero_init)
      94  {
      95    g_return_if_fail (n_values >= value_array->n_values);
      96  
      97    value_array->n_values = n_values;
      98    if (value_array->n_values > value_array->n_prealloced)
      99      {
     100        guint i = value_array->n_prealloced;
     101  
     102        value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
     103        value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
     104        if (!zero_init)
     105  	i = value_array->n_values;
     106        memset (value_array->values + i, 0,
     107  	      (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
     108      }
     109  }
     110  
     111  /**
     112   * g_value_array_new:
     113   * @n_prealloced: number of values to preallocate space for
     114   *
     115   * Allocate and initialize a new #GValueArray, optionally preserve space
     116   * for @n_prealloced elements. New arrays always contain 0 elements,
     117   * regardless of the value of @n_prealloced.
     118   *
     119   * Returns: a newly allocated #GValueArray with 0 values
     120   *
     121   * Deprecated: 2.32: Use #GArray and g_array_sized_new() instead.
     122   */
     123  GValueArray*
     124  g_value_array_new (guint n_prealloced)
     125  {
     126    GValueArray *value_array = g_slice_new (GValueArray);
     127  
     128    value_array->n_values = 0;
     129    value_array->n_prealloced = 0;
     130    value_array->values = NULL;
     131    value_array_grow (value_array, n_prealloced, TRUE);
     132    value_array->n_values = 0;
     133  
     134    return value_array;
     135  }
     136  
     137  /**
     138   * g_value_array_free: (skip)
     139   * @value_array: #GValueArray to free
     140   *
     141   * Free a #GValueArray including its contents.
     142   *
     143   * Deprecated: 2.32: Use #GArray and g_array_unref() instead.
     144   */
     145  void
     146  g_value_array_free (GValueArray *value_array)
     147  {
     148    guint i;
     149  
     150    g_return_if_fail (value_array != NULL);
     151  
     152    for (i = 0; i < value_array->n_values; i++)
     153      {
     154        GValue *value = value_array->values + i;
     155  
     156        if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
     157  	g_value_unset (value);
     158      }
     159    g_free (value_array->values);
     160    g_slice_free (GValueArray, value_array);
     161  }
     162  
     163  /**
     164   * g_value_array_copy:
     165   * @value_array: #GValueArray to copy
     166   *
     167   * Construct an exact copy of a #GValueArray by duplicating all its
     168   * contents.
     169   *
     170   * Returns: (transfer full): Newly allocated copy of #GValueArray
     171   *
     172   * Deprecated: 2.32: Use #GArray and g_array_ref() instead.
     173   */
     174  GValueArray*
     175  g_value_array_copy (const GValueArray *value_array)
     176  {
     177    GValueArray *new_array;
     178    guint i;
     179  
     180    g_return_val_if_fail (value_array != NULL, NULL);
     181  
     182    new_array = g_slice_new (GValueArray);
     183    new_array->n_values = 0;
     184    new_array->values = NULL;
     185    new_array->n_prealloced = 0;
     186    value_array_grow (new_array, value_array->n_values, TRUE);
     187    for (i = 0; i < new_array->n_values; i++)
     188      if (G_VALUE_TYPE (value_array->values + i) != 0)
     189        {
     190  	GValue *value = new_array->values + i;
     191  	
     192  	g_value_init (value, G_VALUE_TYPE (value_array->values + i));
     193  	g_value_copy (value_array->values + i, value);
     194        }
     195    return new_array;
     196  }
     197  
     198  /**
     199   * g_value_array_prepend:
     200   * @value_array: #GValueArray to add an element to
     201   * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
     202   *
     203   * Insert a copy of @value as first element of @value_array. If @value is
     204   * %NULL, an uninitialized value is prepended.
     205   *
     206   *
     207   * Returns: (transfer none): the #GValueArray passed in as @value_array
     208   *
     209   * Deprecated: 2.32: Use #GArray and g_array_prepend_val() instead.
     210   */
     211  GValueArray*
     212  g_value_array_prepend (GValueArray  *value_array,
     213  		       const GValue *value)
     214  {
     215    g_return_val_if_fail (value_array != NULL, NULL);
     216  
     217    G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     218    return g_value_array_insert (value_array, 0, value);
     219    G_GNUC_END_IGNORE_DEPRECATIONS
     220  }
     221  
     222  /**
     223   * g_value_array_append:
     224   * @value_array: #GValueArray to add an element to
     225   * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
     226   *
     227   * Insert a copy of @value as last element of @value_array. If @value is
     228   * %NULL, an uninitialized value is appended.
     229   *
     230   * Returns: (transfer none): the #GValueArray passed in as @value_array
     231   *
     232   * Deprecated: 2.32: Use #GArray and g_array_append_val() instead.
     233   */
     234  GValueArray*
     235  g_value_array_append (GValueArray  *value_array,
     236  		      const GValue *value)
     237  {
     238    g_return_val_if_fail (value_array != NULL, NULL);
     239  
     240    G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     241    return g_value_array_insert (value_array, value_array->n_values, value);
     242    G_GNUC_END_IGNORE_DEPRECATIONS
     243  }
     244  
     245  /**
     246   * g_value_array_insert:
     247   * @value_array: #GValueArray to add an element to
     248   * @index_: insertion position, must be <= value_array->;n_values
     249   * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
     250   *
     251   * Insert a copy of @value at specified position into @value_array. If @value
     252   * is %NULL, an uninitialized value is inserted.
     253   *
     254   * Returns: (transfer none): the #GValueArray passed in as @value_array
     255   *
     256   * Deprecated: 2.32: Use #GArray and g_array_insert_val() instead.
     257   */
     258  GValueArray*
     259  g_value_array_insert (GValueArray  *value_array,
     260  		      guint         index,
     261  		      const GValue *value)
     262  {
     263    guint i;
     264  
     265    g_return_val_if_fail (value_array != NULL, NULL);
     266    g_return_val_if_fail (index <= value_array->n_values, value_array);
     267  
     268    i = value_array->n_values;
     269    value_array_grow (value_array, value_array->n_values + 1, FALSE);
     270    if (index + 1 < value_array->n_values)
     271      memmove (value_array->values + index + 1, value_array->values + index,
     272               (i - index) * sizeof (value_array->values[0]));
     273    memset (value_array->values + index, 0, sizeof (value_array->values[0]));
     274    if (value)
     275      {
     276        g_value_init (value_array->values + index, G_VALUE_TYPE (value));
     277        g_value_copy (value, value_array->values + index);
     278      }
     279    return value_array;
     280  }
     281  
     282  /**
     283   * g_value_array_remove:
     284   * @value_array: #GValueArray to remove an element from
     285   * @index_: position of value to remove, which must be less than
     286   *     @value_array->n_values
     287   *
     288   * Remove the value at position @index_ from @value_array.
     289   *
     290   * Returns: (transfer none): the #GValueArray passed in as @value_array
     291   *
     292   * Deprecated: 2.32: Use #GArray and g_array_remove_index() instead.
     293   */
     294  GValueArray*
     295  g_value_array_remove (GValueArray *value_array,
     296  		      guint        index)
     297  {
     298    g_return_val_if_fail (value_array != NULL, NULL);
     299    g_return_val_if_fail (index < value_array->n_values, value_array);
     300  
     301    if (G_VALUE_TYPE (value_array->values + index) != 0)
     302      g_value_unset (value_array->values + index);
     303    value_array->n_values--;
     304    if (index < value_array->n_values)
     305      memmove (value_array->values + index, value_array->values + index + 1,
     306               (value_array->n_values - index) * sizeof (value_array->values[0]));
     307    if (value_array->n_prealloced > value_array->n_values)
     308      memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
     309  
     310    return value_array;
     311  }
     312  
     313  /**
     314   * g_value_array_sort:
     315   * @value_array: #GValueArray to sort
     316   * @compare_func: (scope call): function to compare elements
     317   *
     318   * Sort @value_array using @compare_func to compare the elements according to
     319   * the semantics of #GCompareFunc.
     320   *
     321   * The current implementation uses the same sorting algorithm as standard
     322   * C qsort() function.
     323   *
     324   * Returns: (transfer none): the #GValueArray passed in as @value_array
     325   *
     326   * Deprecated: 2.32: Use #GArray and g_array_sort().
     327   */
     328  GValueArray*
     329  g_value_array_sort (GValueArray *value_array,
     330  		    GCompareFunc compare_func)
     331  {
     332    g_return_val_if_fail (compare_func != NULL, NULL);
     333  
     334    if (value_array->n_values)
     335      qsort (value_array->values,
     336  	   value_array->n_values,
     337  	   sizeof (value_array->values[0]),
     338  	   compare_func);
     339    return value_array;
     340  }
     341  
     342  /**
     343   * g_value_array_sort_with_data: (rename-to g_value_array_sort)
     344   * @value_array: #GValueArray to sort
     345   * @compare_func: (scope call): function to compare elements
     346   * @user_data: (closure): extra data argument provided for @compare_func
     347   *
     348   * Sort @value_array using @compare_func to compare the elements according
     349   * to the semantics of #GCompareDataFunc.
     350   *
     351   * The current implementation uses the same sorting algorithm as standard
     352   * C qsort() function.
     353   *
     354   * Returns: (transfer none): the #GValueArray passed in as @value_array
     355   *
     356   * Deprecated: 2.32: Use #GArray and g_array_sort_with_data().
     357   */
     358  GValueArray*
     359  g_value_array_sort_with_data (GValueArray     *value_array,
     360  			      GCompareDataFunc compare_func,
     361  			      gpointer         user_data)
     362  {
     363    g_return_val_if_fail (value_array != NULL, NULL);
     364    g_return_val_if_fail (compare_func != NULL, NULL);
     365  
     366    if (value_array->n_values)
     367      g_qsort_with_data (value_array->values,
     368  		       value_array->n_values,
     369  		       sizeof (value_array->values[0]),
     370  		       compare_func, user_data);
     371    return value_array;
     372  }