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