Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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 Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : /*
21 : : * Modified by the GLib Team and others 1997-2000. See the AUTHORS
22 : : * file for a list of people on the GLib Team. See the ChangeLog
23 : : * files for a list of changes. These files are distributed with
24 : : * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 : : */
26 : :
27 : : /*
28 : : * MT safe
29 : : */
30 : :
31 : : #include "config.h"
32 : :
33 : : #include <string.h>
34 : : #include <stdlib.h>
35 : :
36 : : #include "garray.h"
37 : :
38 : : #include "galloca.h"
39 : : #include "gbytes.h"
40 : : #include "ghash.h"
41 : : #include "gslice.h"
42 : : #include "gmem.h"
43 : : #include "gtestutils.h"
44 : : #include "gthread.h"
45 : : #include "gmessages.h"
46 : : #include "gqsort.h"
47 : : #include "grefcount.h"
48 : : #include "gutilsprivate.h"
49 : :
50 : : #define MIN_ARRAY_SIZE 16
51 : :
52 : : typedef struct _GRealArray GRealArray;
53 : :
54 : : /**
55 : : * GArray: (copy-func g_array_ref) (free-func g_array_unref)
56 : : * @data: a pointer to the element data. The data may be moved as
57 : : * elements are added to the `GArray`.
58 : : * @len: the number of elements in the `GArray` not including the
59 : : * possible terminating zero element
60 : : *
61 : : * Contains the public fields of a `GArray`.
62 : : */
63 : : struct _GRealArray
64 : : {
65 : : guint8 *data;
66 : : guint len;
67 : : guint elt_capacity;
68 : : guint elt_size;
69 : : guint zero_terminated : 1;
70 : : guint clear : 1;
71 : : gatomicrefcount ref_count;
72 : : GDestroyNotify clear_func;
73 : : };
74 : :
75 : : /**
76 : : * g_array_index:
77 : : * @a: an array
78 : : * @t: the type of the elements
79 : : * @i: the index of the element to return
80 : : *
81 : : * Returns the element of a `GArray` at the given index. The return
82 : : * value is cast to the given type. This is the main way to read or write an
83 : : * element in a `GArray`.
84 : : *
85 : : * Writing an element is typically done by reference, as in the following
86 : : * example. This example gets a pointer to an element in a `GArray`, and then
87 : : * writes to a field in it:
88 : : * ```c
89 : : * EDayViewEvent *event;
90 : : * // This gets a pointer to the 4th element in the array of
91 : : * // EDayViewEvent structs.
92 : : * event = &g_array_index (events, EDayViewEvent, 3);
93 : : * event->start_time = g_get_current_time ();
94 : : * ```
95 : : *
96 : : * This example reads from and writes to an array of integers:
97 : : * ```c
98 : : * g_autoptr(GArray) int_array = g_array_new (FALSE, FALSE, sizeof (guint));
99 : : * for (guint i = 0; i < 10; i++)
100 : : * g_array_append_val (int_array, i);
101 : : *
102 : : * guint *my_int = &g_array_index (int_array, guint, 1);
103 : : * g_print ("Int at index 1 is %u; decrementing it\n", *my_int);
104 : : * *my_int = *my_int - 1;
105 : : * ```
106 : : *
107 : : * Returns: (transfer none): The element of the `GArray` at the index given by @i
108 : : */
109 : :
110 : : #define g_array_elt_len(array,i) ((gsize)(array)->elt_size * (i))
111 : : #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
112 : : #define g_array_elt_zero(array, pos, len) \
113 : : (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
114 : : #define g_array_zero_terminate(array) G_STMT_START{ \
115 : : if ((array)->zero_terminated) \
116 : : g_array_elt_zero ((array), (array)->len, 1); \
117 : : }G_STMT_END
118 : :
119 : : static void g_array_maybe_expand (GRealArray *array,
120 : : guint len);
121 : :
122 : : /**
123 : : * g_array_new:
124 : : * @zero_terminated: if true, the array should have an extra element at
125 : : * the end which is set to 0
126 : : * @clear_: if true, `GArray` elements should be automatically cleared
127 : : * to 0 when they are allocated
128 : : * @element_size: the size of each element in bytes
129 : : *
130 : : * Creates a new `GArray` with a reference count of 1.
131 : : *
132 : : * Returns: (transfer full): The new `GArray`
133 : : */
134 : : GArray*
135 : 8158 : g_array_new (gboolean zero_terminated,
136 : : gboolean clear,
137 : : guint elt_size)
138 : : {
139 : 8158 : g_return_val_if_fail (elt_size > 0, NULL);
140 : : #if (UINT_WIDTH / 8) >= GLIB_SIZEOF_SIZE_T
141 : : g_return_val_if_fail (elt_size <= G_MAXSIZE / 2 - 1, NULL);
142 : : #endif
143 : :
144 : 8158 : return g_array_sized_new (zero_terminated, clear, elt_size, 0);
145 : : }
146 : :
147 : : /**
148 : : * g_array_new_take: (skip)
149 : : * @data: (array length=len) (transfer full) (nullable): an array of
150 : : * elements of @element_size
151 : : * @len: the number of elements in @data
152 : : * @clear: if true, `GArray` elements should be automatically cleared
153 : : * to 0 when they are allocated
154 : : * @element_size: the size of each element in bytes
155 : : *
156 : : * Creates a new `GArray` with @data as array data, @len as length and a
157 : : * reference count of 1.
158 : : *
159 : : * This avoids having to copy the data manually, when it can just be
160 : : * inherited.
161 : : * After this call, @data belongs to the `GArray` and may no longer be
162 : : * modified by the caller. The memory of @data has to be dynamically
163 : : * allocated and will eventually be freed with [func@GLib.free].
164 : : *
165 : : * In case the elements need to be cleared when the array is freed, use
166 : : * [func@GLib.Array.set_clear_func] to set a [callback@GLib.DestroyNotify]
167 : : * function to perform such task.
168 : : *
169 : : * Do not use it if @len or @element_size are greater than
170 : : * [`G_MAXUINT`](types.html#guint). `GArray` stores the length of its data in
171 : : * `guint`, which may be shorter than `gsize`.
172 : : *
173 : : * Returns: (transfer full): The new #GArray
174 : : *
175 : : * Since: 2.76
176 : : */
177 : : GArray *
178 : 12 : g_array_new_take (gpointer data,
179 : : gsize len,
180 : : gboolean clear,
181 : : gsize element_size)
182 : : {
183 : : GRealArray *rarray;
184 : : GArray *array;
185 : :
186 : 12 : g_return_val_if_fail (data != NULL || len == 0, NULL);
187 : 12 : g_return_val_if_fail (len <= G_MAXUINT, NULL);
188 : 11 : g_return_val_if_fail (element_size > 0 && element_size <= G_MAXUINT, NULL);
189 : :
190 : 9 : array = g_array_sized_new (FALSE, clear, element_size, 0);
191 : 9 : rarray = (GRealArray *) array;
192 : 9 : rarray->data = (guint8 *) g_steal_pointer (&data);
193 : 9 : rarray->len = len;
194 : 9 : rarray->elt_capacity = len;
195 : :
196 : 9 : return array;
197 : : }
198 : :
199 : : /**
200 : : * g_array_new_take_zero_terminated: (skip)
201 : : * @data: (array zero-terminated=1) (transfer full) (nullable): an array
202 : : * of elements of @element_size, `NULL` terminated
203 : : * @clear: if true, `GArray` elements should be automatically cleared
204 : : * to 0 when they are allocated
205 : : * @element_size: the size of each element in bytes
206 : : *
207 : : * Creates a new `GArray` with @data as array data, computing the length of it
208 : : * and setting the reference count to 1.
209 : : *
210 : : * This avoids having to copy the data manually, when it can just be
211 : : * inherited.
212 : : * After this call, @data belongs to the `GArray` and may no longer be
213 : : * modified by the caller. The memory of @data has to be dynamically
214 : : * allocated and will eventually be freed with [func@GLib.free].
215 : : *
216 : : * The length is calculated by iterating through @data until the first `NULL`
217 : : * element is found.
218 : : *
219 : : * In case the elements need to be cleared when the array is freed, use
220 : : * [func@GLib.Array.set_clear_func] to set a [callback@GLib.DestroyNotify]
221 : : * function to perform such task.
222 : : *
223 : : * Do not use it if @data length or @element_size are greater than
224 : : * [`G_MAXUINT`](types.html#guint). `GArray` stores the length of its data in
225 : : * `guint`, which may be shorter than `gsize`.
226 : : *
227 : : * Returns: (transfer full): The new `GArray`
228 : : *
229 : : * Since: 2.76
230 : : */
231 : : GArray *
232 : 7 : g_array_new_take_zero_terminated (gpointer data,
233 : : gboolean clear,
234 : : gsize element_size)
235 : : {
236 : : GRealArray *rarray;
237 : : GArray *array;
238 : 7 : gsize len = 0;
239 : :
240 : 7 : g_return_val_if_fail (element_size > 0 && element_size <= G_MAXUINT, NULL);
241 : :
242 : 6 : if (data != NULL)
243 : : {
244 : 2 : guint8 *array_data = data;
245 : :
246 : 2 : for (gsize i = 0; ; ++i)
247 : 10255 : {
248 : 10257 : const guint8 *element_start = array_data + (i * element_size);
249 : :
250 : 10257 : if (*element_start == 0 &&
251 : 41 : memcmp (element_start, element_start + 1, element_size - 1) == 0)
252 : 2 : break;
253 : :
254 : 10255 : len += 1;
255 : : }
256 : : }
257 : :
258 : 6 : g_return_val_if_fail (len < G_MAXUINT, NULL);
259 : :
260 : 6 : array = g_array_new_take (data, len, clear, element_size);
261 : 6 : rarray = (GRealArray *) array;
262 : 6 : rarray->zero_terminated = TRUE;
263 : 6 : if (G_LIKELY (rarray->data != NULL))
264 : 2 : rarray->elt_capacity = len + 1;
265 : :
266 : 6 : return array;
267 : : }
268 : :
269 : : /**
270 : : * g_array_steal:
271 : : * @array: an array
272 : : * @len: (optional) (out): a pointer to retrieve the number of
273 : : * elements of the original array
274 : : *
275 : : * Frees the data in the array and resets the size to zero, while
276 : : * the underlying array is preserved for use elsewhere and returned
277 : : * to the caller.
278 : : *
279 : : * Note that if the array was created with the @zero_terminate
280 : : * property set to true, this may still return `NULL` if the length
281 : : * of the array was zero and data was not yet allocated.
282 : : *
283 : : * If array elements contain dynamically-allocated memory,
284 : : * the array elements should also be freed by the caller.
285 : : *
286 : : * A short example of use:
287 : : * ```c
288 : : * ...
289 : : * gpointer data;
290 : : * gsize data_len;
291 : : * data = g_array_steal (some_array, &data_len);
292 : : * ...
293 : : * ```
294 : : *
295 : : * Returns: (transfer full): The allocated element data
296 : : *
297 : : * Since: 2.64
298 : : */
299 : : gpointer
300 : 9 : g_array_steal (GArray *array,
301 : : gsize *len)
302 : : {
303 : : GRealArray *rarray;
304 : : gpointer segment;
305 : :
306 : 9 : g_return_val_if_fail (array != NULL, NULL);
307 : :
308 : 9 : rarray = (GRealArray *) array;
309 : 9 : segment = (gpointer) rarray->data;
310 : :
311 : 9 : if (len != NULL)
312 : 7 : *len = rarray->len;
313 : :
314 : 9 : rarray->data = NULL;
315 : 9 : rarray->len = 0;
316 : 9 : rarray->elt_capacity = 0;
317 : 9 : return segment;
318 : : }
319 : :
320 : : /**
321 : : * g_array_sized_new:
322 : : * @zero_terminated: if true, the array should have an extra element at
323 : : * the end with all bits cleared
324 : : * @clear_: if true, all bits in the array should be cleared to 0 on
325 : : * allocation
326 : : * @element_size: the size of each element in the array
327 : : * @reserved_size: the number of elements preallocated
328 : : *
329 : : * Creates a new `GArray` with @reserved_size elements preallocated and
330 : : * a reference count of 1. This avoids frequent reallocation, if you
331 : : * are going to add many elements to the array. Note however that the
332 : : * size of the array is still 0.
333 : : *
334 : : * Returns: (transfer full): The new `GArray`
335 : : */
336 : : GArray*
337 : 8816 : g_array_sized_new (gboolean zero_terminated,
338 : : gboolean clear,
339 : : guint elt_size,
340 : : guint reserved_size)
341 : : {
342 : : GRealArray *array;
343 : :
344 : 8816 : g_return_val_if_fail (elt_size > 0, NULL);
345 : : #if (UINT_WIDTH / 8) >= GLIB_SIZEOF_SIZE_T
346 : : g_return_val_if_fail (elt_size <= G_MAXSIZE / 2 - 1, NULL);
347 : : #endif
348 : :
349 : 8816 : array = g_slice_new (GRealArray);
350 : :
351 : 8816 : array->data = NULL;
352 : 8816 : array->len = 0;
353 : 8816 : array->elt_capacity = 0;
354 : 8816 : array->zero_terminated = (zero_terminated ? 1 : 0);
355 : 8816 : array->clear = (clear ? 1 : 0);
356 : 8816 : array->elt_size = elt_size;
357 : 8816 : array->clear_func = NULL;
358 : :
359 : 8816 : g_atomic_ref_count_init (&array->ref_count);
360 : :
361 : 8816 : if (array->zero_terminated || reserved_size != 0)
362 : : {
363 : 283 : g_array_maybe_expand (array, reserved_size);
364 : 283 : g_assert (array->data != NULL);
365 : 283 : g_array_zero_terminate (array);
366 : : }
367 : :
368 : 8816 : return (GArray*) array;
369 : : }
370 : :
371 : : /**
372 : : * g_array_set_clear_func:
373 : : * @array: an array
374 : : * @clear_func: (nullable): a function to clear an element of @array
375 : : *
376 : : * Sets a function to clear an element of @array.
377 : : *
378 : : * The @clear_func will be called when an element in the array
379 : : * data segment is removed and when the array is freed and data
380 : : * segment is deallocated as well. @clear_func will be passed a
381 : : * pointer to the element to clear, rather than the element itself.
382 : : *
383 : : * Note that in contrast with other uses of [callback@GLib.DestroyNotify]
384 : : * functions, @clear_func is expected to clear the contents of
385 : : * the array element it is given, but not free the element itself.
386 : : *
387 : : * ```c
388 : : * typedef struct
389 : : * {
390 : : * gchar *str;
391 : : * GObject *obj;
392 : : * } ArrayElement;
393 : : *
394 : : * static void
395 : : * array_element_clear (ArrayElement *element)
396 : : * {
397 : : * g_clear_pointer (&element->str, g_free);
398 : : * g_clear_object (&element->obj);
399 : : * }
400 : : *
401 : : * // main code
402 : : * GArray *garray = g_array_new (FALSE, FALSE, sizeof (ArrayElement));
403 : : * g_array_set_clear_func (garray, (GDestroyNotify) array_element_clear);
404 : : * // assign data to the structure
405 : : * g_array_free (garray, TRUE);
406 : : * ```
407 : : *
408 : : * Since: 2.32
409 : : */
410 : : void
411 : 11 : g_array_set_clear_func (GArray *array,
412 : : GDestroyNotify clear_func)
413 : : {
414 : 11 : GRealArray *rarray = (GRealArray *) array;
415 : :
416 : 11 : g_return_if_fail (array != NULL);
417 : :
418 : 11 : rarray->clear_func = clear_func;
419 : : }
420 : :
421 : : /**
422 : : * g_array_ref:
423 : : * @array: an array
424 : : *
425 : : * Atomically increments the reference count of @array by one.
426 : : * This function is thread-safe and may be called from any thread.
427 : : *
428 : : * Returns: (transfer full): The passed in `GArray`
429 : : *
430 : : * Since: 2.22
431 : : */
432 : : GArray *
433 : 6 : g_array_ref (GArray *array)
434 : : {
435 : 6 : GRealArray *rarray = (GRealArray*) array;
436 : 6 : g_return_val_if_fail (array, NULL);
437 : :
438 : 6 : g_atomic_ref_count_inc (&rarray->ref_count);
439 : :
440 : 6 : return array;
441 : : }
442 : :
443 : : typedef enum
444 : : {
445 : : FREE_SEGMENT = 1 << 0,
446 : : PRESERVE_WRAPPER = 1 << 1
447 : : } G_GNUC_FLAG_ENUM ArrayFreeFlags;
448 : :
449 : : static gchar *array_free (GRealArray *, ArrayFreeFlags);
450 : :
451 : : /**
452 : : * g_array_unref:
453 : : * @array: (transfer full): an array
454 : : *
455 : : * Atomically decrements the reference count of @array by one. If the
456 : : * reference count drops to 0, the effect is the same as calling
457 : : * [func@GLib.Array.free] with @free_segment set to true. This function is
458 : : * thread-safe and may be called from any thread.
459 : : *
460 : : * Since: 2.22
461 : : */
462 : : void
463 : 175 : g_array_unref (GArray *array)
464 : : {
465 : 175 : GRealArray *rarray = (GRealArray*) array;
466 : 175 : g_return_if_fail (array);
467 : :
468 : 175 : if (g_atomic_ref_count_dec (&rarray->ref_count))
469 : 171 : array_free (rarray, FREE_SEGMENT);
470 : : }
471 : :
472 : : /**
473 : : * g_array_get_element_size:
474 : : * @array: an array
475 : : *
476 : : * Gets the size of the elements in @array.
477 : : *
478 : : * Returns: The size of each element, in bytes
479 : : *
480 : : * Since: 2.22
481 : : */
482 : : guint
483 : 1 : g_array_get_element_size (GArray *array)
484 : : {
485 : 1 : GRealArray *rarray = (GRealArray*) array;
486 : :
487 : 1 : g_return_val_if_fail (array, 0);
488 : :
489 : 1 : return rarray->elt_size;
490 : : }
491 : :
492 : : /**
493 : : * g_array_free:
494 : : * @array: (transfer full): an array
495 : : * @free_segment: if true, the actual element data is freed as well
496 : : *
497 : : * Frees the memory allocated for the `GArray`. If @free_segment is
498 : : * true it frees the memory block holding the elements as well. Pass
499 : : * false if you want to free the `GArray` wrapper but preserve the
500 : : * underlying array for use elsewhere. If the reference count of
501 : : * @array is greater than one, the `GArray` wrapper is preserved but
502 : : * the size of @array will be set to zero.
503 : : *
504 : : * If array contents point to dynamically-allocated memory, they should
505 : : * be freed separately if @free_segment is true and no @clear_func
506 : : * function has been set for @array.
507 : : *
508 : : * This function is not thread-safe. If using a `GArray` from multiple
509 : : * threads, use only the atomic [func@GLib.Array.ref] and
510 : : * [func@GLib.Array.unref] functions.
511 : : *
512 : : * Returns: The allocated element data if @free_segment is false, otherwise
513 : : * `NULL`
514 : : */
515 : : gchar*
516 : 8568 : g_array_free (GArray *farray,
517 : : gboolean free_segment)
518 : : {
519 : 8568 : GRealArray *array = (GRealArray*) farray;
520 : : ArrayFreeFlags flags;
521 : :
522 : 8568 : g_return_val_if_fail (array, NULL);
523 : :
524 : 8568 : flags = (free_segment ? FREE_SEGMENT : 0);
525 : :
526 : : /* if others are holding a reference, preserve the wrapper but do free/return the data */
527 : 8568 : if (!g_atomic_ref_count_dec (&array->ref_count))
528 : 2 : flags |= PRESERVE_WRAPPER;
529 : :
530 : 8568 : return array_free (array, flags);
531 : : }
532 : :
533 : : static gchar *
534 : 8739 : array_free (GRealArray *array,
535 : : ArrayFreeFlags flags)
536 : : {
537 : : gchar *segment;
538 : :
539 : 8739 : if (flags & FREE_SEGMENT)
540 : : {
541 : 8153 : if (array->clear_func != NULL)
542 : : {
543 : : guint i;
544 : :
545 : 125 : for (i = 0; i < array->len; i++)
546 : 114 : array->clear_func (g_array_elt_pos (array, i));
547 : : }
548 : :
549 : 8153 : g_free (array->data);
550 : 8153 : segment = NULL;
551 : : }
552 : : else
553 : 586 : segment = (gchar*) array->data;
554 : :
555 : 8739 : if (flags & PRESERVE_WRAPPER)
556 : : {
557 : 2 : array->data = NULL;
558 : 2 : array->len = 0;
559 : 2 : array->elt_capacity = 0;
560 : : }
561 : : else
562 : : {
563 : 8737 : g_slice_free1 (sizeof (GRealArray), array);
564 : : }
565 : :
566 : 8739 : return segment;
567 : : }
568 : :
569 : : /**
570 : : * g_array_append_vals:
571 : : * @array: an array
572 : : * @data: (nullable): a pointer to the elements to append to the end of the array
573 : : * @len: the number of elements to append
574 : : *
575 : : * Adds @len elements onto the end of the array.
576 : : *
577 : : * @data may be `NULL` if (and only if) @len is zero. If @len is zero, this
578 : : * function is a no-op.
579 : : *
580 : : * Returns: (transfer none): The `GArray`
581 : : */
582 : : /**
583 : : * g_array_append_val:
584 : : * @a: an array
585 : : * @v: the value to append to the #GArray
586 : : *
587 : : * Adds the value on to the end of the array. The array will grow in
588 : : * size automatically if necessary.
589 : : *
590 : : * `g_array_append_val()` is a macro which uses a reference to the value
591 : : * parameter @v. This means that you cannot use it with literal values
592 : : * such as `"27"`. You must use variables.
593 : : *
594 : : * Returns: (transfer none): The `GArray`
595 : : */
596 : : GArray*
597 : 277760 : g_array_append_vals (GArray *farray,
598 : : gconstpointer data,
599 : : guint len)
600 : : {
601 : 277760 : GRealArray *array = (GRealArray*) farray;
602 : :
603 : 277760 : g_return_val_if_fail (array, NULL);
604 : :
605 : 277759 : if (len == 0)
606 : 5 : return farray;
607 : :
608 : 277754 : g_array_maybe_expand (array, len);
609 : :
610 : 277754 : memcpy (g_array_elt_pos (array, array->len), data,
611 : 277754 : g_array_elt_len (array, len));
612 : :
613 : 277754 : array->len += len;
614 : :
615 : 277754 : g_array_zero_terminate (array);
616 : :
617 : 277754 : return farray;
618 : : }
619 : :
620 : : /**
621 : : * g_array_prepend_vals:
622 : : * @array: an array
623 : : * @data: (nullable): a pointer to the elements to prepend to the start of the array
624 : : * @len: the number of elements to prepend, which may be zero
625 : : *
626 : : * Adds @len elements onto the start of the array.
627 : : *
628 : : * @data may be `NULL` if (and only if) @len is zero. If @len is zero, this
629 : : * function is a no-op.
630 : : *
631 : : * This operation is slower than [func@GLib.Array.append_vals] since the
632 : : * existing elements in the array have to be moved to make space for
633 : : * the new elements.
634 : : *
635 : : * Returns: (transfer none): The `GArray`
636 : : */
637 : : /**
638 : : * g_array_prepend_val:
639 : : * @a: an array
640 : : * @v: the value to prepend to the #GArray
641 : : *
642 : : * Adds the value on to the start of the array. The array will grow in
643 : : * size automatically if necessary.
644 : : *
645 : : * This operation is slower than [func@GLib.array_append_val] since the
646 : : * existing elements in the array have to be moved to make space for
647 : : * the new element.
648 : : *
649 : : * `g_array_prepend_val()` is a macro which uses a reference to the value
650 : : * parameter @v. This means that you cannot use it with literal values
651 : : * such as `"27"`. You must use variables.
652 : : *
653 : : * Returns: (transfer none): The `GArray`
654 : : */
655 : : GArray*
656 : 10524 : g_array_prepend_vals (GArray *farray,
657 : : gconstpointer data,
658 : : guint len)
659 : : {
660 : 10524 : GRealArray *array = (GRealArray*) farray;
661 : :
662 : 10524 : g_return_val_if_fail (array, NULL);
663 : :
664 : 10523 : if (len == 0)
665 : 8 : return farray;
666 : :
667 : 10515 : g_array_maybe_expand (array, len);
668 : :
669 : 10515 : memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0),
670 : 10515 : g_array_elt_len (array, array->len));
671 : :
672 : 10515 : memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
673 : :
674 : 10515 : array->len += len;
675 : :
676 : 10515 : g_array_zero_terminate (array);
677 : :
678 : 10515 : return farray;
679 : : }
680 : :
681 : : /**
682 : : * g_array_insert_vals:
683 : : * @array: an array
684 : : * @index_: the index to place the elements at
685 : : * @data: (nullable): a pointer to the elements to insert
686 : : * @len: the number of elements to insert
687 : : *
688 : : * Inserts @len elements into a `GArray` at the given index.
689 : : *
690 : : * If @index_ is greater than the array’s current length, the array is expanded.
691 : : * The elements between the old end of the array and the newly inserted elements
692 : : * will be initialised to zero if the array was configured to clear elements;
693 : : * otherwise their values will be undefined.
694 : : *
695 : : * If @index_ is less than the array’s current length, new entries will be
696 : : * inserted into the array, and the existing entries above @index_ will be moved
697 : : * upwards.
698 : : *
699 : : * @data may be `NULL` if (and only if) @len is zero. If @len is zero, this
700 : : * function is a no-op.
701 : : *
702 : : * Returns: The `GArray`
703 : : */
704 : : /**
705 : : * g_array_insert_val:
706 : : * @a: an array
707 : : * @i: the index to place the element at
708 : : * @v: the value to insert into the array
709 : : *
710 : : * Inserts an element into an array at the given index.
711 : : *
712 : : * `g_array_insert_val()` is a macro which uses a reference to the value
713 : : * parameter @v. This means that you cannot use it with literal values
714 : : * such as `"27"`. You must use variables.
715 : : *
716 : : * Returns: (transfer none): The `GArray`
717 : : */
718 : : GArray*
719 : 6669 : g_array_insert_vals (GArray *farray,
720 : : guint index_,
721 : : gconstpointer data,
722 : : guint len)
723 : : {
724 : 6669 : GRealArray *array = (GRealArray*) farray;
725 : :
726 : 6669 : g_return_val_if_fail (array, NULL);
727 : :
728 : 6669 : if (len == 0)
729 : 8 : return farray;
730 : :
731 : : /* Is the index off the end of the array, and hence do we need to over-allocate
732 : : * and clear some elements? */
733 : 6661 : if (index_ >= array->len)
734 : : {
735 : 3015 : g_array_maybe_expand (array, index_ - array->len + len);
736 : 3015 : return g_array_append_vals (g_array_set_size (farray, index_), data, len);
737 : : }
738 : :
739 : 3646 : g_array_maybe_expand (array, len);
740 : :
741 : 3646 : memmove (g_array_elt_pos (array, len + index_),
742 : 3646 : g_array_elt_pos (array, index_),
743 : 3646 : g_array_elt_len (array, array->len - index_));
744 : :
745 : 3646 : memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len));
746 : :
747 : 3646 : array->len += len;
748 : :
749 : 3646 : g_array_zero_terminate (array);
750 : :
751 : 3646 : return farray;
752 : : }
753 : :
754 : : /**
755 : : * g_array_set_size:
756 : : * @array: an array
757 : : * @length: the new size of the #GArray
758 : : *
759 : : * Sets the size of the array, expanding it if necessary. If the array
760 : : * was created with @clear_ set to true, the new elements are set to 0.
761 : : *
762 : : * Returns: (transfer none): The `GArray`
763 : : */
764 : : GArray*
765 : 6452 : g_array_set_size (GArray *farray,
766 : : guint length)
767 : : {
768 : 6452 : GRealArray *array = (GRealArray*) farray;
769 : :
770 : 6452 : g_return_val_if_fail (array, NULL);
771 : :
772 : 6451 : if (length > array->len)
773 : : {
774 : 2080 : g_array_maybe_expand (array, length - array->len);
775 : :
776 : 2080 : if (array->clear)
777 : 2071 : g_array_elt_zero (array, array->len, length - array->len);
778 : : }
779 : 4371 : else if (length < array->len)
780 : 43 : g_array_remove_range (farray, length, array->len - length);
781 : :
782 : 6451 : array->len = length;
783 : :
784 : 6451 : if (G_LIKELY (array->data != NULL))
785 : 6450 : g_array_zero_terminate (array);
786 : :
787 : 6451 : return farray;
788 : : }
789 : :
790 : : /**
791 : : * g_array_remove_index:
792 : : * @array: an array
793 : : * @index_: the index of the element to remove
794 : : *
795 : : * Removes the element at the given index from a `GArray`. The following
796 : : * elements are moved down one place.
797 : : *
798 : : * Returns: (transfer none): The `GArray`
799 : : */
800 : : GArray*
801 : 133 : g_array_remove_index (GArray *farray,
802 : : guint index_)
803 : : {
804 : 133 : GRealArray* array = (GRealArray*) farray;
805 : :
806 : 133 : g_return_val_if_fail (array, NULL);
807 : :
808 : 132 : g_return_val_if_fail (index_ < array->len, NULL);
809 : :
810 : 132 : if (array->clear_func != NULL)
811 : 1 : array->clear_func (g_array_elt_pos (array, index_));
812 : :
813 : 132 : if (index_ != array->len - 1)
814 : 32 : memmove (g_array_elt_pos (array, index_),
815 : 32 : g_array_elt_pos (array, index_ + 1),
816 : 32 : g_array_elt_len (array, array->len - index_ - 1));
817 : :
818 : 132 : array->len -= 1;
819 : :
820 : 132 : if (G_UNLIKELY (g_mem_gc_friendly))
821 : 132 : g_array_elt_zero (array, array->len, 1);
822 : : else
823 : 0 : g_array_zero_terminate (array);
824 : :
825 : 132 : return farray;
826 : : }
827 : :
828 : : /**
829 : : * g_array_remove_index_fast:
830 : : * @array: an array
831 : : * @index_: the index of the element to remove
832 : : *
833 : : * Removes the element at the given index from a `GArray`. The last
834 : : * element in the array is used to fill in the space, so this function
835 : : * does not preserve the order of the `GArray`. But it is faster than
836 : : * [func@GLib.Array.remove_index].
837 : : *
838 : : * Returns: (transfer none): The `GArray`
839 : : */
840 : : GArray*
841 : 22 : g_array_remove_index_fast (GArray *farray,
842 : : guint index_)
843 : : {
844 : 22 : GRealArray* array = (GRealArray*) farray;
845 : :
846 : 22 : g_return_val_if_fail (array, NULL);
847 : :
848 : 21 : g_return_val_if_fail (index_ < array->len, NULL);
849 : :
850 : 21 : if (array->clear_func != NULL)
851 : 1 : array->clear_func (g_array_elt_pos (array, index_));
852 : :
853 : 21 : if (index_ != array->len - 1)
854 : 21 : memcpy (g_array_elt_pos (array, index_),
855 : 21 : g_array_elt_pos (array, array->len - 1),
856 : 21 : g_array_elt_len (array, 1));
857 : :
858 : 21 : array->len -= 1;
859 : :
860 : 21 : if (G_UNLIKELY (g_mem_gc_friendly))
861 : 21 : g_array_elt_zero (array, array->len, 1);
862 : : else
863 : 0 : g_array_zero_terminate (array);
864 : :
865 : 21 : return farray;
866 : : }
867 : :
868 : : /**
869 : : * g_array_remove_range:
870 : : * @array: an array
871 : : * @index_: the index of the first element to remove
872 : : * @length: the number of elements to remove
873 : : *
874 : : * Removes the given number of elements starting at the given index
875 : : * from a `GArray`. The following elements are moved to close the gap.
876 : : *
877 : : * Returns: (transfer none): The `GArray`
878 : : *
879 : : * Since: 2.4
880 : : */
881 : : GArray*
882 : 60 : g_array_remove_range (GArray *farray,
883 : : guint index_,
884 : : guint length)
885 : : {
886 : 60 : GRealArray *array = (GRealArray*) farray;
887 : :
888 : 60 : g_return_val_if_fail (array, NULL);
889 : 60 : g_return_val_if_fail (index_ <= array->len, NULL);
890 : 60 : g_return_val_if_fail (index_ <= G_MAXUINT - length, NULL);
891 : 60 : g_return_val_if_fail (index_ + length <= array->len, NULL);
892 : :
893 : 60 : if (length == 0)
894 : 6 : return farray;
895 : :
896 : 54 : if (array->clear_func != NULL)
897 : : {
898 : : guint i;
899 : :
900 : 24 : for (i = 0; i < length; i++)
901 : 22 : array->clear_func (g_array_elt_pos (array, index_ + i));
902 : : }
903 : :
904 : 54 : if (index_ + length != array->len)
905 : 6 : memmove (g_array_elt_pos (array, index_),
906 : 6 : g_array_elt_pos (array, index_ + length),
907 : 6 : g_array_elt_len (array, array->len - (index_ + length)));
908 : :
909 : 54 : array->len -= length;
910 : 54 : if (G_UNLIKELY (g_mem_gc_friendly))
911 : 54 : g_array_elt_zero (array, array->len, length);
912 : : else
913 : 0 : g_array_zero_terminate (array);
914 : :
915 : 54 : return farray;
916 : : }
917 : :
918 : : /**
919 : : * g_array_sort:
920 : : * @array: an array
921 : : * @compare_func: (scope call): a comparison function
922 : : *
923 : : * Sorts a `GArray` using @compare_func which should be a `qsort()`-style
924 : : * comparison function (returns less than zero for first arg is less
925 : : * than second arg, zero for equal, greater zero if first arg is
926 : : * greater than second arg).
927 : : *
928 : : * This is guaranteed to be a stable sort since version 2.32.
929 : : */
930 : : void
931 : 1291 : g_array_sort (GArray *farray,
932 : : GCompareFunc compare_func)
933 : : {
934 : 1291 : GRealArray *array = (GRealArray*) farray;
935 : :
936 : 1291 : g_return_if_fail (array != NULL);
937 : :
938 : : /* Don't use qsort as we want a guaranteed stable sort */
939 : 1291 : if (array->len > 0)
940 : 1287 : g_sort_array (array->data,
941 : 1287 : array->len,
942 : 1287 : array->elt_size,
943 : : (GCompareDataFunc) compare_func,
944 : : NULL);
945 : : }
946 : :
947 : : /**
948 : : * g_array_sort_with_data:
949 : : * @array: an array
950 : : * @compare_func: (scope call): a comparison function
951 : : * @user_data: the data to pass to @compare_func
952 : : *
953 : : * Like [func@GLib.Array.sort], but the comparison function receives an extra
954 : : * user data argument.
955 : : *
956 : : * This is guaranteed to be a stable sort since version 2.32.
957 : : *
958 : : * There used to be a comment here about making the sort stable by
959 : : * using the addresses of the elements in the comparison function.
960 : : * This did not actually work, so any such code should be removed.
961 : : */
962 : : void
963 : 9 : g_array_sort_with_data (GArray *farray,
964 : : GCompareDataFunc compare_func,
965 : : gpointer user_data)
966 : : {
967 : 9 : GRealArray *array = (GRealArray*) farray;
968 : :
969 : 9 : g_return_if_fail (array != NULL);
970 : :
971 : 9 : if (array->len > 0)
972 : 5 : g_sort_array (array->data,
973 : 5 : array->len,
974 : 5 : array->elt_size,
975 : : compare_func,
976 : : user_data);
977 : : }
978 : :
979 : : /**
980 : : * g_array_binary_search:
981 : : * @array: an array
982 : : * @target: a pointer to the item to look up
983 : : * @compare_func: (scope call): a comparison function to locate @target
984 : : * @out_match_index: (optional) (out): the return location
985 : : * for the index of the element, if found
986 : : *
987 : : * Checks whether @target exists in @array by performing a binary
988 : : * search based on the given comparison function @compare_func which
989 : : * gets pointers to items as arguments. If the element is found, true
990 : : * is returned and the element’s index is returned in @out_match_index
991 : : * (if non-`NULL`). Otherwise, false is returned and @out_match_index
992 : : * is undefined. This search is using a binary search, so the @array must
993 : : * absolutely be sorted to return a correct result (if not, the function may
994 : : * produce false-negative).
995 : : *
996 : : * This example defines a comparison function and searches an element in a
997 : : * `GArray`:
998 : : * ```c
999 : : * static gint
1000 : : * cmpint (gconstpointer a, gconstpointer b)
1001 : : * {
1002 : : * const gint *_a = a;
1003 : : * const gint *_b = b;
1004 : : *
1005 : : * return *_a - *_b;
1006 : : * }
1007 : : * ...
1008 : : * gint i = 424242;
1009 : : * guint matched_index;
1010 : : * gboolean result = g_array_binary_search (garray, &i, cmpint, &matched_index);
1011 : : * ...
1012 : : * ```
1013 : : *
1014 : : * Returns: true if @target is one of the elements of @array; false otherwise
1015 : : *
1016 : : * Since: 2.62
1017 : : */
1018 : : gboolean
1019 : 20024 : g_array_binary_search (GArray *array,
1020 : : gconstpointer target,
1021 : : GCompareFunc compare_func,
1022 : : guint *out_match_index)
1023 : : {
1024 : 20024 : gboolean result = FALSE;
1025 : 20024 : GRealArray *_array = (GRealArray *) array;
1026 : 20024 : guint left, middle = 0, right;
1027 : : gint val;
1028 : :
1029 : 20024 : g_return_val_if_fail (_array != NULL, FALSE);
1030 : 20023 : g_return_val_if_fail (compare_func != NULL, FALSE);
1031 : :
1032 : 20022 : if (G_LIKELY(_array->len))
1033 : : {
1034 : 20021 : left = 0;
1035 : 20021 : right = _array->len - 1;
1036 : :
1037 : 247363 : while (left <= right)
1038 : : {
1039 : 247355 : middle = left + (right - left) / 2;
1040 : :
1041 : 247355 : val = compare_func (g_array_elt_pos (_array, middle), target);
1042 : 247355 : if (val == 0)
1043 : : {
1044 : 20006 : result = TRUE;
1045 : 20006 : break;
1046 : : }
1047 : 227349 : else if (val < 0)
1048 : 118082 : left = middle + 1;
1049 : 109267 : else if (/* val > 0 && */ middle > 0)
1050 : 109260 : right = middle - 1;
1051 : : else
1052 : 7 : break; /* element not found */
1053 : : }
1054 : : }
1055 : :
1056 : 20022 : if (result && out_match_index != NULL)
1057 : 10000 : *out_match_index = middle;
1058 : :
1059 : 20022 : return result;
1060 : : }
1061 : :
1062 : : static void
1063 : 297293 : g_array_maybe_expand (GRealArray *array,
1064 : : guint len)
1065 : : {
1066 : : guint max_len, want_len;
1067 : :
1068 : : /* The maximum array length is derived from following constraints:
1069 : : * - The number of bytes must fit into a gsize / 2.
1070 : : * - The number of elements must fit into guint.
1071 : : * - zero terminated arrays must leave space for the terminating element
1072 : : */
1073 : 297293 : max_len = MIN (G_MAXSIZE / 2 / array->elt_size, G_MAXUINT) - array->zero_terminated;
1074 : :
1075 : : /* Detect potential overflow */
1076 : 297293 : if G_UNLIKELY ((max_len - array->len) < len)
1077 : 0 : g_error ("adding %u to array would overflow", len);
1078 : :
1079 : 297293 : want_len = array->len + len + array->zero_terminated;
1080 : 297293 : if (want_len > array->elt_capacity)
1081 : : {
1082 : 8687 : gsize want_alloc = g_nearest_pow (g_array_elt_len (array, want_len));
1083 : 8687 : g_assert (want_alloc >= g_array_elt_len (array, want_len));
1084 : 8687 : want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
1085 : :
1086 : 8687 : array->data = g_realloc (array->data, want_alloc);
1087 : :
1088 : 8687 : if (G_UNLIKELY (g_mem_gc_friendly))
1089 : 7502 : memset (g_array_elt_pos (array, array->elt_capacity), 0,
1090 : 7502 : g_array_elt_len (array, want_len - array->elt_capacity));
1091 : :
1092 : 8687 : array->elt_capacity = MIN (want_alloc / array->elt_size, G_MAXUINT);
1093 : : }
1094 : 297293 : }
1095 : :
1096 : : typedef struct _GRealPtrArray GRealPtrArray;
1097 : :
1098 : : /**
1099 : : * GPtrArray: (copy-func g_ptr_array_ref) (free-func g_ptr_array_unref)
1100 : : * @pdata: a pointer to the array of pointers, which may be moved when the
1101 : : * array grows
1102 : : * @len: the number of pointers in the array
1103 : : *
1104 : : * Contains the public fields of a `GPtrArray`.
1105 : : */
1106 : : struct _GRealPtrArray
1107 : : {
1108 : : gpointer *pdata;
1109 : : guint len;
1110 : : guint alloc;
1111 : : gatomicrefcount ref_count;
1112 : : guint8 null_terminated : 1; /* always either 0 or 1, so it can be added to array lengths */
1113 : : GDestroyNotify element_free_func;
1114 : : };
1115 : :
1116 : : /**
1117 : : * g_ptr_array_index:
1118 : : * @array: a pointer array
1119 : : * @index_: the index of the pointer to return
1120 : : *
1121 : : * Returns the pointer at the given index of the pointer array.
1122 : : *
1123 : : * This does not perform bounds checking on the given @index_,
1124 : : * so you are responsible for checking it against the array length.
1125 : : *
1126 : : * Returns: (transfer none): The pointer at the given index
1127 : : */
1128 : :
1129 : : static void g_ptr_array_maybe_expand (GRealPtrArray *array,
1130 : : guint len);
1131 : :
1132 : : static void
1133 : 1746943 : ptr_array_maybe_null_terminate (GRealPtrArray *rarray)
1134 : : {
1135 : 1746943 : if (G_UNLIKELY (rarray->null_terminated))
1136 : 51058 : rarray->pdata[rarray->len] = NULL;
1137 : 1746943 : }
1138 : :
1139 : : static GPtrArray *
1140 : 156520 : ptr_array_new (guint reserved_size,
1141 : : GDestroyNotify element_free_func,
1142 : : gboolean null_terminated)
1143 : : {
1144 : : GRealPtrArray *array;
1145 : :
1146 : 156520 : array = g_slice_new (GRealPtrArray);
1147 : :
1148 : 156520 : array->pdata = NULL;
1149 : 156520 : array->len = 0;
1150 : 156520 : array->alloc = 0;
1151 : 156520 : array->null_terminated = null_terminated ? 1 : 0;
1152 : 156520 : array->element_free_func = element_free_func;
1153 : :
1154 : 156520 : g_atomic_ref_count_init (&array->ref_count);
1155 : :
1156 : 156520 : if (reserved_size != 0)
1157 : : {
1158 : 879 : g_ptr_array_maybe_expand (array, reserved_size);
1159 : 879 : g_assert (array->pdata != NULL);
1160 : :
1161 : 879 : if (null_terminated)
1162 : : {
1163 : : /* don't use ptr_array_maybe_null_terminate(). It helps the compiler
1164 : : * to see when @null_terminated is false and thereby inline
1165 : : * ptr_array_new() and possibly remove the code entirely. */
1166 : 129 : array->pdata[0] = NULL;
1167 : : }
1168 : : }
1169 : :
1170 : 156520 : return (GPtrArray *) array;
1171 : : }
1172 : :
1173 : : /**
1174 : : * g_ptr_array_new:
1175 : : *
1176 : : * Creates a new `GPtrArray` with a reference count of 1.
1177 : : *
1178 : : * Returns: (transfer full): The new `GPtrArray`
1179 : : */
1180 : : GPtrArray*
1181 : 153878 : g_ptr_array_new (void)
1182 : : {
1183 : 153878 : return ptr_array_new (0, NULL, FALSE);
1184 : : }
1185 : :
1186 : : /**
1187 : : * g_ptr_array_new_take: (skip)
1188 : : * @data: (array length=len) (transfer full) (nullable): an array of pointers
1189 : : * @len: the number of pointers in @data
1190 : : * @element_free_func: (nullable): a function to free elements on @array
1191 : : * destruction
1192 : : *
1193 : : * Creates a new `GPtrArray` with @data as pointers, @len as length and a
1194 : : * reference count of 1.
1195 : : *
1196 : : * This avoids having to copy such data manually.
1197 : : * After this call, @data belongs to the `GPtrArray` and may no longer be
1198 : : * modified by the caller. The memory of @data has to be dynamically
1199 : : * allocated and will eventually be freed with [func@GLib.free].
1200 : : *
1201 : : * It also sets @element_free_func for freeing each element when the array is
1202 : : * destroyed either via [func@GLib.PtrArray.unref], when
1203 : : * [func@GLib.PtrArray.free] is called with @free_segment set to true or when
1204 : : * removing elements.
1205 : : *
1206 : : * Do not use it if @len is greater than [`G_MAXUINT`](types.html#guint).
1207 : : * `GPtrArray` stores the length of its data in `guint`, which may be shorter
1208 : : * than `gsize`.
1209 : : *
1210 : : * Returns: (transfer full): The new `GPtrArray`
1211 : : *
1212 : : * Since: 2.76
1213 : : */
1214 : : GPtrArray *
1215 : 97 : g_ptr_array_new_take (gpointer *data,
1216 : : gsize len,
1217 : : GDestroyNotify element_free_func)
1218 : : {
1219 : : GPtrArray *array;
1220 : : GRealPtrArray *rarray;
1221 : :
1222 : 97 : g_return_val_if_fail (data != NULL || len == 0, NULL);
1223 : 96 : g_return_val_if_fail (len <= G_MAXUINT, NULL);
1224 : :
1225 : 95 : array = ptr_array_new (0, element_free_func, FALSE);
1226 : 95 : rarray = (GRealPtrArray *)array;
1227 : :
1228 : 95 : rarray->pdata = g_steal_pointer (&data);
1229 : 95 : rarray->len = len;
1230 : 95 : rarray->alloc = len;
1231 : :
1232 : 95 : return array;
1233 : : }
1234 : :
1235 : : /**
1236 : : * g_ptr_array_new_take_null_terminated: (skip)
1237 : : * @data: (array zero-terminated=1) (transfer full) (nullable): an array
1238 : : * of pointers, `NULL` terminated
1239 : : * @element_free_func: (nullable): a function to free elements on @array
1240 : : * destruction
1241 : : *
1242 : : * Creates a new `GPtrArray` with @data as pointers, computing the length of it
1243 : : * and setting the reference count to 1.
1244 : : *
1245 : : * This avoids having to copy such data manually.
1246 : : * After this call, @data belongs to the `GPtrArray` and may no longer be
1247 : : * modified by the caller. The memory of @data has to be dynamically
1248 : : * allocated and will eventually be freed with [func@GLib.free].
1249 : : *
1250 : : * The length is calculated by iterating through @data until the first `NULL`
1251 : : * element is found.
1252 : : *
1253 : : * It also sets @element_free_func for freeing each element when the array is
1254 : : * destroyed either via [func@GLib.PtrArray.unref], when
1255 : : * [func@GLib.PtrArray.free] is called with @free_segment set to true or when
1256 : : * removing elements.
1257 : : *
1258 : : * Do not use it if the @data length is greater than
1259 : : * [`G_MAXUINT`](types.html#guint). `GPtrArray` stores the length of its data
1260 : : * in `guint`, which may be shorter than `gsize`.
1261 : : *
1262 : : * Returns: (transfer full): The new `GPtrArray`
1263 : : *
1264 : : * Since: 2.76
1265 : : */
1266 : : GPtrArray *
1267 : 91 : g_ptr_array_new_take_null_terminated (gpointer *data,
1268 : : GDestroyNotify element_free_func)
1269 : : {
1270 : : GRealPtrArray *rarray;
1271 : : GPtrArray *array;
1272 : 91 : gsize len = 0;
1273 : :
1274 : 91 : if (data != NULL)
1275 : : {
1276 : 20180 : for (gsize i = 0; data[i] != NULL; ++i)
1277 : 20090 : len += 1;
1278 : : }
1279 : :
1280 : 91 : g_return_val_if_fail (len < G_MAXUINT, NULL);
1281 : :
1282 : 91 : array = g_ptr_array_new_take (g_steal_pointer (&data), len, element_free_func);
1283 : 91 : rarray = (GRealPtrArray *) array;
1284 : 91 : rarray->null_terminated = TRUE;
1285 : 91 : if (G_LIKELY (rarray->pdata != NULL))
1286 : 90 : rarray->alloc = len + 1;
1287 : :
1288 : 91 : return array;
1289 : : }
1290 : :
1291 : : static GPtrArray *
1292 : 8 : ptr_array_new_from_array (gpointer *data,
1293 : : gsize len,
1294 : : GCopyFunc copy_func,
1295 : : gpointer copy_func_user_data,
1296 : : GDestroyNotify element_free_func,
1297 : : gboolean null_terminated)
1298 : : {
1299 : : GPtrArray *array;
1300 : : GRealPtrArray *rarray;
1301 : :
1302 : 8 : g_assert (data != NULL || len == 0);
1303 : 8 : g_assert (len <= G_MAXUINT - (null_terminated ? 1 : 0));
1304 : :
1305 : 8 : array = ptr_array_new (len, element_free_func, null_terminated);
1306 : 8 : rarray = (GRealPtrArray *)array;
1307 : :
1308 : 8 : if (copy_func != NULL)
1309 : : {
1310 : 20002 : for (gsize i = 0; i < len; i++)
1311 : 20000 : rarray->pdata[i] = copy_func (data[i], copy_func_user_data);
1312 : : }
1313 : 6 : else if (len != 0)
1314 : : {
1315 : 3 : memcpy (rarray->pdata, data, len * sizeof (gpointer));
1316 : : }
1317 : :
1318 : 8 : if (null_terminated && rarray->pdata != NULL)
1319 : 3 : rarray->pdata[len] = NULL;
1320 : :
1321 : 8 : rarray->len = len;
1322 : :
1323 : 8 : return array;
1324 : : }
1325 : :
1326 : : /**
1327 : : * g_ptr_array_new_from_array: (skip)
1328 : : * @data: (array length=len) (transfer none) (nullable): an array of pointers
1329 : : * @len: the number of pointers in @data
1330 : : * @copy_func: (nullable): a copy function used to copy every element in the
1331 : : * array
1332 : : * @copy_func_user_data: the user data passed to @copy_func
1333 : : * @element_free_func: (nullable): a function to free elements on @array
1334 : : * destruction
1335 : : *
1336 : : * Creates a new `GPtrArray`, copying @len pointers from @data, and setting
1337 : : * the array’s reference count to 1.
1338 : : *
1339 : : * This avoids having to manually add each element one by one.
1340 : : *
1341 : : * If @copy_func is provided, then it is used to copy each element before
1342 : : * adding them to the new array. If it is `NULL` then the pointers are copied
1343 : : * directly.
1344 : : *
1345 : : * It also sets @element_free_func for freeing each element when the array is
1346 : : * destroyed either via [func@GLib.PtrArray.unref], when
1347 : : * [func@GLib.PtrArray.free] is called with @free_segment set to true or when
1348 : : * removing elements.
1349 : : *
1350 : : * Do not use it if @len is greater than [`G_MAXUINT`](types.html#guint).
1351 : : * `GPtrArray` stores the length of its data in `guint`, which may be shorter
1352 : : * than `gsize`.
1353 : : *
1354 : : * Returns: (transfer full): The new `GPtrArray`
1355 : : *
1356 : : * Since: 2.76
1357 : : */
1358 : : GPtrArray *
1359 : 5 : g_ptr_array_new_from_array (gpointer *data,
1360 : : gsize len,
1361 : : GCopyFunc copy_func,
1362 : : gpointer copy_func_user_data,
1363 : : GDestroyNotify element_free_func)
1364 : : {
1365 : 5 : g_return_val_if_fail (data != NULL || len == 0, NULL);
1366 : 4 : g_return_val_if_fail (len <= G_MAXUINT, NULL);
1367 : :
1368 : 3 : return ptr_array_new_from_array (
1369 : : data, len, copy_func, copy_func_user_data, element_free_func, FALSE);
1370 : : }
1371 : :
1372 : : /**
1373 : : * g_ptr_array_new_from_null_terminated_array: (skip)
1374 : : * @data: (array zero-terminated=1) (transfer none) (nullable): an array of
1375 : : * pointers, `NULL` terminated
1376 : : * @copy_func: (nullable): a copy function used to copy every element in the
1377 : : * array
1378 : : * @copy_func_user_data: the user data passed to @copy_func
1379 : : * @element_free_func: (nullable): a function to free elements on @array
1380 : : * destruction
1381 : : *
1382 : : * Creates a new `GPtrArray` copying the pointers from @data after having
1383 : : * computed the length of it and with a reference count of 1.
1384 : : * This avoids having to manually add each element one by one.
1385 : : * If @copy_func is provided, then it is used to copy the data in the new
1386 : : * array.
1387 : : * It also sets @element_free_func for freeing each element when the array is
1388 : : * destroyed either via [func@GLib.PtrArray.unref], when
1389 : : * [func@GLib.PtrArray.free] is called with @free_segment set to true or when
1390 : : * removing elements.
1391 : : *
1392 : : * Do not use it if the @data has more than [`G_MAXUINT`](types.html#guint)
1393 : : * elements. `GPtrArray` stores the length of its data in `guint`, which may be
1394 : : * shorter than `gsize`.
1395 : : *
1396 : : * Returns: (transfer full): The new `GPtrArray`
1397 : : *
1398 : : * Since: 2.76
1399 : : */
1400 : : GPtrArray *
1401 : 5 : g_ptr_array_new_from_null_terminated_array (gpointer *data,
1402 : : GCopyFunc copy_func,
1403 : : gpointer copy_func_user_data,
1404 : : GDestroyNotify element_free_func)
1405 : : {
1406 : 5 : gsize len = 0;
1407 : :
1408 : 5 : if (data != NULL)
1409 : : {
1410 : 20008 : for (gsize i = 0; data[i] != NULL; ++i)
1411 : 20004 : len += 1;
1412 : : }
1413 : :
1414 : 5 : g_assert (data != NULL || len == 0);
1415 : 5 : g_return_val_if_fail (len < G_MAXUINT, NULL);
1416 : :
1417 : 5 : return ptr_array_new_from_array (
1418 : : data, len, copy_func, copy_func_user_data, element_free_func, TRUE);
1419 : : }
1420 : :
1421 : : /**
1422 : : * g_ptr_array_steal:
1423 : : * @array: a pointer array
1424 : : * @len: (optional) (out): a pointer to retrieve the number of
1425 : : * elements of the original array
1426 : : *
1427 : : * Frees the data in the array and resets the size to zero, while
1428 : : * the underlying array is preserved for use elsewhere and returned
1429 : : * to the caller.
1430 : : *
1431 : : * Note that if the array is `NULL` terminated this may still return
1432 : : * `NULL` if the length of the array was zero and pdata was not yet
1433 : : * allocated.
1434 : : *
1435 : : * Even if set, the [callback@GLib.DestroyNotify] function will never be called
1436 : : * on the current contents of the array and the caller is
1437 : : * responsible for freeing the array elements.
1438 : : *
1439 : : * An example of use:
1440 : : * ```c
1441 : : * g_autoptr(GPtrArray) chunk_buffer = g_ptr_array_new_with_free_func (g_bytes_unref);
1442 : : *
1443 : : * // Some part of your application appends a number of chunks to the pointer array.
1444 : : * g_ptr_array_add (chunk_buffer, g_bytes_new_static ("hello", 5));
1445 : : * g_ptr_array_add (chunk_buffer, g_bytes_new_static ("world", 5));
1446 : : *
1447 : : * …
1448 : : *
1449 : : * // Periodically, the chunks need to be sent as an array-and-length to some
1450 : : * // other part of the program.
1451 : : * GBytes **chunks;
1452 : : * gsize n_chunks;
1453 : : *
1454 : : * chunks = g_ptr_array_steal (chunk_buffer, &n_chunks);
1455 : : * for (gsize i = 0; i < n_chunks; i++)
1456 : : * {
1457 : : * // Do something with each chunk here, and then free them, since
1458 : : * // g_ptr_array_steal() transfers ownership of all the elements and the
1459 : : * // array to the caller.
1460 : : * …
1461 : : *
1462 : : * g_bytes_unref (chunks[i]);
1463 : : * }
1464 : : *
1465 : : * g_free (chunks);
1466 : : *
1467 : : * // After calling g_ptr_array_steal(), the pointer array can be reused for the
1468 : : * // next set of chunks.
1469 : : * g_assert (chunk_buffer->len == 0);
1470 : : * ```
1471 : : *
1472 : : * Returns: (transfer full) (nullable) (array length=len): The allocated element data.
1473 : : * This may be `NULL`if the array doesn’t have any elements (i.e. if `*len` is zero).
1474 : : *
1475 : : * Since: 2.64
1476 : : */
1477 : : gpointer *
1478 : 18783 : g_ptr_array_steal (GPtrArray *array,
1479 : : gsize *len)
1480 : : {
1481 : : GRealPtrArray *rarray;
1482 : : gpointer *segment;
1483 : :
1484 : 18783 : g_return_val_if_fail (array != NULL, NULL);
1485 : :
1486 : 18783 : rarray = (GRealPtrArray *) array;
1487 : 18783 : segment = (gpointer *) rarray->pdata;
1488 : :
1489 : 18783 : if (len != NULL)
1490 : 18201 : *len = rarray->len;
1491 : :
1492 : 18783 : rarray->pdata = NULL;
1493 : 18783 : rarray->len = 0;
1494 : 18783 : rarray->alloc = 0;
1495 : 18783 : return segment;
1496 : : }
1497 : :
1498 : : /**
1499 : : * g_ptr_array_copy:
1500 : : * @array: a pointer array to duplicate
1501 : : * @func: (scope call) (nullable): a copy function used to copy every element in the array
1502 : : * @user_data: the user data passed to the copy function @func
1503 : : *
1504 : : * Makes a full (deep) copy of a `GPtrArray`.
1505 : : *
1506 : : * @func, as a [callback@GLib.CopyFunc], takes two arguments, the data to be
1507 : : * copied
1508 : : * and a @user_data pointer. On common processor architectures, it’s safe to
1509 : : * pass `NULL` as @user_data if the copy function takes only one argument. You
1510 : : * may get compiler warnings from this though if compiling with GCC’s
1511 : : * `-Wcast-function-type` warning.
1512 : : *
1513 : : * If @func is `NULL`, then only the pointers (and not what they are
1514 : : * pointing to) are copied to the new `GPtrArray`.
1515 : : *
1516 : : * The copy of @array will have the same [callback@GLib.DestroyNotify] for its
1517 : : * elements as
1518 : : * @array. The copy will also be `NULL` terminated if (and only if) the source
1519 : : * array is.
1520 : : *
1521 : : * Returns: (transfer full): The deep copy of the initial `GPtrArray`
1522 : : *
1523 : : * Since: 2.62
1524 : : **/
1525 : : GPtrArray *
1526 : 8 : g_ptr_array_copy (GPtrArray *array,
1527 : : GCopyFunc func,
1528 : : gpointer user_data)
1529 : : {
1530 : 8 : GRealPtrArray *rarray = (GRealPtrArray *) array;
1531 : : GPtrArray *new_array;
1532 : :
1533 : 8 : g_return_val_if_fail (array != NULL, NULL);
1534 : :
1535 : 6 : new_array = ptr_array_new (0,
1536 : : rarray->element_free_func,
1537 : 6 : rarray->null_terminated);
1538 : :
1539 : 6 : if (rarray->alloc > 0)
1540 : : {
1541 : 4 : g_ptr_array_maybe_expand ((GRealPtrArray *) new_array, array->len);
1542 : :
1543 : 4 : if (array->len > 0)
1544 : : {
1545 : 4 : if (func != NULL)
1546 : : {
1547 : : guint i;
1548 : :
1549 : 202 : for (i = 0; i < array->len; i++)
1550 : 200 : new_array->pdata[i] = func (array->pdata[i], user_data);
1551 : : }
1552 : : else
1553 : : {
1554 : 2 : memcpy (new_array->pdata, array->pdata,
1555 : 2 : array->len * sizeof (*array->pdata));
1556 : : }
1557 : :
1558 : 4 : new_array->len = array->len;
1559 : : }
1560 : :
1561 : 4 : ptr_array_maybe_null_terminate ((GRealPtrArray *) new_array);
1562 : : }
1563 : :
1564 : 6 : return new_array;
1565 : : }
1566 : :
1567 : : /**
1568 : : * g_ptr_array_sized_new:
1569 : : * @reserved_size: the number of pointers preallocated
1570 : : *
1571 : : * Creates a new `GPtrArray` with @reserved_size pointers preallocated
1572 : : * and a reference count of 1. This avoids frequent reallocation, if
1573 : : * you are going to add many pointers to the array. Note however that
1574 : : * the size of the array is still 0.
1575 : : *
1576 : : * Returns: (transfer full): The new `GPtrArray`
1577 : : */
1578 : : GPtrArray*
1579 : 391 : g_ptr_array_sized_new (guint reserved_size)
1580 : : {
1581 : 391 : return ptr_array_new (reserved_size, NULL, FALSE);
1582 : : }
1583 : :
1584 : : /**
1585 : : * g_array_copy:
1586 : : * @array: an array
1587 : : *
1588 : : * Creates a shallow copy of a #GArray. If the array elements consist of
1589 : : * pointers to data, the pointers are copied but the actual data is not.
1590 : : *
1591 : : * Returns: (transfer container): The copy of @array
1592 : : *
1593 : : * Since: 2.62
1594 : : **/
1595 : : GArray *
1596 : 42 : g_array_copy (GArray *array)
1597 : : {
1598 : 42 : GRealArray *rarray = (GRealArray *) array;
1599 : : GRealArray *new_rarray;
1600 : :
1601 : 42 : g_return_val_if_fail (rarray != NULL, NULL);
1602 : :
1603 : : new_rarray =
1604 : 38 : (GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear,
1605 : : rarray->elt_size, rarray->len);
1606 : 38 : new_rarray->len = rarray->len;
1607 : 38 : if (rarray->len > 0)
1608 : 5 : memcpy (new_rarray->data, rarray->data, g_array_elt_len (rarray, rarray->len));
1609 : :
1610 : 38 : g_array_zero_terminate (new_rarray);
1611 : :
1612 : 38 : return (GArray *) new_rarray;
1613 : : }
1614 : :
1615 : : /**
1616 : : * g_ptr_array_new_with_free_func:
1617 : : * @element_free_func: (nullable): a function to free elements with
1618 : : * destroy @array
1619 : : *
1620 : : * Creates a new `GPtrArray` with a reference count of 1 and use
1621 : : * @element_free_func for freeing each element when the array is destroyed
1622 : : * either via [func@GLib.PtrArray.unref], when [func@GLib.PtrArray.free] is
1623 : : * called with @free_segment set to true or when removing elements.
1624 : : *
1625 : : * Returns: (transfer full): The new `GPtrArray`
1626 : : *
1627 : : * Since: 2.22
1628 : : */
1629 : : GPtrArray*
1630 : 1624 : g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
1631 : : {
1632 : 1624 : return ptr_array_new (0, element_free_func, FALSE);
1633 : : }
1634 : :
1635 : : /**
1636 : : * g_ptr_array_new_full:
1637 : : * @reserved_size: the number of pointers preallocated
1638 : : * @element_free_func: (nullable): a function to free elements with
1639 : : * destroy @array
1640 : : *
1641 : : * Creates a new `GPtrArray` with @reserved_size pointers preallocated
1642 : : * and a reference count of 1. This avoids frequent reallocation, if
1643 : : * you are going to add many pointers to the array. Note however that
1644 : : * the size of the array is still 0. It also sets @element_free_func
1645 : : * for freeing each element when the array is destroyed either via
1646 : : * [func@GLib.PtrArray.unref], when [func@GLib.PtrArray.free] is called with
1647 : : * @free_segment set to true or when removing elements.
1648 : : *
1649 : : * Returns: (transfer full): The new `GPtrArray`
1650 : : *
1651 : : * Since: 2.30
1652 : : */
1653 : : GPtrArray*
1654 : 358 : g_ptr_array_new_full (guint reserved_size,
1655 : : GDestroyNotify element_free_func)
1656 : : {
1657 : 358 : return ptr_array_new (reserved_size, element_free_func, FALSE);
1658 : : }
1659 : :
1660 : : /**
1661 : : * g_ptr_array_new_null_terminated:
1662 : : * @reserved_size: the number of pointers preallocated.
1663 : : * If @null_terminated is `TRUE`, the actually allocated
1664 : : * buffer size is @reserved_size plus 1, unless @reserved_size
1665 : : * is zero, in which case no initial buffer gets allocated.
1666 : : * @element_free_func: (nullable): a function to free elements during
1667 : : * destruction of @array
1668 : : * @null_terminated: if true, make the array `NULL` terminated
1669 : : *
1670 : : * Like [func@GLib.PtrArray.new_full] but also allows to set the array to
1671 : : * be `NULL` terminated. A `NULL` terminated pointer array has an
1672 : : * additional `NULL` pointer after the last element, beyond the
1673 : : * current length.
1674 : : *
1675 : : * `GPtrArray` created by other constructors are not automatically `NULL`
1676 : : * terminated.
1677 : : *
1678 : : * Note that if the @array’s length is zero and currently no
1679 : : * data array is allocated, then `pdata` will still be `NULL`.
1680 : : * `GPtrArray` will only `NULL` terminate `pdata`, if an actual
1681 : : * array is allocated. It does not guarantee that an array
1682 : : * is always allocated. In other words, if the length is zero,
1683 : : * then `pdata` may either point to a `NULL` terminated array of length
1684 : : * zero or be `NULL`.
1685 : : *
1686 : : * Returns: (transfer full): The new `GPtrArray`
1687 : : *
1688 : : * Since: 2.74
1689 : : */
1690 : : GPtrArray *
1691 : 160 : g_ptr_array_new_null_terminated (guint reserved_size,
1692 : : GDestroyNotify element_free_func,
1693 : : gboolean null_terminated)
1694 : : {
1695 : 160 : return ptr_array_new (reserved_size, element_free_func, null_terminated);
1696 : : }
1697 : :
1698 : : /**
1699 : : * g_ptr_array_set_free_func:
1700 : : * @array: a pointer array
1701 : : * @element_free_func: (nullable): a function to free elements during
1702 : : * destruction of @array
1703 : : *
1704 : : * Sets a function for freeing each element when @array is destroyed
1705 : : * either via [func@GLib.PtrArray.unref], when [func@GLib.PtrArray.free] is
1706 : : * called with @free_segment set to true or when removing elements.
1707 : : *
1708 : : * Since: 2.22
1709 : : */
1710 : : void
1711 : 76 : g_ptr_array_set_free_func (GPtrArray *array,
1712 : : GDestroyNotify element_free_func)
1713 : : {
1714 : 76 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1715 : :
1716 : 76 : g_return_if_fail (array);
1717 : :
1718 : 76 : rarray->element_free_func = element_free_func;
1719 : : }
1720 : :
1721 : : /**
1722 : : * g_ptr_array_is_null_terminated:
1723 : : * @array: a pointer array
1724 : : *
1725 : : * Checks whether the @array was constructed as `NULL`-terminated.
1726 : : *
1727 : : * This will only return true for arrays constructed by passing true to the
1728 : : * `null_terminated` argument of [func@GLib.PtrArray.new_null_terminated]. It
1729 : : * will not return true for normal arrays which have had a `NULL` element
1730 : : * appended to them.
1731 : : *
1732 : : * Returns: true if the array is made to be `NULL` terminated; false otherwise
1733 : : *
1734 : : * Since: 2.74
1735 : : */
1736 : : gboolean
1737 : 20094 : g_ptr_array_is_null_terminated (GPtrArray *array)
1738 : : {
1739 : 20094 : g_return_val_if_fail (array, FALSE);
1740 : :
1741 : 20094 : return ((GRealPtrArray *) array)->null_terminated;
1742 : : }
1743 : :
1744 : : /**
1745 : : * g_ptr_array_ref:
1746 : : * @array: a pointer array
1747 : : *
1748 : : * Atomically increments the reference count of @array by one.
1749 : : * This function is thread-safe and may be called from any thread.
1750 : : *
1751 : : * Returns: (transfer full): The passed in `GPtrArray`
1752 : : *
1753 : : * Since: 2.22
1754 : : */
1755 : : GPtrArray*
1756 : 369 : g_ptr_array_ref (GPtrArray *array)
1757 : : {
1758 : 369 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1759 : :
1760 : 369 : g_return_val_if_fail (array, NULL);
1761 : :
1762 : 369 : g_atomic_ref_count_inc (&rarray->ref_count);
1763 : :
1764 : 369 : return array;
1765 : : }
1766 : :
1767 : : static gpointer *ptr_array_free (GPtrArray *, ArrayFreeFlags);
1768 : :
1769 : : /**
1770 : : * g_ptr_array_unref:
1771 : : * @array: (transfer full): a pointer array
1772 : : *
1773 : : * Atomically decrements the reference count of @array by one. If the
1774 : : * reference count drops to 0, the effect is the same as calling
1775 : : * [func@GLib.PtrArray.free] with @free_segment set to true. This function
1776 : : * is thread-safe and may be called from any thread.
1777 : : *
1778 : : * Since: 2.22
1779 : : */
1780 : : void
1781 : 12139 : g_ptr_array_unref (GPtrArray *array)
1782 : : {
1783 : 12139 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1784 : :
1785 : 12139 : g_return_if_fail (array);
1786 : :
1787 : 12139 : if (g_atomic_ref_count_dec (&rarray->ref_count))
1788 : 11773 : ptr_array_free (array, FREE_SEGMENT);
1789 : : }
1790 : :
1791 : : /**
1792 : : * g_ptr_array_free:
1793 : : * @array: (transfer full): a pointer array
1794 : : * @free_segment: if true, the actual pointer array is freed as well
1795 : : *
1796 : : * Frees the memory allocated for the `GPtrArray`. If @free_segment is true
1797 : : * it frees the memory block holding the elements as well. Pass false
1798 : : * if you want to free the `GPtrArray` wrapper but preserve the
1799 : : * underlying array for use elsewhere. If the reference count of @array
1800 : : * is greater than one, the `GPtrArray` wrapper is preserved but the
1801 : : * size of @array will be set to zero.
1802 : : *
1803 : : * If array contents point to dynamically-allocated memory, they should
1804 : : * be freed separately if @free_segment is true and no
1805 : : * [callback@GLib.DestroyNotify] function has been set for @array.
1806 : : *
1807 : : * Note that if the array is `NULL` terminated and @free_segment is false
1808 : : * then this will always return an allocated `NULL` terminated buffer.
1809 : : * If `pdata` is previously `NULL`, a new buffer will be allocated.
1810 : : *
1811 : : * This function is not thread-safe. If using a `GPtrArray` from multiple
1812 : : * threads, use only the atomic [func@GLib.PtrArray.ref] and
1813 : : * [func@GLib.PtrArray.unref] functions.
1814 : : *
1815 : : * Returns: (transfer full) (array) (nullable): The allocated pointer array if
1816 : : * @free_segment is false, otherwise `NULL`.
1817 : : */
1818 : : gpointer*
1819 : 143484 : g_ptr_array_free (GPtrArray *array,
1820 : : gboolean free_segment)
1821 : : {
1822 : 143484 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1823 : : ArrayFreeFlags flags;
1824 : :
1825 : 143484 : g_return_val_if_fail (rarray, NULL);
1826 : :
1827 : 143484 : flags = (free_segment ? FREE_SEGMENT : 0);
1828 : :
1829 : : /* if others are holding a reference, preserve the wrapper but
1830 : : * do free/return the data
1831 : : *
1832 : : * Coverity doesn’t understand this and assumes it’s a leak, so comment this
1833 : : * out.
1834 : : */
1835 : : #ifndef __COVERITY__
1836 : 143484 : if (!g_atomic_ref_count_dec (&rarray->ref_count))
1837 : 3 : flags |= PRESERVE_WRAPPER;
1838 : : #endif
1839 : :
1840 : 143484 : return ptr_array_free (array, flags);
1841 : : }
1842 : :
1843 : : static gpointer *
1844 : 155257 : ptr_array_free (GPtrArray *array,
1845 : : ArrayFreeFlags flags)
1846 : : {
1847 : 155257 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1848 : : gpointer *segment;
1849 : :
1850 : 155257 : if (flags & FREE_SEGMENT)
1851 : : {
1852 : : /* Data here is stolen and freed manually. It is an
1853 : : * error to attempt to access the array data (including
1854 : : * mutating the array bounds) during destruction).
1855 : : *
1856 : : * https://bugzilla.gnome.org/show_bug.cgi?id=769064
1857 : : */
1858 : 36724 : gpointer *stolen_pdata = g_steal_pointer (&rarray->pdata);
1859 : 36724 : if (rarray->element_free_func != NULL)
1860 : : {
1861 : : guint i;
1862 : :
1863 : 164604 : for (i = 0; i < rarray->len; ++i)
1864 : 162907 : rarray->element_free_func (stolen_pdata[i]);
1865 : : }
1866 : :
1867 : 36724 : g_free (stolen_pdata);
1868 : 36724 : segment = NULL;
1869 : : }
1870 : : else
1871 : : {
1872 : 118533 : segment = rarray->pdata;
1873 : 118533 : if (!segment && rarray->null_terminated)
1874 : 4 : segment = (gpointer *) g_new0 (char *, 1);
1875 : : }
1876 : :
1877 : 155257 : if (flags & PRESERVE_WRAPPER)
1878 : : {
1879 : 3 : rarray->pdata = NULL;
1880 : 3 : rarray->len = 0;
1881 : 3 : rarray->alloc = 0;
1882 : : }
1883 : : else
1884 : : {
1885 : 155254 : g_slice_free1 (sizeof (GRealPtrArray), rarray);
1886 : : }
1887 : :
1888 : 155257 : return segment;
1889 : : }
1890 : :
1891 : : static void
1892 : 1747816 : g_ptr_array_maybe_expand (GRealPtrArray *array,
1893 : : guint len)
1894 : : {
1895 : : guint max_len, want_len;
1896 : :
1897 : : /* The maximum array length is derived from following constraints:
1898 : : * - The number of bytes must fit into a gsize / 2.
1899 : : * - The number of elements must fit into guint.
1900 : : * - null terminated arrays must leave space for the terminating element
1901 : : */
1902 : 1747816 : max_len = MIN (G_MAXSIZE / 2 / sizeof (gpointer), G_MAXUINT) - (array->null_terminated ? 1 : 0);
1903 : :
1904 : : /* Detect potential overflow */
1905 : 1747816 : if G_UNLIKELY ((max_len - array->len) < len)
1906 : 0 : g_error ("adding %u to array would overflow", len);
1907 : :
1908 : 1747816 : want_len = array->len + len + (array->null_terminated ? 1 : 0);
1909 : 1747816 : if (want_len > array->alloc)
1910 : : {
1911 : 277348 : guint old_alloc = array->alloc;
1912 : 277348 : gsize want_alloc = g_nearest_pow (sizeof (gpointer) * want_len);
1913 : 277348 : want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
1914 : 277348 : array->alloc = MIN (want_alloc / sizeof (gpointer), G_MAXUINT);
1915 : 277348 : array->pdata = g_realloc (array->pdata, want_alloc);
1916 : 277348 : if (G_UNLIKELY (g_mem_gc_friendly))
1917 : 1447665 : for ( ; old_alloc < array->alloc; old_alloc++)
1918 : 1214260 : array->pdata [old_alloc] = NULL;
1919 : : }
1920 : 1747816 : }
1921 : :
1922 : : /**
1923 : : * g_ptr_array_set_size:
1924 : : * @array: a pointer array
1925 : : * @length: the new length of the pointer array
1926 : : *
1927 : : * Sets the size of the array. When making the array larger,
1928 : : * newly-added elements will be set to `NULL`. When making it smaller,
1929 : : * if @array has a non-`NULL` [callback@GLib.DestroyNotify] function then it
1930 : : * will be called for the removed elements.
1931 : : */
1932 : : void
1933 : 1556704 : g_ptr_array_set_size (GPtrArray *array,
1934 : : gint length)
1935 : : {
1936 : 1556704 : GRealPtrArray *rarray = (GRealPtrArray *)array;
1937 : : guint length_unsigned;
1938 : :
1939 : 1556704 : g_return_if_fail (rarray);
1940 : 1556704 : g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL));
1941 : 1556704 : g_return_if_fail (length >= 0);
1942 : :
1943 : 1556704 : length_unsigned = (guint) length;
1944 : :
1945 : 1556704 : if (length_unsigned > rarray->len)
1946 : : {
1947 : : guint i;
1948 : :
1949 : 1 : g_ptr_array_maybe_expand (rarray, length_unsigned - rarray->len);
1950 : :
1951 : : /* This is not
1952 : : * memset (array->pdata + array->len, 0,
1953 : : * sizeof (gpointer) * (length_unsigned - array->len));
1954 : : * to make it really portable. Remember (void*)NULL needn't be
1955 : : * bitwise zero. It of course is silly not to use memset (..,0,..).
1956 : : */
1957 : 18 : for (i = rarray->len; i < length_unsigned; i++)
1958 : 17 : rarray->pdata[i] = NULL;
1959 : :
1960 : 1 : rarray->len = length_unsigned;
1961 : :
1962 : 1 : ptr_array_maybe_null_terminate (rarray);
1963 : : }
1964 : 1556703 : else if (length_unsigned < rarray->len)
1965 : 677883 : g_ptr_array_remove_range (array, length_unsigned, rarray->len - length_unsigned);
1966 : : }
1967 : :
1968 : : static gpointer
1969 : 165511 : ptr_array_remove_index (GPtrArray *array,
1970 : : guint index_,
1971 : : gboolean fast,
1972 : : gboolean free_element)
1973 : : {
1974 : 165511 : GRealPtrArray *rarray = (GRealPtrArray *) array;
1975 : : gpointer result;
1976 : :
1977 : 165511 : g_return_val_if_fail (rarray, NULL);
1978 : 165511 : g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL);
1979 : :
1980 : 165511 : g_return_val_if_fail (index_ < rarray->len, NULL);
1981 : :
1982 : 165511 : result = rarray->pdata[index_];
1983 : :
1984 : 165511 : if (rarray->element_free_func != NULL && free_element)
1985 : 904 : rarray->element_free_func (rarray->pdata[index_]);
1986 : :
1987 : 165511 : if (index_ != rarray->len - 1 && !fast)
1988 : 97 : memmove (rarray->pdata + index_, rarray->pdata + index_ + 1,
1989 : 97 : sizeof (gpointer) * (rarray->len - index_ - 1));
1990 : 165414 : else if (index_ != rarray->len - 1)
1991 : 133788 : rarray->pdata[index_] = rarray->pdata[rarray->len - 1];
1992 : :
1993 : 165511 : rarray->len -= 1;
1994 : :
1995 : 165511 : if (rarray->null_terminated || G_UNLIKELY (g_mem_gc_friendly))
1996 : 165510 : rarray->pdata[rarray->len] = NULL;
1997 : :
1998 : 165511 : return result;
1999 : : }
2000 : :
2001 : : /**
2002 : : * g_ptr_array_remove_index:
2003 : : * @array: a pointer array
2004 : : * @index_: the index of the pointer to remove
2005 : : *
2006 : : * Removes the pointer at the given index from the pointer array.
2007 : : * The following elements are moved down one place. If @array has
2008 : : * a non-`NULL` [callback@GLib.DestroyNotify] function it is called for the
2009 : : * removed
2010 : : * element. If so, the return value from this function will potentially point
2011 : : * to freed memory (depending on the [callback@GLib.DestroyNotify]
2012 : : * implementation).
2013 : : *
2014 : : * Returns: (nullable): The pointer which was removed
2015 : : */
2016 : : gpointer
2017 : 473 : g_ptr_array_remove_index (GPtrArray *array,
2018 : : guint index_)
2019 : : {
2020 : 473 : return ptr_array_remove_index (array, index_, FALSE, TRUE);
2021 : : }
2022 : :
2023 : : /**
2024 : : * g_ptr_array_remove_index_fast:
2025 : : * @array: a pointer array
2026 : : * @index_: the index of the pointer to remove
2027 : : *
2028 : : * Removes the pointer at the given index from the pointer array.
2029 : : * The last element in the array is used to fill in the space, so
2030 : : * this function does not preserve the order of the array. But it
2031 : : * is faster than [func@GLib.PtrArray.remove_index]. If @array has a non-`NULL`
2032 : : * [callback@GLib.DestroyNotify] function it is called for the removed element.
2033 : : * If so, the
2034 : : * return value from this function will potentially point to freed memory
2035 : : * (depending on the [callback@GLib.DestroyNotify] implementation).
2036 : : *
2037 : : * Returns: (nullable): The pointer which was removed
2038 : : */
2039 : : gpointer
2040 : 134748 : g_ptr_array_remove_index_fast (GPtrArray *array,
2041 : : guint index_)
2042 : : {
2043 : 134748 : return ptr_array_remove_index (array, index_, TRUE, TRUE);
2044 : : }
2045 : :
2046 : : /**
2047 : : * g_ptr_array_steal_index:
2048 : : * @array: a pointer array
2049 : : * @index_: the index of the pointer to steal
2050 : : *
2051 : : * Removes the pointer at the given index from the pointer array.
2052 : : * The following elements are moved down one place. The
2053 : : * [callback@GLib.DestroyNotify] for
2054 : : * @array is *not* called on the removed element; ownership is transferred to
2055 : : * the caller of this function.
2056 : : *
2057 : : * Returns: (transfer full) (nullable): The pointer which was removed
2058 : : * Since: 2.58
2059 : : */
2060 : : gpointer
2061 : 2 : g_ptr_array_steal_index (GPtrArray *array,
2062 : : guint index_)
2063 : : {
2064 : 2 : return ptr_array_remove_index (array, index_, FALSE, FALSE);
2065 : : }
2066 : :
2067 : : /**
2068 : : * g_ptr_array_steal_index_fast:
2069 : : * @array: a pointer array
2070 : : * @index_: the index of the pointer to steal
2071 : : *
2072 : : * Removes the pointer at the given index from the pointer array.
2073 : : * The last element in the array is used to fill in the space, so
2074 : : * this function does not preserve the order of the array. But it
2075 : : * is faster than [func@GLib.PtrArray.steal_index]. The
2076 : : * [callback@GLib.DestroyNotify] for @array is
2077 : : * *not* called on the removed element; ownership is transferred to the caller
2078 : : * of this function.
2079 : : *
2080 : : * Returns: (transfer full) (nullable): The pointer which was removed
2081 : : * Since: 2.58
2082 : : */
2083 : : gpointer
2084 : 30288 : g_ptr_array_steal_index_fast (GPtrArray *array,
2085 : : guint index_)
2086 : : {
2087 : 30288 : return ptr_array_remove_index (array, index_, TRUE, FALSE);
2088 : : }
2089 : :
2090 : : /**
2091 : : * g_ptr_array_remove_range:
2092 : : * @array: a pointer array
2093 : : * @index_: the index of the first pointer to remove
2094 : : * @length: the number of pointers to remove
2095 : : *
2096 : : * Removes the given number of pointers starting at the given index
2097 : : * from a `GPtrArray`. The following elements are moved to close the
2098 : : * gap. If @array has a non-`NULL` [callback@GLib.DestroyNotify] function it is
2099 : : * called for the removed elements.
2100 : : *
2101 : : * Returns: (transfer none): The @array
2102 : : *
2103 : : * Since: 2.4
2104 : : */
2105 : : GPtrArray*
2106 : 677888 : g_ptr_array_remove_range (GPtrArray *array,
2107 : : guint index_,
2108 : : guint length)
2109 : : {
2110 : 677888 : GRealPtrArray *rarray = (GRealPtrArray *)array;
2111 : : guint i;
2112 : :
2113 : 677888 : g_return_val_if_fail (rarray != NULL, NULL);
2114 : 677888 : g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL);
2115 : 677888 : g_return_val_if_fail (index_ <= rarray->len, NULL);
2116 : 677888 : g_return_val_if_fail (index_ <= G_MAXUINT - length, NULL);
2117 : 677888 : g_return_val_if_fail (length == 0 || index_ + length <= rarray->len, NULL);
2118 : :
2119 : 677888 : if (length == 0)
2120 : 1 : return array;
2121 : :
2122 : 677887 : if (rarray->element_free_func != NULL)
2123 : : {
2124 : 450 : for (i = index_; i < index_ + length; i++)
2125 : 382 : rarray->element_free_func (rarray->pdata[i]);
2126 : : }
2127 : :
2128 : 677887 : if (index_ + length != rarray->len)
2129 : : {
2130 : 3 : memmove (&rarray->pdata[index_],
2131 : 3 : &rarray->pdata[index_ + length],
2132 : 3 : (rarray->len - (index_ + length)) * sizeof (gpointer));
2133 : : }
2134 : :
2135 : 677887 : rarray->len -= length;
2136 : 677887 : if (G_UNLIKELY (g_mem_gc_friendly))
2137 : : {
2138 : 1387830 : for (i = 0; i < length; i++)
2139 : 709949 : rarray->pdata[rarray->len + i] = NULL;
2140 : : }
2141 : : else
2142 : 6 : ptr_array_maybe_null_terminate (rarray);
2143 : :
2144 : 677887 : return array;
2145 : : }
2146 : :
2147 : : /**
2148 : : * g_ptr_array_remove:
2149 : : * @array: a pointer array
2150 : : * @data: the pointer to remove
2151 : : *
2152 : : * Removes the first occurrence of the given pointer from the pointer
2153 : : * array. The following elements are moved down one place. If @array
2154 : : * has a non-`NULL` [callback@GLib.DestroyNotify] function it is called for the
2155 : : * removed element.
2156 : : *
2157 : : * It returns true if the pointer was removed, or false if the
2158 : : * pointer was not found.
2159 : : *
2160 : : * Returns: true if the pointer is found and removed; false otherwise
2161 : : */
2162 : : gboolean
2163 : 447 : g_ptr_array_remove (GPtrArray *array,
2164 : : gpointer data)
2165 : : {
2166 : : guint i;
2167 : :
2168 : 447 : g_return_val_if_fail (array, FALSE);
2169 : 447 : g_return_val_if_fail (array->len == 0 || (array->len != 0 && array->pdata != NULL), FALSE);
2170 : :
2171 : 566 : for (i = 0; i < array->len; i += 1)
2172 : : {
2173 : 565 : if (array->pdata[i] == data)
2174 : : {
2175 : 446 : g_ptr_array_remove_index (array, i);
2176 : 446 : return TRUE;
2177 : : }
2178 : : }
2179 : :
2180 : 1 : return FALSE;
2181 : : }
2182 : :
2183 : : /**
2184 : : * g_ptr_array_remove_fast:
2185 : : * @array: a pointer array
2186 : : * @data: the pointer to remove
2187 : : *
2188 : : * Removes the first occurrence of the given pointer from the pointer
2189 : : * array. The last element in the array is used to fill in the space,
2190 : : * so this function does not preserve the order of the array. But it
2191 : : * is faster than [func@GLib.PtrArray.remove]. If @array has a non-`NULL`
2192 : : * [callback@GLib.DestroyNotify] function it is called for the removed element.
2193 : : *
2194 : : * It returns true if the pointer was removed, or false if the
2195 : : * pointer was not found.
2196 : : *
2197 : : * Returns: true if the pointer is found and removed; false otherwise
2198 : : */
2199 : : gboolean
2200 : 133862 : g_ptr_array_remove_fast (GPtrArray *array,
2201 : : gpointer data)
2202 : : {
2203 : 133862 : GRealPtrArray *rarray = (GRealPtrArray *)array;
2204 : : guint i;
2205 : :
2206 : 133862 : g_return_val_if_fail (rarray, FALSE);
2207 : 133862 : g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), FALSE);
2208 : :
2209 : 412923 : for (i = 0; i < rarray->len; i += 1)
2210 : : {
2211 : 412922 : if (rarray->pdata[i] == data)
2212 : : {
2213 : 133861 : g_ptr_array_remove_index_fast (array, i);
2214 : 133861 : return TRUE;
2215 : : }
2216 : : }
2217 : :
2218 : 1 : return FALSE;
2219 : : }
2220 : :
2221 : : /**
2222 : : * g_ptr_array_add:
2223 : : * @array: a pointer array
2224 : : * @data: the pointer to add
2225 : : *
2226 : : * Adds a pointer to the end of the pointer array. The array will grow
2227 : : * in size automatically if necessary.
2228 : : */
2229 : : void
2230 : 1736803 : g_ptr_array_add (GPtrArray *array,
2231 : : gpointer data)
2232 : : {
2233 : 1736803 : GRealPtrArray *rarray = (GRealPtrArray *)array;
2234 : :
2235 : 1736803 : g_return_if_fail (rarray);
2236 : 1736803 : g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL));
2237 : :
2238 : 1736803 : g_ptr_array_maybe_expand (rarray, 1u);
2239 : :
2240 : 1736803 : rarray->pdata[rarray->len++] = data;
2241 : :
2242 : 1736803 : ptr_array_maybe_null_terminate (rarray);
2243 : : }
2244 : :
2245 : : /**
2246 : : * g_ptr_array_extend:
2247 : : * @array_to_extend: a pointer array
2248 : : * @array: (transfer none): a pointer array to add to the end of @array_to_extend
2249 : : * @func: (scope call) (nullable): a copy function used to copy every element in the array
2250 : : * @user_data: the user data passed to the copy function @func
2251 : : *
2252 : : * Adds all pointers of @array to the end of the array @array_to_extend.
2253 : : * The array will grow in size automatically if needed. @array_to_extend is
2254 : : * modified in-place.
2255 : : *
2256 : : * @func, as a [callback@GLib.CopyFunc], takes two arguments, the data to be
2257 : : * copied
2258 : : * and a @user_data pointer. On common processor architectures, it’s safe to
2259 : : * pass `NULL` as @user_data if the copy function takes only one argument. You
2260 : : * may get compiler warnings from this though if compiling with GCC’s
2261 : : * `-Wcast-function-type` warning.
2262 : : *
2263 : : * If @func is `NULL`, then only the pointers (and not what they are
2264 : : * pointing to) are copied to the new `GPtrArray`.
2265 : : *
2266 : : * Whether @array_to_extend is `NULL` terminated stays unchanged by this function.
2267 : : *
2268 : : * Since: 2.62
2269 : : **/
2270 : : void
2271 : 16 : g_ptr_array_extend (GPtrArray *array_to_extend,
2272 : : GPtrArray *array,
2273 : : GCopyFunc func,
2274 : : gpointer user_data)
2275 : : {
2276 : 16 : GRealPtrArray *rarray_to_extend = (GRealPtrArray *) array_to_extend;
2277 : :
2278 : 16 : g_return_if_fail (array_to_extend != NULL);
2279 : 14 : g_return_if_fail (array != NULL);
2280 : :
2281 : 12 : if (array->len == 0u)
2282 : 4 : return;
2283 : :
2284 : 8 : g_ptr_array_maybe_expand (rarray_to_extend, array->len);
2285 : :
2286 : 8 : if (func != NULL)
2287 : : {
2288 : : guint i;
2289 : :
2290 : 102 : for (i = 0; i < array->len; i++)
2291 : 100 : rarray_to_extend->pdata[i + rarray_to_extend->len] =
2292 : 100 : func (array->pdata[i], user_data);
2293 : : }
2294 : 6 : else if (array->len > 0)
2295 : : {
2296 : 6 : memcpy (rarray_to_extend->pdata + rarray_to_extend->len, array->pdata,
2297 : 6 : array->len * sizeof (*array->pdata));
2298 : : }
2299 : :
2300 : 8 : rarray_to_extend->len += array->len;
2301 : :
2302 : 8 : ptr_array_maybe_null_terminate (rarray_to_extend);
2303 : : }
2304 : :
2305 : : /**
2306 : : * g_ptr_array_extend_and_steal:
2307 : : * @array_to_extend: (transfer none): a pointer array
2308 : : * @array: (transfer container): a pointer array to add to the end of
2309 : : * @array_to_extend
2310 : : *
2311 : : * Adds all the pointers in @array to the end of @array_to_extend, transferring
2312 : : * ownership of each element from @array to @array_to_extend and modifying
2313 : : * @array_to_extend in-place. @array is then freed.
2314 : : *
2315 : : * As with [func@GLib.PtrArray.free], @array will be destroyed if its reference
2316 : : * count is 1. If its reference count is higher, it will be decremented and the
2317 : : * length of @array set to zero.
2318 : : *
2319 : : * Since: 2.62
2320 : : **/
2321 : : void
2322 : 4 : g_ptr_array_extend_and_steal (GPtrArray *array_to_extend,
2323 : : GPtrArray *array)
2324 : : {
2325 : : gpointer *pdata;
2326 : :
2327 : 4 : g_return_if_fail (array_to_extend != NULL);
2328 : 3 : g_return_if_fail (array != NULL);
2329 : :
2330 : 2 : g_ptr_array_extend (array_to_extend, array, NULL, NULL);
2331 : :
2332 : : /* Get rid of @array without triggering the GDestroyNotify attached
2333 : : * to the elements moved from @array to @array_to_extend. */
2334 : 2 : pdata = g_steal_pointer (&array->pdata);
2335 : 2 : array->len = 0;
2336 : 2 : ((GRealPtrArray *) array)->alloc = 0;
2337 : 2 : g_ptr_array_unref (array);
2338 : 2 : g_free (pdata);
2339 : : }
2340 : :
2341 : : /**
2342 : : * g_ptr_array_insert:
2343 : : * @array: a pointer array
2344 : : * @index_: the index to place the new element at, or -1 to append
2345 : : * @data: the pointer to add
2346 : : *
2347 : : * Inserts an element into the pointer array at the given index. The
2348 : : * array will grow in size automatically if necessary.
2349 : : *
2350 : : * Since: 2.40
2351 : : */
2352 : : void
2353 : 10121 : g_ptr_array_insert (GPtrArray *array,
2354 : : gint index_,
2355 : : gpointer data)
2356 : : {
2357 : 10121 : GRealPtrArray *rarray = (GRealPtrArray *)array;
2358 : : guint real_index;
2359 : :
2360 : 10121 : g_return_if_fail (rarray);
2361 : 10121 : g_return_if_fail (index_ >= -1);
2362 : 10121 : g_return_if_fail (index_ < 0 || (guint) index_ <= rarray->len);
2363 : :
2364 : 10121 : g_ptr_array_maybe_expand (rarray, 1u);
2365 : :
2366 : 10121 : real_index = (index_ >= 0) ? (guint) index_ : rarray->len;
2367 : :
2368 : 10121 : if (real_index < rarray->len)
2369 : 10076 : memmove (&(rarray->pdata[real_index + 1]),
2370 : 10076 : &(rarray->pdata[real_index]),
2371 : 10076 : (rarray->len - real_index) * sizeof (gpointer));
2372 : :
2373 : 10121 : rarray->len++;
2374 : 10121 : rarray->pdata[real_index] = data;
2375 : :
2376 : 10121 : ptr_array_maybe_null_terminate (rarray);
2377 : : }
2378 : :
2379 : : /* Please keep this doc-comment in sync with pointer_array_sort_example()
2380 : : * in glib/tests/array-test.c */
2381 : : /**
2382 : : * g_ptr_array_sort:
2383 : : * @array: a pointer array
2384 : : * @compare_func: (scope call): a comparison function
2385 : : *
2386 : : * Sorts the array, using @compare_func which should be a `qsort()`-style
2387 : : * comparison function (returns less than zero for first arg is less
2388 : : * than second arg, zero for equal, greater than zero if first arg is
2389 : : * greater than second arg).
2390 : : *
2391 : : * Note that the comparison function for [func@GLib.PtrArray.sort] doesn’t
2392 : : * take the pointers from the array as arguments, it takes pointers to
2393 : : * the pointers in the array.
2394 : : *
2395 : : * Use [func@GLib.PtrArray.sort_values] if you want to use normal
2396 : : * [callback@GLib.CompareFunc] instances, otherwise here is a full example of
2397 : : * use:
2398 : : *
2399 : : * ```c
2400 : : * typedef struct
2401 : : * {
2402 : : * gchar *name;
2403 : : * gint size;
2404 : : * } FileListEntry;
2405 : : *
2406 : : * static gint
2407 : : * sort_filelist (gconstpointer a, gconstpointer b)
2408 : : * {
2409 : : * const FileListEntry *entry1 = *((FileListEntry **) a);
2410 : : * const FileListEntry *entry2 = *((FileListEntry **) b);
2411 : : *
2412 : : * return g_ascii_strcasecmp (entry1->name, entry2->name);
2413 : : * }
2414 : : *
2415 : : * …
2416 : : * g_autoptr (GPtrArray) file_list = NULL;
2417 : : *
2418 : : * // initialize file_list array and load with many FileListEntry entries
2419 : : * ...
2420 : : * // now sort it with
2421 : : * g_ptr_array_sort (file_list, sort_filelist);
2422 : : * ```
2423 : : *
2424 : : * This is guaranteed to be a stable sort since version 2.32.
2425 : : */
2426 : : void
2427 : 281 : g_ptr_array_sort (GPtrArray *array,
2428 : : GCompareFunc compare_func)
2429 : : {
2430 : 281 : g_return_if_fail (array != NULL);
2431 : :
2432 : : /* Don't use qsort as we want a guaranteed stable sort */
2433 : 281 : if (array->len > 0)
2434 : 280 : g_sort_array (array->pdata,
2435 : 280 : array->len,
2436 : : sizeof (gpointer),
2437 : : (GCompareDataFunc) compare_func,
2438 : : NULL);
2439 : : }
2440 : :
2441 : : /* Please keep this doc-comment in sync with
2442 : : * pointer_array_sort_with_data_example() in glib/tests/array-test.c */
2443 : : /**
2444 : : * g_ptr_array_sort_with_data:
2445 : : * @array: a pointer array
2446 : : * @compare_func: (scope call): a comparison function
2447 : : * @user_data: the data to pass to @compare_func
2448 : : *
2449 : : * Like [func@GLib.PtrArray.sort], but the comparison function has an extra
2450 : : * user data argument.
2451 : : *
2452 : : * Note that the comparison function for [func@GLib.PtrArray.sort_with_data]
2453 : : * doesn’t take the pointers from the array as arguments, it takes
2454 : : * pointers to the pointers in the array.
2455 : : *
2456 : : * Use [func@GLib.PtrArray.sort_values_with_data] if you want to use normal
2457 : : * [callback@GLib.CompareDataFunc] instances, otherwise here is a full example
2458 : : * of use:
2459 : : *
2460 : : * ```c
2461 : : * typedef enum { SORT_NAME, SORT_SIZE } SortMode;
2462 : : *
2463 : : * typedef struct
2464 : : * {
2465 : : * gchar *name;
2466 : : * gint size;
2467 : : * } FileListEntry;
2468 : : *
2469 : : * static gint
2470 : : * sort_filelist (gconstpointer a, gconstpointer b, gpointer user_data)
2471 : : * {
2472 : : * gint order;
2473 : : * const SortMode sort_mode = GPOINTER_TO_INT (user_data);
2474 : : * const FileListEntry *entry1 = *((FileListEntry **) a);
2475 : : * const FileListEntry *entry2 = *((FileListEntry **) b);
2476 : : *
2477 : : * switch (sort_mode)
2478 : : * {
2479 : : * case SORT_NAME:
2480 : : * order = g_ascii_strcasecmp (entry1->name, entry2->name);
2481 : : * break;
2482 : : * case SORT_SIZE:
2483 : : * order = entry1->size - entry2->size;
2484 : : * break;
2485 : : * default:
2486 : : * order = 0;
2487 : : * break;
2488 : : * }
2489 : : * return order;
2490 : : * }
2491 : : *
2492 : : * ...
2493 : : * g_autoptr (GPtrArray) file_list = NULL;
2494 : : * SortMode sort_mode;
2495 : : *
2496 : : * // initialize file_list array and load with many FileListEntry entries
2497 : : * ...
2498 : : * // now sort it with
2499 : : * sort_mode = SORT_NAME;
2500 : : * g_ptr_array_sort_with_data (file_list,
2501 : : * sort_filelist,
2502 : : * GINT_TO_POINTER (sort_mode));
2503 : : * ```
2504 : : *
2505 : : * This is guaranteed to be a stable sort since version 2.32.
2506 : : */
2507 : : void
2508 : 105 : g_ptr_array_sort_with_data (GPtrArray *array,
2509 : : GCompareDataFunc compare_func,
2510 : : gpointer user_data)
2511 : : {
2512 : 105 : g_return_if_fail (array != NULL);
2513 : :
2514 : 105 : if (array->len > 0)
2515 : 102 : g_sort_array (array->pdata,
2516 : 102 : array->len,
2517 : : sizeof (gpointer),
2518 : : compare_func,
2519 : : user_data);
2520 : : }
2521 : :
2522 : : static inline gint
2523 : 121353 : compare_ptr_array_values (gconstpointer a, gconstpointer b, gpointer user_data)
2524 : : {
2525 : 121353 : gconstpointer aa = *((gconstpointer *) a);
2526 : 121353 : gconstpointer bb = *((gconstpointer *) b);
2527 : 121353 : GCompareFunc compare_func = user_data;
2528 : :
2529 : 121353 : return compare_func (aa, bb);
2530 : : }
2531 : :
2532 : : /**
2533 : : * g_ptr_array_sort_values:
2534 : : * @array: a pointer array
2535 : : * @compare_func: (scope call): a comparison function
2536 : : *
2537 : : * Sorts the array, using @compare_func which should be a `qsort()`-style
2538 : : * comparison function (returns less than zero for first arg is less
2539 : : * than second arg, zero for equal, greater than zero if first arg is
2540 : : * greater than second arg).
2541 : : *
2542 : : * This is guaranteed to be a stable sort.
2543 : : *
2544 : : * Since: 2.76
2545 : : */
2546 : : void
2547 : 97 : g_ptr_array_sort_values (GPtrArray *array,
2548 : : GCompareFunc compare_func)
2549 : : {
2550 : 97 : g_ptr_array_sort_with_data (array, compare_ptr_array_values, compare_func);
2551 : 97 : }
2552 : :
2553 : : typedef struct
2554 : : {
2555 : : GCompareDataFunc compare_func;
2556 : : gpointer user_data;
2557 : : } GPtrArraySortValuesData;
2558 : :
2559 : : static inline gint
2560 : 120356 : compare_ptr_array_values_with_data (gconstpointer a,
2561 : : gconstpointer b,
2562 : : gpointer user_data)
2563 : : {
2564 : 120356 : gconstpointer aa = *((gconstpointer *) a);
2565 : 120356 : gconstpointer bb = *((gconstpointer *) b);
2566 : 120356 : GPtrArraySortValuesData *data = user_data;
2567 : :
2568 : 120356 : return data->compare_func (aa, bb, data->user_data);
2569 : : }
2570 : :
2571 : : /**
2572 : : * g_ptr_array_sort_values_with_data:
2573 : : * @array: a pointer array
2574 : : * @compare_func: (scope call): a comparison function
2575 : : * @user_data: the data to pass to @compare_func
2576 : : *
2577 : : * Like [func@GLib.PtrArray.sort_values], but the comparison function has an
2578 : : * extra user data argument.
2579 : : *
2580 : : * This is guaranteed to be a stable sort.
2581 : : *
2582 : : * Since: 2.76
2583 : : */
2584 : : void
2585 : 4 : g_ptr_array_sort_values_with_data (GPtrArray *array,
2586 : : GCompareDataFunc compare_func,
2587 : : gpointer user_data)
2588 : : {
2589 : 4 : g_ptr_array_sort_with_data (array, compare_ptr_array_values_with_data,
2590 : 4 : &(GPtrArraySortValuesData){
2591 : : .compare_func = compare_func,
2592 : : .user_data = user_data,
2593 : : });
2594 : 4 : }
2595 : :
2596 : : /**
2597 : : * g_ptr_array_foreach:
2598 : : * @array: a pointer array
2599 : : * @func: (scope call): the function to call for each array element
2600 : : * @user_data: the user data to pass to the function
2601 : : *
2602 : : * Calls a function for each element of a `GPtrArray`. @func must not
2603 : : * add elements to or remove elements from the array.
2604 : : *
2605 : : * Since: 2.4
2606 : : */
2607 : : void
2608 : 5984 : g_ptr_array_foreach (GPtrArray *array,
2609 : : GFunc func,
2610 : : gpointer user_data)
2611 : : {
2612 : : guint i;
2613 : :
2614 : 5984 : g_return_if_fail (array);
2615 : :
2616 : 45986 : for (i = 0; i < array->len; i++)
2617 : 40002 : (*func) (array->pdata[i], user_data);
2618 : : }
2619 : :
2620 : : /**
2621 : : * g_ptr_array_find: (skip)
2622 : : * @haystack: the pointer array to be searched
2623 : : * @needle: the pointer to look for
2624 : : * @index_: (optional) (out): the return location for the index of
2625 : : * the element, if found
2626 : : *
2627 : : * Checks whether @needle exists in @haystack. If the element is found, true
2628 : : * is returned and the element’s index is returned in @index_ (if non-`NULL`).
2629 : : * Otherwise, false is returned and @index_ is undefined. If @needle exists
2630 : : * multiple times in @haystack, the index of the first instance is returned.
2631 : : *
2632 : : * This does pointer comparisons only. If you want to use more complex equality
2633 : : * checks, such as string comparisons, use
2634 : : * [func@GLib.PtrArray.find_with_equal_func].
2635 : : *
2636 : : * Returns: true if @needle is one of the elements of @haystack; false otherwise
2637 : : * Since: 2.54
2638 : : */
2639 : : gboolean
2640 : 10 : g_ptr_array_find (GPtrArray *haystack,
2641 : : gconstpointer needle,
2642 : : guint *index_)
2643 : : {
2644 : 10 : return g_ptr_array_find_with_equal_func (haystack, needle, NULL, index_);
2645 : : }
2646 : :
2647 : : /**
2648 : : * g_ptr_array_find_with_equal_func: (skip)
2649 : : * @haystack: the pointer array to be searched
2650 : : * @needle: the pointer to look for
2651 : : * @equal_func: (nullable): the function to call for each element, which should
2652 : : * return true when the desired element is found; or `NULL` to use pointer
2653 : : * equality
2654 : : * @index_: (optional) (out): the return location for the index of
2655 : : * the element, if found
2656 : : *
2657 : : * Checks whether @needle exists in @haystack, using the given @equal_func.
2658 : : * If the element is found, true is returned and the element’s index is
2659 : : * returned in @index_ (if non-`NULL`). Otherwise, false is returned and @index_
2660 : : * is undefined. If @needle exists multiple times in @haystack, the index of
2661 : : * the first instance is returned.
2662 : : *
2663 : : * @equal_func is called with the element from the array as its first parameter,
2664 : : * and @needle as its second parameter. If @equal_func is `NULL`, pointer
2665 : : * equality is used.
2666 : : *
2667 : : * Returns: true if @needle is one of the elements of @haystack; false otherwise
2668 : : * Since: 2.54
2669 : : */
2670 : : gboolean
2671 : 24 : g_ptr_array_find_with_equal_func (GPtrArray *haystack,
2672 : : gconstpointer needle,
2673 : : GEqualFunc equal_func,
2674 : : guint *index_)
2675 : : {
2676 : : guint i;
2677 : :
2678 : 24 : g_return_val_if_fail (haystack != NULL, FALSE);
2679 : :
2680 : 24 : if (equal_func == NULL)
2681 : 11 : equal_func = g_direct_equal;
2682 : :
2683 : 55 : for (i = 0; i < haystack->len; i++)
2684 : : {
2685 : 50 : if (equal_func (g_ptr_array_index (haystack, i), needle))
2686 : : {
2687 : 19 : if (index_ != NULL)
2688 : 5 : *index_ = i;
2689 : 19 : return TRUE;
2690 : : }
2691 : : }
2692 : :
2693 : 5 : return FALSE;
2694 : : }
2695 : :
2696 : : /**
2697 : : * GByteArray: (copy-func g_byte_array_ref) (free-func g_byte_array_unref)
2698 : : * @data: a pointer to the element data. The data may be moved as
2699 : : * elements are added to the `GByteArray`
2700 : : * @len: the number of elements in the `GByteArray`
2701 : : *
2702 : : * Contains the public fields of a `GByteArray`.
2703 : : */
2704 : :
2705 : : /**
2706 : : * g_byte_array_new:
2707 : : *
2708 : : * Creates a new `GByteArray` with a reference count of 1.
2709 : : *
2710 : : * Returns: (transfer full): The new `GByteArray`
2711 : : */
2712 : : GByteArray*
2713 : 438 : g_byte_array_new (void)
2714 : : {
2715 : 438 : return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, 0);
2716 : : }
2717 : :
2718 : : /**
2719 : : * g_byte_array_steal:
2720 : : * @array: a byte array
2721 : : * @len: (optional) (out): the pointer to retrieve the number of
2722 : : * elements of the original array
2723 : : *
2724 : : * Frees the data in the array and resets the size to zero, while
2725 : : * the underlying array is preserved for use elsewhere and returned
2726 : : * to the caller.
2727 : : *
2728 : : * Returns: (transfer full) (array length=len): The allocated element data
2729 : : *
2730 : : * Since: 2.64
2731 : : */
2732 : : guint8 *
2733 : 2 : g_byte_array_steal (GByteArray *array,
2734 : : gsize *len)
2735 : : {
2736 : 2 : return (guint8 *) g_array_steal ((GArray *) array, len);
2737 : : }
2738 : :
2739 : : /**
2740 : : * g_byte_array_new_take:
2741 : : * @data: (transfer full) (array length=len): the byte data for the array
2742 : : * @len: the length of @data
2743 : : *
2744 : : * Creates a byte array containing the @data.
2745 : : * After this call, @data belongs to the `GByteArray` and may no longer be
2746 : : * modified by the caller. The memory of @data has to be dynamically
2747 : : * allocated and will eventually be freed with [func@GLib.free].
2748 : : *
2749 : : * Do not use it if @len is greater than [`G_MAXUINT`](types.html#guint).
2750 : : * `GByteArray` stores the length of its data in `guint`, which may be shorter
2751 : : * than `gsize`.
2752 : : *
2753 : : * Since: 2.32
2754 : : *
2755 : : * Returns: (transfer full): The new `GByteArray`
2756 : : */
2757 : : GByteArray*
2758 : 6 : g_byte_array_new_take (guint8 *data,
2759 : : gsize len)
2760 : : {
2761 : : GByteArray *array;
2762 : : GRealArray *real;
2763 : :
2764 : 6 : g_return_val_if_fail (len <= G_MAXUINT, NULL);
2765 : 4 : array = g_byte_array_new ();
2766 : 4 : real = (GRealArray *)array;
2767 : 4 : g_assert (real->data == NULL);
2768 : 4 : g_assert (real->len == 0);
2769 : :
2770 : 4 : real->data = data;
2771 : 4 : real->len = len;
2772 : 4 : real->elt_capacity = len;
2773 : :
2774 : 4 : return array;
2775 : : }
2776 : :
2777 : : /**
2778 : : * g_byte_array_sized_new:
2779 : : * @reserved_size: the number of bytes preallocated
2780 : : *
2781 : : * Creates a new `GByteArray` with @reserved_size bytes preallocated.
2782 : : * This avoids frequent reallocation, if you are going to add many
2783 : : * bytes to the array. Note however that the size of the array is still
2784 : : * 0.
2785 : : *
2786 : : * Returns: (transfer full): The new `GByteArray`
2787 : : */
2788 : : GByteArray*
2789 : 27 : g_byte_array_sized_new (guint reserved_size)
2790 : : {
2791 : 27 : return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, reserved_size);
2792 : : }
2793 : :
2794 : : /**
2795 : : * g_byte_array_free:
2796 : : * @array: (transfer full): a byte array
2797 : : * @free_segment: if true, the actual byte data is freed as well
2798 : : *
2799 : : * Frees the memory allocated by the `GByteArray`. If @free_segment is
2800 : : * true it frees the actual byte data. If the reference count of
2801 : : * @array is greater than one, the `GByteArray` wrapper is preserved but
2802 : : * the size of @array will be set to zero.
2803 : : *
2804 : : * Returns: (nullable) (array) (transfer full): The allocated element data if
2805 : : * @free_segment is false, otherwise `NULL`.
2806 : : */
2807 : : guint8*
2808 : 434 : g_byte_array_free (GByteArray *array,
2809 : : gboolean free_segment)
2810 : : {
2811 : 434 : return (guint8 *)g_array_free ((GArray *)array, free_segment);
2812 : : }
2813 : :
2814 : : /**
2815 : : * g_byte_array_free_to_bytes:
2816 : : * @array: (transfer full): a byte array
2817 : : *
2818 : : * Transfers the data from the `GByteArray` into a new immutable
2819 : : * [struct@GLib.Bytes].
2820 : : *
2821 : : * The `GByteArray` is freed unless the reference count of @array is greater
2822 : : * than one, in which the `GByteArray` wrapper is preserved but the size of
2823 : : * @array will be set to zero.
2824 : : *
2825 : : * This is identical to using [ctor@GLib.Bytes.new_take] and
2826 : : * [func@GLib.ByteArray.free] together.
2827 : : *
2828 : : * Since: 2.32
2829 : : *
2830 : : * Returns: (transfer full): The new immutable [struct@GLib.Bytes] representing
2831 : : * same byte data that was in the array
2832 : : */
2833 : : GBytes*
2834 : 1 : g_byte_array_free_to_bytes (GByteArray *array)
2835 : : {
2836 : : gsize length;
2837 : :
2838 : 1 : g_return_val_if_fail (array != NULL, NULL);
2839 : :
2840 : 1 : length = array->len;
2841 : 1 : return g_bytes_new_take (g_byte_array_free (array, FALSE), length);
2842 : : }
2843 : :
2844 : : /**
2845 : : * g_byte_array_ref:
2846 : : * @array: a byte array
2847 : : *
2848 : : * Atomically increments the reference count of @array by one.
2849 : : * This function is thread-safe and may be called from any thread.
2850 : : *
2851 : : * Returns: (transfer full): The passed in `GByteArray`
2852 : : *
2853 : : * Since: 2.22
2854 : : */
2855 : : GByteArray*
2856 : 3 : g_byte_array_ref (GByteArray *array)
2857 : : {
2858 : 3 : return (GByteArray *)g_array_ref ((GArray *)array);
2859 : : }
2860 : :
2861 : : /**
2862 : : * g_byte_array_unref:
2863 : : * @array: (transfer full): a byte array
2864 : : *
2865 : : * Atomically decrements the reference count of @array by one. If the
2866 : : * reference count drops to 0, all memory allocated by the array is
2867 : : * released. This function is thread-safe and may be called from any
2868 : : * thread.
2869 : : *
2870 : : * Since: 2.22
2871 : : */
2872 : : void
2873 : 34 : g_byte_array_unref (GByteArray *array)
2874 : : {
2875 : 34 : g_array_unref ((GArray *)array);
2876 : 34 : }
2877 : :
2878 : : /**
2879 : : * g_byte_array_append:
2880 : : * @array: a byte array
2881 : : * @data: (array length=len): the byte data to be added
2882 : : * @len: the number of bytes to add
2883 : : *
2884 : : * Adds the given bytes to the end of the `GByteArray`.
2885 : : * The array will grow in size automatically if necessary.
2886 : : *
2887 : : * Returns: (transfer none): The `GByteArray`
2888 : : */
2889 : : GByteArray*
2890 : 44867 : g_byte_array_append (GByteArray *array,
2891 : : const guint8 *data,
2892 : : guint len)
2893 : : {
2894 : 44867 : return (GByteArray *) g_array_append_vals ((GArray *) array, (guint8 *) data, len);
2895 : : }
2896 : :
2897 : : /**
2898 : : * g_byte_array_prepend:
2899 : : * @array: a byte array
2900 : : * @data: (array length=len): the byte data to be added
2901 : : * @len: the number of bytes to add
2902 : : *
2903 : : * Adds the given data to the start of the `GByteArray`.
2904 : : * The array will grow in size automatically if necessary.
2905 : : *
2906 : : * Returns: (transfer none): The `GByteArray`
2907 : : */
2908 : : GByteArray*
2909 : 10001 : g_byte_array_prepend (GByteArray *array,
2910 : : const guint8 *data,
2911 : : guint len)
2912 : : {
2913 : 10001 : return (GByteArray *) g_array_prepend_vals ((GArray *) array, (guint8 *) data, len);
2914 : : }
2915 : :
2916 : : /**
2917 : : * g_byte_array_set_size:
2918 : : * @array: a byte array
2919 : : * @length: the new size of the `GByteArray`
2920 : : *
2921 : : * Sets the size of the `GByteArray`, expanding it if necessary.
2922 : : *
2923 : : * Returns: (transfer none): The `GByteArray`
2924 : : */
2925 : : GByteArray*
2926 : 2 : g_byte_array_set_size (GByteArray *array,
2927 : : guint length)
2928 : : {
2929 : 2 : return (GByteArray *) g_array_set_size ((GArray *) array, length);
2930 : : }
2931 : :
2932 : : /**
2933 : : * g_byte_array_remove_index:
2934 : : * @array: a byte array
2935 : : * @index_: the index of the byte to remove
2936 : : *
2937 : : * Removes the byte at the given index from a `GByteArray`.
2938 : : * The following bytes are moved down one place.
2939 : : *
2940 : : * Returns: (transfer none): The `GByteArray`
2941 : : **/
2942 : : GByteArray*
2943 : 6 : g_byte_array_remove_index (GByteArray *array,
2944 : : guint index_)
2945 : : {
2946 : 6 : return (GByteArray *) g_array_remove_index ((GArray *) array, index_);
2947 : : }
2948 : :
2949 : : /**
2950 : : * g_byte_array_remove_index_fast:
2951 : : * @array: a byte array
2952 : : * @index_: the index of the byte to remove
2953 : : *
2954 : : * Removes the byte at the given index from a `GByteArray`. The last
2955 : : * element in the array is used to fill in the space, so this function
2956 : : * does not preserve the order of the `GByteArray`. But it is faster
2957 : : * than [func@GLib.ByteArray.remove_index].
2958 : : *
2959 : : * Returns: (transfer none): The `GByteArray`
2960 : : */
2961 : : GByteArray*
2962 : 5 : g_byte_array_remove_index_fast (GByteArray *array,
2963 : : guint index_)
2964 : : {
2965 : 5 : return (GByteArray *) g_array_remove_index_fast ((GArray *) array, index_);
2966 : : }
2967 : :
2968 : : /**
2969 : : * g_byte_array_remove_range:
2970 : : * @array: a byte array
2971 : : * @index_: the index of the first byte to remove
2972 : : * @length: the number of bytes to remove
2973 : : *
2974 : : * Removes the given number of bytes starting at the given index from a
2975 : : * `GByteArray`. The following elements are moved to close the gap.
2976 : : *
2977 : : * Returns: (transfer none): The `GByteArray`
2978 : : *
2979 : : * Since: 2.4
2980 : : */
2981 : : GByteArray*
2982 : 3 : g_byte_array_remove_range (GByteArray *array,
2983 : : guint index_,
2984 : : guint length)
2985 : : {
2986 : 3 : g_return_val_if_fail (array, NULL);
2987 : 3 : g_return_val_if_fail (index_ <= array->len, NULL);
2988 : 3 : g_return_val_if_fail (index_ <= G_MAXUINT - length, NULL);
2989 : 3 : g_return_val_if_fail (index_ + length <= array->len, NULL);
2990 : :
2991 : 3 : return (GByteArray *)g_array_remove_range ((GArray *)array, index_, length);
2992 : : }
2993 : :
2994 : : /**
2995 : : * g_byte_array_sort:
2996 : : * @array: a byte array
2997 : : * @compare_func: (scope call): the comparison function
2998 : : *
2999 : : * Sorts a byte array, using @compare_func which should be a
3000 : : * `qsort()`-style comparison function (returns less than zero for first
3001 : : * arg is less than second arg, zero for equal, greater than zero if
3002 : : * first arg is greater than second arg).
3003 : : *
3004 : : * If two array elements compare equal, their order in the sorted array
3005 : : * is undefined. If you want equal elements to keep their order (i.e.
3006 : : * you want a stable sort) you can write a comparison function that,
3007 : : * if two elements would otherwise compare equal, compares them by
3008 : : * their addresses.
3009 : : */
3010 : : void
3011 : 1 : g_byte_array_sort (GByteArray *array,
3012 : : GCompareFunc compare_func)
3013 : : {
3014 : 1 : g_array_sort ((GArray *)array, compare_func);
3015 : 1 : }
3016 : :
3017 : : /**
3018 : : * g_byte_array_sort_with_data:
3019 : : * @array: a byte array
3020 : : * @compare_func: (scope call): the comparison function
3021 : : * @user_data: the data to pass to @compare_func
3022 : : *
3023 : : * Like [func@GLib.ByteArray.sort], but the comparison function takes an extra
3024 : : * user data argument.
3025 : : */
3026 : : void
3027 : 1 : g_byte_array_sort_with_data (GByteArray *array,
3028 : : GCompareDataFunc compare_func,
3029 : : gpointer user_data)
3030 : : {
3031 : 1 : g_array_sort_with_data ((GArray *)array, compare_func, user_data);
3032 : 1 : }
|