glib/gobject/gvaluearray.c
changeset 18 47c74d1534e1
equal deleted inserted replaced
0:e4d67989cc36 18:47c74d1534e1
       
     1 /* GObject - GLib Type, Object, Parameter and Signal Library
       
     2  * Copyright (C) 2001 Red Hat, Inc.
       
     3  * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General
       
    16  * Public License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /*
       
    22  * MT safe
       
    23  */
       
    24 
       
    25 #include "config.h"
       
    26 
       
    27 #include <string.h>
       
    28 #include <stdlib.h>  /* qsort() */
       
    29 
       
    30 #include "gvaluearray.h"
       
    31 #include "gobjectalias.h"
       
    32 
       
    33 
       
    34 /**
       
    35  * SECTION:value_arrays
       
    36  * @short_description: A container structure to maintain an array of
       
    37  *     generic values
       
    38  * @see_also: #GValue, #GParamSpecValueArray, g_param_spec_value_array()
       
    39  * @title: Value arrays
       
    40  *
       
    41  * The prime purpose of a #GValueArray is for it to be used as an
       
    42  * object property that holds an array of values. A #GValueArray wraps
       
    43  * an array of #GValue elements in order for it to be used as a boxed
       
    44  * type through %G_TYPE_VALUE_ARRAY.
       
    45  */
       
    46 
       
    47 
       
    48 #ifdef	DISABLE_MEM_POOLS
       
    49 #  define	GROUP_N_VALUES	(1)	/* power of 2 !! */
       
    50 #else
       
    51 #  define	GROUP_N_VALUES	(8)	/* power of 2 !! */
       
    52 #endif
       
    53 
       
    54 
       
    55 /* --- functions --- */
       
    56 /**
       
    57  * g_value_array_get_nth:
       
    58  * @value_array: #GValueArray to get a value from
       
    59  * @index_: index of the value of interest
       
    60  *
       
    61  * Return a pointer to the value at @index_ containd in @value_array.
       
    62  *
       
    63  * Returns: pointer to a value at @index_ in @value_array
       
    64  */
       
    65 EXPORT_C GValue*
       
    66 g_value_array_get_nth (GValueArray *value_array,
       
    67 		       guint        index)
       
    68 {
       
    69   g_return_val_if_fail (value_array != NULL, NULL);
       
    70   g_return_val_if_fail (index < value_array->n_values, NULL);
       
    71 
       
    72   return value_array->values + index;
       
    73 }
       
    74 
       
    75 static inline void
       
    76 value_array_grow (GValueArray *value_array,
       
    77 		  guint        n_values,
       
    78 		  gboolean     zero_init)
       
    79 {
       
    80   g_return_if_fail (n_values >= value_array->n_values);
       
    81 
       
    82   value_array->n_values = n_values;
       
    83   if (value_array->n_values > value_array->n_prealloced)
       
    84     {
       
    85       guint i = value_array->n_prealloced;
       
    86 
       
    87       value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
       
    88       value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
       
    89       if (!zero_init)
       
    90 	i = value_array->n_values;
       
    91       memset (value_array->values + i, 0,
       
    92 	      (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
       
    93     }
       
    94 }
       
    95 
       
    96 static inline void
       
    97 value_array_shrink (GValueArray *value_array)
       
    98 {
       
    99 #ifdef  DISABLE_MEM_POOLS
       
   100   if (value_array->n_prealloced >= value_array->n_values + GROUP_N_VALUES)
       
   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     }
       
   105 #endif
       
   106 }
       
   107 
       
   108 /**
       
   109  * g_value_array_new:
       
   110  * @n_prealloced: number of values to preallocate space for
       
   111  *
       
   112  * Allocate and initialize a new #GValueArray, optionally preserve space
       
   113  * for @n_prealloced elements. New arrays always contain 0 elements,
       
   114  * regardless of the value of @n_prealloced.
       
   115  *
       
   116  * Returns: a newly allocated #GValueArray with 0 values
       
   117  */
       
   118 EXPORT_C GValueArray*
       
   119 g_value_array_new (guint n_prealloced)
       
   120 {
       
   121   GValueArray *value_array = g_slice_new (GValueArray);
       
   122 
       
   123   value_array->n_values = 0;
       
   124   value_array->n_prealloced = 0;
       
   125   value_array->values = NULL;
       
   126   value_array_grow (value_array, n_prealloced, TRUE);
       
   127   value_array->n_values = 0;
       
   128 
       
   129   return value_array;
       
   130 }
       
   131 
       
   132 /**
       
   133  * g_value_array_free:
       
   134  * @value_array: #GValueArray to free
       
   135  *
       
   136  * Free a #GValueArray including its contents.
       
   137  */
       
   138 EXPORT_C void
       
   139 g_value_array_free (GValueArray *value_array)
       
   140 {
       
   141   guint i;
       
   142 
       
   143   g_return_if_fail (value_array != NULL);
       
   144 
       
   145   for (i = 0; i < value_array->n_values; i++)
       
   146     {
       
   147       GValue *value = value_array->values + i;
       
   148 
       
   149       if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
       
   150 	g_value_unset (value);
       
   151     }
       
   152   g_free (value_array->values);
       
   153   g_slice_free (GValueArray, value_array);
       
   154 }
       
   155 
       
   156 /**
       
   157  * g_value_array_copy:
       
   158  * @value_array: #GValueArray to copy
       
   159  *
       
   160  * Construct an exact copy of a #GValueArray by duplicating all its
       
   161  * contents.
       
   162  *
       
   163  * Returns: Newly allocated copy of #GValueArray
       
   164  */
       
   165 EXPORT_C GValueArray*
       
   166 g_value_array_copy (const GValueArray *value_array)
       
   167 {
       
   168   GValueArray *new_array;
       
   169   guint i;
       
   170 
       
   171   g_return_val_if_fail (value_array != NULL, NULL);
       
   172 
       
   173   new_array = g_slice_new (GValueArray);
       
   174   new_array->n_values = 0;
       
   175   new_array->values = NULL;
       
   176   new_array->n_prealloced = 0;
       
   177   value_array_grow (new_array, value_array->n_values, TRUE);
       
   178   for (i = 0; i < new_array->n_values; i++)
       
   179     if (G_VALUE_TYPE (value_array->values + i) != 0)
       
   180       {
       
   181 	GValue *value = new_array->values + i;
       
   182 	
       
   183 	g_value_init (value, G_VALUE_TYPE (value_array->values + i));
       
   184 	g_value_copy (value_array->values + i, value);
       
   185       }
       
   186   return new_array;
       
   187 }
       
   188 
       
   189 /**
       
   190  * g_value_array_prepend:
       
   191  * @value_array: #GValueArray to add an element to
       
   192  * @value: #GValue to copy into #GValueArray
       
   193  *
       
   194  * Insert a copy of @value as first element of @value_array.
       
   195  *
       
   196  * Returns: the #GValueArray passed in as @value_array
       
   197  */
       
   198 EXPORT_C GValueArray*
       
   199 g_value_array_prepend (GValueArray  *value_array,
       
   200 		       const GValue *value)
       
   201 {
       
   202   g_return_val_if_fail (value_array != NULL, NULL);
       
   203 
       
   204   return g_value_array_insert (value_array, 0, value);
       
   205 }
       
   206 
       
   207 /**
       
   208  * g_value_array_append:
       
   209  * @value_array: #GValueArray to add an element to
       
   210  * @value: #GValue to copy into #GValueArray
       
   211  *
       
   212  * Insert a copy of @value as last element of @value_array.
       
   213  *
       
   214  * Returns: the #GValueArray passed in as @value_array
       
   215  */
       
   216 EXPORT_C GValueArray*
       
   217 g_value_array_append (GValueArray  *value_array,
       
   218 		      const GValue *value)
       
   219 {
       
   220   g_return_val_if_fail (value_array != NULL, NULL);
       
   221 
       
   222   return g_value_array_insert (value_array, value_array->n_values, value);
       
   223 }
       
   224 
       
   225 /**
       
   226  * g_value_array_insert:
       
   227  * @value_array: #GValueArray to add an element to
       
   228  * @index_: insertion position, must be &lt;= value_array-&gt;n_values
       
   229  * @value: #GValue to copy into #GValueArray
       
   230  *
       
   231  * Insert a copy of @value at specified position into @value_array.
       
   232  *
       
   233  * Returns: the #GValueArray passed in as @value_array
       
   234  */
       
   235 EXPORT_C GValueArray*
       
   236 g_value_array_insert (GValueArray  *value_array,
       
   237 		      guint         index,
       
   238 		      const GValue *value)
       
   239 {
       
   240   guint i;
       
   241 
       
   242   g_return_val_if_fail (value_array != NULL, NULL);
       
   243   g_return_val_if_fail (index <= value_array->n_values, value_array);
       
   244 
       
   245   /* we support NULL for "value" as a shortcut for an unset value */
       
   246 
       
   247   i = value_array->n_values;
       
   248   value_array_grow (value_array, value_array->n_values + 1, FALSE);
       
   249   if (index + 1 < value_array->n_values)
       
   250     g_memmove (value_array->values + index + 1, value_array->values + index,
       
   251 	       (i - index) * sizeof (value_array->values[0]));
       
   252   memset (value_array->values + index, 0, sizeof (value_array->values[0]));
       
   253   if (value)
       
   254     {
       
   255       g_value_init (value_array->values + index, G_VALUE_TYPE (value));
       
   256       g_value_copy (value, value_array->values + index);
       
   257     }
       
   258   return value_array;
       
   259 }
       
   260 
       
   261 /**
       
   262  * g_value_array_remove:
       
   263  * @value_array: #GValueArray to remove an element from
       
   264  * @index_: position of value to remove, must be &lt; value_array->n_values
       
   265  *
       
   266  * Remove the value at position @index_ from @value_array.
       
   267  *
       
   268  * Returns: the #GValueArray passed in as @value_array
       
   269  */
       
   270 EXPORT_C GValueArray*
       
   271 g_value_array_remove (GValueArray *value_array,
       
   272 		      guint        index)
       
   273 {
       
   274   g_return_val_if_fail (value_array != NULL, NULL);
       
   275   g_return_val_if_fail (index < value_array->n_values, value_array);
       
   276 
       
   277   if (G_VALUE_TYPE (value_array->values + index) != 0)
       
   278     g_value_unset (value_array->values + index);
       
   279   value_array->n_values--;
       
   280   if (index < value_array->n_values)
       
   281     g_memmove (value_array->values + index, value_array->values + index + 1,
       
   282 	       (value_array->n_values - index) * sizeof (value_array->values[0]));
       
   283   value_array_shrink (value_array);
       
   284   if (value_array->n_prealloced > value_array->n_values)
       
   285     memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
       
   286 
       
   287   return value_array;
       
   288 }
       
   289 
       
   290 /**
       
   291  * g_value_array_sort:
       
   292  * @value_array: #GValueArray to sort
       
   293  * @compare_func: function to compare elements
       
   294  *
       
   295  * Sort @value_array using @compare_func to compare the elements accoring to
       
   296  * the semantics of #GCompareFunc.
       
   297  *
       
   298  * The current implementation uses Quick-Sort as sorting algorithm.
       
   299  *
       
   300  * Returns: the #GValueArray passed in as @value_array
       
   301  */
       
   302 EXPORT_C GValueArray*
       
   303 g_value_array_sort (GValueArray *value_array,
       
   304 		    GCompareFunc compare_func)
       
   305 {
       
   306   g_return_val_if_fail (compare_func != NULL, NULL);
       
   307 
       
   308   if (value_array->n_values)
       
   309     qsort (value_array->values,
       
   310 	   value_array->n_values,
       
   311 	   sizeof (value_array->values[0]),
       
   312 	   compare_func);
       
   313   return value_array;
       
   314 }
       
   315 
       
   316 /**
       
   317  * g_value_array_sort_with_data:
       
   318  * @value_array: #GValueArray to sort
       
   319  * @compare_func: function to compare elements
       
   320  * @user_data: extra data argument provided for @compare_func
       
   321  *
       
   322  * Sort @value_array using @compare_func to compare the elements accoring
       
   323  * to the semantics of #GCompareDataFunc.
       
   324  *
       
   325  * The current implementation uses Quick-Sort as sorting algorithm.
       
   326  *
       
   327  * Returns: the #GValueArray passed in as @value_array
       
   328  */
       
   329 EXPORT_C GValueArray*
       
   330 g_value_array_sort_with_data (GValueArray     *value_array,
       
   331 			      GCompareDataFunc compare_func,
       
   332 			      gpointer         user_data)
       
   333 {
       
   334   g_return_val_if_fail (value_array != NULL, NULL);
       
   335   g_return_val_if_fail (compare_func != NULL, NULL);
       
   336 
       
   337   if (value_array->n_values)
       
   338     g_qsort_with_data (value_array->values,
       
   339 		       value_array->n_values,
       
   340 		       sizeof (value_array->values[0]),
       
   341 		       compare_func, user_data);
       
   342   return value_array;
       
   343 }
       
   344 
       
   345 #define __G_VALUE_ARRAY_C__
       
   346 #include "gobjectaliasdef.c"