Coverage Report

Created: 2025-06-13 06:55

/src/glib/gobject/gvaluearray.c
Line
Count
Source (jump to first uncovered line)
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
 * SECTION:value_arrays
34
 * @short_description: A container structure to maintain an array of
35
 *     generic values
36
 * @see_also: #GValue, #GParamSpecValueArray, g_param_spec_value_array()
37
 * @title: Value arrays
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. It
45
 * is possible to create a #GArray that behaves like a #GValueArray by
46
 * using the size of #GValue as the element size, and by setting
47
 * g_value_unset() as the clear function using g_array_set_clear_func(),
48
 * for instance, the following code:
49
 *
50
 * |[<!-- language="C" --> 
51
 *   GValueArray *array = g_value_array_new (10);
52
 * ]|
53
 *
54
 * can be replaced by:
55
 *
56
 * |[<!-- language="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
0
#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
0
{
84
0
  g_return_val_if_fail (value_array != NULL, NULL);
85
0
  g_return_val_if_fail (index < value_array->n_values, NULL);
86
87
0
  return value_array->values + index;
88
0
}
89
90
static inline void
91
value_array_grow (GValueArray *value_array,
92
      guint        n_values,
93
      gboolean     zero_init)
94
0
{
95
0
  g_return_if_fail (n_values >= value_array->n_values);
96
97
0
  value_array->n_values = n_values;
98
0
  if (value_array->n_values > value_array->n_prealloced)
99
0
    {
100
0
      guint i = value_array->n_prealloced;
101
102
0
      value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
103
0
      value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
104
0
      if (!zero_init)
105
0
  i = value_array->n_values;
106
0
      memset (value_array->values + i, 0,
107
0
        (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
108
0
    }
109
0
}
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
0
{
126
0
  GValueArray *value_array = g_slice_new (GValueArray);
127
128
0
  value_array->n_values = 0;
129
0
  value_array->n_prealloced = 0;
130
0
  value_array->values = NULL;
131
0
  value_array_grow (value_array, n_prealloced, TRUE);
132
0
  value_array->n_values = 0;
133
134
0
  return value_array;
135
0
}
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
0
{
148
0
  guint i;
149
150
0
  g_return_if_fail (value_array != NULL);
151
152
0
  for (i = 0; i < value_array->n_values; i++)
153
0
    {
154
0
      GValue *value = value_array->values + i;
155
156
0
      if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
157
0
  g_value_unset (value);
158
0
    }
159
0
  g_free (value_array->values);
160
0
  g_slice_free (GValueArray, value_array);
161
0
}
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
0
{
177
0
  GValueArray *new_array;
178
0
  guint i;
179
180
0
  g_return_val_if_fail (value_array != NULL, NULL);
181
182
0
  new_array = g_slice_new (GValueArray);
183
0
  new_array->n_values = 0;
184
0
  new_array->values = NULL;
185
0
  new_array->n_prealloced = 0;
186
0
  value_array_grow (new_array, value_array->n_values, TRUE);
187
0
  for (i = 0; i < new_array->n_values; i++)
188
0
    if (G_VALUE_TYPE (value_array->values + i) != 0)
189
0
      {
190
0
  GValue *value = new_array->values + i;
191
  
192
0
  g_value_init (value, G_VALUE_TYPE (value_array->values + i));
193
0
  g_value_copy (value_array->values + i, value);
194
0
      }
195
0
  return new_array;
196
0
}
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
0
{
215
0
  g_return_val_if_fail (value_array != NULL, NULL);
216
217
0
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
218
0
  return g_value_array_insert (value_array, 0, value);
219
0
  G_GNUC_END_IGNORE_DEPRECATIONS
220
0
}
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
0
{
238
0
  g_return_val_if_fail (value_array != NULL, NULL);
239
240
0
  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
241
0
  return g_value_array_insert (value_array, value_array->n_values, value);
242
0
  G_GNUC_END_IGNORE_DEPRECATIONS
243
0
}
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
0
{
263
0
  guint i;
264
265
0
  g_return_val_if_fail (value_array != NULL, NULL);
266
0
  g_return_val_if_fail (index <= value_array->n_values, value_array);
267
268
0
  i = value_array->n_values;
269
0
  value_array_grow (value_array, value_array->n_values + 1, FALSE);
270
0
  if (index + 1 < value_array->n_values)
271
0
    memmove (value_array->values + index + 1, value_array->values + index,
272
0
             (i - index) * sizeof (value_array->values[0]));
273
0
  memset (value_array->values + index, 0, sizeof (value_array->values[0]));
274
0
  if (value)
275
0
    {
276
0
      g_value_init (value_array->values + index, G_VALUE_TYPE (value));
277
0
      g_value_copy (value, value_array->values + index);
278
0
    }
279
0
  return value_array;
280
0
}
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
0
{
298
0
  g_return_val_if_fail (value_array != NULL, NULL);
299
0
  g_return_val_if_fail (index < value_array->n_values, value_array);
300
301
0
  if (G_VALUE_TYPE (value_array->values + index) != 0)
302
0
    g_value_unset (value_array->values + index);
303
0
  value_array->n_values--;
304
0
  if (index < value_array->n_values)
305
0
    memmove (value_array->values + index, value_array->values + index + 1,
306
0
             (value_array->n_values - index) * sizeof (value_array->values[0]));
307
0
  if (value_array->n_prealloced > value_array->n_values)
308
0
    memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
309
310
0
  return value_array;
311
0
}
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
0
{
332
0
  g_return_val_if_fail (compare_func != NULL, NULL);
333
334
0
  if (value_array->n_values)
335
0
    qsort (value_array->values,
336
0
     value_array->n_values,
337
0
     sizeof (value_array->values[0]),
338
0
     compare_func);
339
0
  return value_array;
340
0
}
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
0
{
363
0
  g_return_val_if_fail (value_array != NULL, NULL);
364
0
  g_return_val_if_fail (compare_func != NULL, NULL);
365
366
0
  if (value_array->n_values)
367
0
    g_qsort_with_data (value_array->values,
368
0
           value_array->n_values,
369
0
           sizeof (value_array->values[0]),
370
0
           compare_func, user_data);
371
0
  return value_array;
372
0
}