Imported Upstream version 2.57.2
[platform/upstream/glib.git] / gobject / gvaluearray.c
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
60 #define GROUP_N_VALUES  (8)     /* power of 2 !! */
61
62
63 /* --- functions --- */
64 /**
65  * g_value_array_get_nth:
66  * @value_array: #GValueArray to get a value from
67  * @index_: index of the value of interest
68  *
69  * Return a pointer to the value at @index_ containd in @value_array.
70  *
71  * Returns: (transfer none): pointer to a value at @index_ in @value_array
72  *
73  * Deprecated: 2.32: Use g_array_index() instead.
74  */
75 GValue*
76 g_value_array_get_nth (GValueArray *value_array,
77                        guint        index)
78 {
79   g_return_val_if_fail (value_array != NULL, NULL);
80   g_return_val_if_fail (index < value_array->n_values, NULL);
81
82   return value_array->values + index;
83 }
84
85 static inline void
86 value_array_grow (GValueArray *value_array,
87                   guint        n_values,
88                   gboolean     zero_init)
89 {
90   g_return_if_fail (n_values >= value_array->n_values);
91
92   value_array->n_values = n_values;
93   if (value_array->n_values > value_array->n_prealloced)
94     {
95       guint i = value_array->n_prealloced;
96
97       value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
98       value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
99       if (!zero_init)
100         i = value_array->n_values;
101       memset (value_array->values + i, 0,
102               (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
103     }
104 }
105
106 /**
107  * g_value_array_new:
108  * @n_prealloced: number of values to preallocate space for
109  *
110  * Allocate and initialize a new #GValueArray, optionally preserve space
111  * for @n_prealloced elements. New arrays always contain 0 elements,
112  * regardless of the value of @n_prealloced.
113  *
114  * Returns: a newly allocated #GValueArray with 0 values
115  *
116  * Deprecated: 2.32: Use #GArray and g_array_sized_new() instead.
117  */
118 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: (skip)
134  * @value_array: #GValueArray to free
135  *
136  * Free a #GValueArray including its contents.
137  *
138  * Deprecated: 2.32: Use #GArray and g_array_unref() instead.
139  */
140 void
141 g_value_array_free (GValueArray *value_array)
142 {
143   guint i;
144
145   g_return_if_fail (value_array != NULL);
146
147   for (i = 0; i < value_array->n_values; i++)
148     {
149       GValue *value = value_array->values + i;
150
151       if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
152         g_value_unset (value);
153     }
154   g_free (value_array->values);
155   g_slice_free (GValueArray, value_array);
156 }
157
158 /**
159  * g_value_array_copy:
160  * @value_array: #GValueArray to copy
161  *
162  * Construct an exact copy of a #GValueArray by duplicating all its
163  * contents.
164  *
165  * Returns: (transfer full): Newly allocated copy of #GValueArray
166  *
167  * Deprecated: 2.32: Use #GArray and g_array_ref() instead.
168  */
169 GValueArray*
170 g_value_array_copy (const GValueArray *value_array)
171 {
172   GValueArray *new_array;
173   guint i;
174
175   g_return_val_if_fail (value_array != NULL, NULL);
176
177   new_array = g_slice_new (GValueArray);
178   new_array->n_values = 0;
179   new_array->values = NULL;
180   new_array->n_prealloced = 0;
181   value_array_grow (new_array, value_array->n_values, TRUE);
182   for (i = 0; i < new_array->n_values; i++)
183     if (G_VALUE_TYPE (value_array->values + i) != 0)
184       {
185         GValue *value = new_array->values + i;
186         
187         g_value_init (value, G_VALUE_TYPE (value_array->values + i));
188         g_value_copy (value_array->values + i, value);
189       }
190   return new_array;
191 }
192
193 /**
194  * g_value_array_prepend:
195  * @value_array: #GValueArray to add an element to
196  * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
197  *
198  * Insert a copy of @value as first element of @value_array. If @value is
199  * %NULL, an uninitialized value is prepended.
200  *
201  *
202  * Returns: (transfer none): the #GValueArray passed in as @value_array
203  *
204  * Deprecated: 2.32: Use #GArray and g_array_prepend_val() instead.
205  */
206 GValueArray*
207 g_value_array_prepend (GValueArray  *value_array,
208                        const GValue *value)
209 {
210   g_return_val_if_fail (value_array != NULL, NULL);
211
212   G_GNUC_BEGIN_IGNORE_DEPRECATIONS
213   return g_value_array_insert (value_array, 0, value);
214   G_GNUC_END_IGNORE_DEPRECATIONS
215 }
216
217 /**
218  * g_value_array_append:
219  * @value_array: #GValueArray to add an element to
220  * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
221  *
222  * Insert a copy of @value as last element of @value_array. If @value is
223  * %NULL, an uninitialized value is appended.
224  *
225  * Returns: (transfer none): the #GValueArray passed in as @value_array
226  *
227  * Deprecated: 2.32: Use #GArray and g_array_append_val() instead.
228  */
229 GValueArray*
230 g_value_array_append (GValueArray  *value_array,
231                       const GValue *value)
232 {
233   g_return_val_if_fail (value_array != NULL, NULL);
234
235   G_GNUC_BEGIN_IGNORE_DEPRECATIONS
236   return g_value_array_insert (value_array, value_array->n_values, value);
237   G_GNUC_END_IGNORE_DEPRECATIONS
238 }
239
240 /**
241  * g_value_array_insert:
242  * @value_array: #GValueArray to add an element to
243  * @index_: insertion position, must be <= value_array->;n_values
244  * @value: (nullable): #GValue to copy into #GValueArray, or %NULL
245  *
246  * Insert a copy of @value at specified position into @value_array. If @value
247  * is %NULL, an uninitialized value is inserted.
248  *
249  * Returns: (transfer none): the #GValueArray passed in as @value_array
250  *
251  * Deprecated: 2.32: Use #GArray and g_array_insert_val() instead.
252  */
253 GValueArray*
254 g_value_array_insert (GValueArray  *value_array,
255                       guint         index,
256                       const GValue *value)
257 {
258   guint i;
259
260   g_return_val_if_fail (value_array != NULL, NULL);
261   g_return_val_if_fail (index <= value_array->n_values, value_array);
262
263   i = value_array->n_values;
264   value_array_grow (value_array, value_array->n_values + 1, FALSE);
265   if (index + 1 < value_array->n_values)
266     memmove (value_array->values + index + 1, value_array->values + index,
267              (i - index) * sizeof (value_array->values[0]));
268   memset (value_array->values + index, 0, sizeof (value_array->values[0]));
269   if (value)
270     {
271       g_value_init (value_array->values + index, G_VALUE_TYPE (value));
272       g_value_copy (value, value_array->values + index);
273     }
274   return value_array;
275 }
276
277 /**
278  * g_value_array_remove:
279  * @value_array: #GValueArray to remove an element from
280  * @index_: position of value to remove, which must be less than
281  *     @value_array->n_values
282  *
283  * Remove the value at position @index_ from @value_array.
284  *
285  * Returns: (transfer none): the #GValueArray passed in as @value_array
286  *
287  * Deprecated: 2.32: Use #GArray and g_array_remove_index() instead.
288  */
289 GValueArray*
290 g_value_array_remove (GValueArray *value_array,
291                       guint        index)
292 {
293   g_return_val_if_fail (value_array != NULL, NULL);
294   g_return_val_if_fail (index < value_array->n_values, value_array);
295
296   if (G_VALUE_TYPE (value_array->values + index) != 0)
297     g_value_unset (value_array->values + index);
298   value_array->n_values--;
299   if (index < value_array->n_values)
300     memmove (value_array->values + index, value_array->values + index + 1,
301              (value_array->n_values - index) * sizeof (value_array->values[0]));
302   if (value_array->n_prealloced > value_array->n_values)
303     memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
304
305   return value_array;
306 }
307
308 /**
309  * g_value_array_sort:
310  * @value_array: #GValueArray to sort
311  * @compare_func: (scope call): function to compare elements
312  *
313  * Sort @value_array using @compare_func to compare the elements according to
314  * the semantics of #GCompareFunc.
315  *
316  * The current implementation uses the same sorting algorithm as standard
317  * C qsort() function.
318  *
319  * Returns: (transfer none): the #GValueArray passed in as @value_array
320  *
321  * Deprecated: 2.32: Use #GArray and g_array_sort().
322  */
323 GValueArray*
324 g_value_array_sort (GValueArray *value_array,
325                     GCompareFunc compare_func)
326 {
327   g_return_val_if_fail (compare_func != NULL, NULL);
328
329   if (value_array->n_values)
330     qsort (value_array->values,
331            value_array->n_values,
332            sizeof (value_array->values[0]),
333            compare_func);
334   return value_array;
335 }
336
337 /**
338  * g_value_array_sort_with_data: (rename-to g_value_array_sort)
339  * @value_array: #GValueArray to sort
340  * @compare_func: (scope call): function to compare elements
341  * @user_data: (closure): extra data argument provided for @compare_func
342  *
343  * Sort @value_array using @compare_func to compare the elements according
344  * to the semantics of #GCompareDataFunc.
345  *
346  * The current implementation uses the same sorting algorithm as standard
347  * C qsort() function.
348  *
349  * Returns: (transfer none): the #GValueArray passed in as @value_array
350  *
351  * Deprecated: 2.32: Use #GArray and g_array_sort_with_data().
352  */
353 GValueArray*
354 g_value_array_sort_with_data (GValueArray     *value_array,
355                               GCompareDataFunc compare_func,
356                               gpointer         user_data)
357 {
358   g_return_val_if_fail (value_array != NULL, NULL);
359   g_return_val_if_fail (compare_func != NULL, NULL);
360
361   if (value_array->n_values)
362     g_qsort_with_data (value_array->values,
363                        value_array->n_values,
364                        sizeof (value_array->values[0]),
365                        compare_func, user_data);
366   return value_array;
367 }