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