1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GLib Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GLib at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25 /*
26 * MT safe
27 */
28
29 #include "config.h"
30
31 #include <string.h>
32 #include <stdlib.h>
33
34 #include "garray.h"
35
36 #include "gbytes.h"
37 #include "ghash.h"
38 #include "gslice.h"
39 #include "gmem.h"
40 #include "gtestutils.h"
41 #include "gthread.h"
42 #include "gmessages.h"
43 #include "gqsort.h"
44 #include "grefcount.h"
45
46 /**
47 * SECTION:arrays
48 * @title: Arrays
49 * @short_description: arrays of arbitrary elements which grow
50 * automatically as elements are added
51 *
52 * Arrays are similar to standard C arrays, except that they grow
53 * automatically as elements are added.
54 *
55 * Array elements can be of any size (though all elements of one array
56 * are the same size), and the array can be automatically cleared to
57 * '0's and zero-terminated.
58 *
59 * To create a new array use g_array_new().
60 *
61 * To add elements to an array, use g_array_append_val(),
62 * g_array_append_vals(), g_array_prepend_val(), and
63 * g_array_prepend_vals().
64 *
65 * To access an element of an array, use g_array_index().
66 *
67 * To set the size of an array, use g_array_set_size().
68 *
69 * To free an array, use g_array_free().
70 *
71 * Here is an example that stores integers in a #GArray:
72 * |[<!-- language="C" -->
73 * GArray *garray;
74 * gint i;
75 * // We create a new array to store gint values.
76 * // We don't want it zero-terminated or cleared to 0's.
77 * garray = g_array_new (FALSE, FALSE, sizeof (gint));
78 * for (i = 0; i < 10000; i++)
79 * g_array_append_val (garray, i);
80 * for (i = 0; i < 10000; i++)
81 * if (g_array_index (garray, gint, i) != i)
82 * g_print ("ERROR: got %d instead of %d\n",
83 * g_array_index (garray, gint, i), i);
84 * g_array_free (garray, TRUE);
85 * ]|
86 */
87
88 #define MIN_ARRAY_SIZE 16
89
90 typedef struct _GRealArray GRealArray;
91
92 /**
93 * GArray:
94 * @data: a pointer to the element data. The data may be moved as
95 * elements are added to the #GArray.
96 * @len: the number of elements in the #GArray not including the
97 * possible terminating zero element.
98 *
99 * Contains the public fields of a GArray.
100 */
101 struct _GRealArray
102 {
103 guint8 *data;
104 guint len;
105 guint alloc;
106 guint elt_size;
107 guint zero_terminated : 1;
108 guint clear : 1;
109 gatomicrefcount ref_count;
110 GDestroyNotify clear_func;
111 };
112
113 /**
114 * g_array_index:
115 * @a: a #GArray
116 * @t: the type of the elements
117 * @i: the index of the element to return
118 *
119 * Returns the element of a #GArray at the given index. The return
120 * value is cast to the given type.
121 *
122 * This example gets a pointer to an element in a #GArray:
123 * |[<!-- language="C" -->
124 * EDayViewEvent *event;
125 * // This gets a pointer to the 4th element in the array of
126 * // EDayViewEvent structs.
127 * event = &g_array_index (events, EDayViewEvent, 3);
128 * ]|
129 *
130 * Returns: the element of the #GArray at the index given by @i
131 */
132
133 #define g_array_elt_len(array,i) ((array)->elt_size * (i))
134 #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
135 #define g_array_elt_zero(array, pos, len) \
136 (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
137 #define g_array_zero_terminate(array) G_STMT_START{ \
138 if ((array)->zero_terminated) \
139 g_array_elt_zero ((array), (array)->len, 1); \
140 }G_STMT_END
141
142 static guint g_nearest_pow (guint num) G_GNUC_CONST;
143 static void g_array_maybe_expand (GRealArray *array,
144 guint len);
145
146 /**
147 * g_array_new:
148 * @zero_terminated: %TRUE if the array should have an extra element at
149 * the end which is set to 0
150 * @clear_: %TRUE if #GArray elements should be automatically cleared
151 * to 0 when they are allocated
152 * @element_size: the size of each element in bytes
153 *
154 * Creates a new #GArray with a reference count of 1.
155 *
156 * Returns: the new #GArray
157 */
158 GArray*
g_array_new(gboolean zero_terminated,gboolean clear,guint elt_size)159 g_array_new (gboolean zero_terminated,
160 gboolean clear,
161 guint elt_size)
162 {
163 g_return_val_if_fail (elt_size > 0, NULL);
164
165 return g_array_sized_new (zero_terminated, clear, elt_size, 0);
166 }
167
168 /**
169 * g_array_sized_new:
170 * @zero_terminated: %TRUE if the array should have an extra element at
171 * the end with all bits cleared
172 * @clear_: %TRUE if all bits in the array should be cleared to 0 on
173 * allocation
174 * @element_size: size of each element in the array
175 * @reserved_size: number of elements preallocated
176 *
177 * Creates a new #GArray with @reserved_size elements preallocated and
178 * a reference count of 1. This avoids frequent reallocation, if you
179 * are going to add many elements to the array. Note however that the
180 * size of the array is still 0.
181 *
182 * Returns: the new #GArray
183 */
184 GArray*
g_array_sized_new(gboolean zero_terminated,gboolean clear,guint elt_size,guint reserved_size)185 g_array_sized_new (gboolean zero_terminated,
186 gboolean clear,
187 guint elt_size,
188 guint reserved_size)
189 {
190 GRealArray *array;
191
192 g_return_val_if_fail (elt_size > 0, NULL);
193
194 array = g_slice_new (GRealArray);
195
196 array->data = NULL;
197 array->len = 0;
198 array->alloc = 0;
199 array->zero_terminated = (zero_terminated ? 1 : 0);
200 array->clear = (clear ? 1 : 0);
201 array->elt_size = elt_size;
202 array->clear_func = NULL;
203
204 g_atomic_ref_count_init (&array->ref_count);
205
206 if (array->zero_terminated || reserved_size != 0)
207 {
208 g_array_maybe_expand (array, reserved_size);
209 g_array_zero_terminate(array);
210 }
211
212 return (GArray*) array;
213 }
214
215 /**
216 * g_array_set_clear_func:
217 * @array: A #GArray
218 * @clear_func: a function to clear an element of @array
219 *
220 * Sets a function to clear an element of @array.
221 *
222 * The @clear_func will be called when an element in the array
223 * data segment is removed and when the array is freed and data
224 * segment is deallocated as well. @clear_func will be passed a
225 * pointer to the element to clear, rather than the element itself.
226 *
227 * Note that in contrast with other uses of #GDestroyNotify
228 * functions, @clear_func is expected to clear the contents of
229 * the array element it is given, but not free the element itself.
230 *
231 * Since: 2.32
232 */
233 void
g_array_set_clear_func(GArray * array,GDestroyNotify clear_func)234 g_array_set_clear_func (GArray *array,
235 GDestroyNotify clear_func)
236 {
237 GRealArray *rarray = (GRealArray *) array;
238
239 g_return_if_fail (array != NULL);
240
241 rarray->clear_func = clear_func;
242 }
243
244 /**
245 * g_array_ref:
246 * @array: A #GArray
247 *
248 * Atomically increments the reference count of @array by one.
249 * This function is thread-safe and may be called from any thread.
250 *
251 * Returns: The passed in #GArray
252 *
253 * Since: 2.22
254 */
255 GArray *
g_array_ref(GArray * array)256 g_array_ref (GArray *array)
257 {
258 GRealArray *rarray = (GRealArray*) array;
259 g_return_val_if_fail (array, NULL);
260
261 g_atomic_ref_count_inc (&rarray->ref_count);
262
263 return array;
264 }
265
266 typedef enum
267 {
268 FREE_SEGMENT = 1 << 0,
269 PRESERVE_WRAPPER = 1 << 1
270 } ArrayFreeFlags;
271
272 static gchar *array_free (GRealArray *, ArrayFreeFlags);
273
274 /**
275 * g_array_unref:
276 * @array: A #GArray
277 *
278 * Atomically decrements the reference count of @array by one. If the
279 * reference count drops to 0, all memory allocated by the array is
280 * released. This function is thread-safe and may be called from any
281 * thread.
282 *
283 * Since: 2.22
284 */
285 void
g_array_unref(GArray * array)286 g_array_unref (GArray *array)
287 {
288 GRealArray *rarray = (GRealArray*) array;
289 g_return_if_fail (array);
290
291 if (g_atomic_ref_count_dec (&rarray->ref_count))
292 array_free (rarray, FREE_SEGMENT);
293 }
294
295 /**
296 * g_array_get_element_size:
297 * @array: A #GArray
298 *
299 * Gets the size of the elements in @array.
300 *
301 * Returns: Size of each element, in bytes
302 *
303 * Since: 2.22
304 */
305 guint
g_array_get_element_size(GArray * array)306 g_array_get_element_size (GArray *array)
307 {
308 GRealArray *rarray = (GRealArray*) array;
309
310 g_return_val_if_fail (array, 0);
311
312 return rarray->elt_size;
313 }
314
315 /**
316 * g_array_free:
317 * @array: a #GArray
318 * @free_segment: if %TRUE the actual element data is freed as well
319 *
320 * Frees the memory allocated for the #GArray. If @free_segment is
321 * %TRUE it frees the memory block holding the elements as well. Pass
322 * %FALSE if you want to free the #GArray wrapper but preserve the
323 * underlying array for use elsewhere. If the reference count of
324 * @array is greater than one, the #GArray wrapper is preserved but
325 * the size of @array will be set to zero.
326 *
327 * If array contents point to dynamically-allocated memory, they should
328 * be freed separately if @free_seg is %TRUE and no @clear_func
329 * function has been set for @array.
330 *
331 * This function is not thread-safe. If using a #GArray from multiple
332 * threads, use only the atomic g_array_ref() and g_array_unref()
333 * functions.
334 *
335 * Returns: the element data if @free_segment is %FALSE, otherwise
336 * %NULL. The element data should be freed using g_free().
337 */
338 gchar*
g_array_free(GArray * farray,gboolean free_segment)339 g_array_free (GArray *farray,
340 gboolean free_segment)
341 {
342 GRealArray *array = (GRealArray*) farray;
343 ArrayFreeFlags flags;
344
345 g_return_val_if_fail (array, NULL);
346
347 flags = (free_segment ? FREE_SEGMENT : 0);
348
349 /* if others are holding a reference, preserve the wrapper but do free/return the data */
350 if (!g_atomic_ref_count_dec (&array->ref_count))
351 flags |= PRESERVE_WRAPPER;
352
353 return array_free (array, flags);
354 }
355
356 static gchar *
array_free(GRealArray * array,ArrayFreeFlags flags)357 array_free (GRealArray *array,
358 ArrayFreeFlags flags)
359 {
360 gchar *segment;
361
362 if (flags & FREE_SEGMENT)
363 {
364 if (array->clear_func != NULL)
365 {
366 guint i;
367
368 for (i = 0; i < array->len; i++)
369 array->clear_func (g_array_elt_pos (array, i));
370 }
371
372 g_free (array->data);
373 segment = NULL;
374 }
375 else
376 segment = (gchar*) array->data;
377
378 if (flags & PRESERVE_WRAPPER)
379 {
380 array->data = NULL;
381 array->len = 0;
382 array->alloc = 0;
383 }
384 else
385 {
386 g_slice_free1 (sizeof (GRealArray), array);
387 }
388
389 return segment;
390 }
391
392 /**
393 * g_array_append_vals:
394 * @array: a #GArray
395 * @data: (not nullable): a pointer to the elements to append to the end of the array
396 * @len: the number of elements to append
397 *
398 * Adds @len elements onto the end of the array.
399 *
400 * Returns: the #GArray
401 */
402 /**
403 * g_array_append_val:
404 * @a: a #GArray
405 * @v: the value to append to the #GArray
406 *
407 * Adds the value on to the end of the array. The array will grow in
408 * size automatically if necessary.
409 *
410 * g_array_append_val() is a macro which uses a reference to the value
411 * parameter @v. This means that you cannot use it with literal values
412 * such as "27". You must use variables.
413 *
414 * Returns: the #GArray
415 */
416 GArray*
g_array_append_vals(GArray * farray,gconstpointer data,guint len)417 g_array_append_vals (GArray *farray,
418 gconstpointer data,
419 guint len)
420 {
421 GRealArray *array = (GRealArray*) farray;
422
423 g_return_val_if_fail (array, NULL);
424
425 if (len == 0)
426 return farray;
427
428 g_array_maybe_expand (array, len);
429
430 memcpy (g_array_elt_pos (array, array->len), data,
431 g_array_elt_len (array, len));
432
433 array->len += len;
434
435 g_array_zero_terminate (array);
436
437 return farray;
438 }
439
440 /**
441 * g_array_prepend_vals:
442 * @array: a #GArray
443 * @data: (nullable): a pointer to the elements to prepend to the start of the array
444 * @len: the number of elements to prepend, which may be zero
445 *
446 * Adds @len elements onto the start of the array.
447 *
448 * @data may be %NULL if (and only if) @len is zero. If @len is zero, this
449 * function is a no-op.
450 *
451 * This operation is slower than g_array_append_vals() since the
452 * existing elements in the array have to be moved to make space for
453 * the new elements.
454 *
455 * Returns: the #GArray
456 */
457 /**
458 * g_array_prepend_val:
459 * @a: a #GArray
460 * @v: the value to prepend to the #GArray
461 *
462 * Adds the value on to the start of the array. The array will grow in
463 * size automatically if necessary.
464 *
465 * This operation is slower than g_array_append_val() since the
466 * existing elements in the array have to be moved to make space for
467 * the new element.
468 *
469 * g_array_prepend_val() is a macro which uses a reference to the value
470 * parameter @v. This means that you cannot use it with literal values
471 * such as "27". You must use variables.
472 *
473 * Returns: the #GArray
474 */
475 GArray*
g_array_prepend_vals(GArray * farray,gconstpointer data,guint len)476 g_array_prepend_vals (GArray *farray,
477 gconstpointer data,
478 guint len)
479 {
480 GRealArray *array = (GRealArray*) farray;
481
482 g_return_val_if_fail (array, NULL);
483
484 if (len == 0)
485 return farray;
486
487 g_array_maybe_expand (array, len);
488
489 memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0),
490 g_array_elt_len (array, array->len));
491
492 memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
493
494 array->len += len;
495
496 g_array_zero_terminate (array);
497
498 return farray;
499 }
500
501 /**
502 * g_array_insert_vals:
503 * @array: a #GArray
504 * @index_: the index to place the elements at
505 * @data: (nullable): a pointer to the elements to insert
506 * @len: the number of elements to insert
507 *
508 * Inserts @len elements into a #GArray at the given index.
509 *
510 * If @index_ is greater than the array’s current length, the array is expanded.
511 * The elements between the old end of the array and the newly inserted elements
512 * will be initialised to zero if the array was configured to clear elements;
513 * otherwise their values will be undefined.
514 *
515 * @data may be %NULL if (and only if) @len is zero. If @len is zero, this
516 * function is a no-op.
517 *
518 * Returns: the #GArray
519 */
520 /**
521 * g_array_insert_val:
522 * @a: a #GArray
523 * @i: the index to place the element at
524 * @v: the value to insert into the array
525 *
526 * Inserts an element into an array at the given index.
527 *
528 * g_array_insert_val() is a macro which uses a reference to the value
529 * parameter @v. This means that you cannot use it with literal values
530 * such as "27". You must use variables.
531 *
532 * Returns: the #GArray
533 */
534 GArray*
g_array_insert_vals(GArray * farray,guint index_,gconstpointer data,guint len)535 g_array_insert_vals (GArray *farray,
536 guint index_,
537 gconstpointer data,
538 guint len)
539 {
540 GRealArray *array = (GRealArray*) farray;
541
542 g_return_val_if_fail (array, NULL);
543
544 if (len == 0)
545 return farray;
546
547 /* Is the index off the end of the array, and hence do we need to over-allocate
548 * and clear some elements? */
549 if (index_ >= array->len)
550 {
551 g_array_maybe_expand (array, index_ - array->len + len);
552 return g_array_append_vals (g_array_set_size (farray, index_), data, len);
553 }
554
555 g_array_maybe_expand (array, len);
556
557 memmove (g_array_elt_pos (array, len + index_),
558 g_array_elt_pos (array, index_),
559 g_array_elt_len (array, array->len - index_));
560
561 memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len));
562
563 array->len += len;
564
565 g_array_zero_terminate (array);
566
567 return farray;
568 }
569
570 /**
571 * g_array_set_size:
572 * @array: a #GArray
573 * @length: the new size of the #GArray
574 *
575 * Sets the size of the array, expanding it if necessary. If the array
576 * was created with @clear_ set to %TRUE, the new elements are set to 0.
577 *
578 * Returns: the #GArray
579 */
580 GArray*
g_array_set_size(GArray * farray,guint length)581 g_array_set_size (GArray *farray,
582 guint length)
583 {
584 GRealArray *array = (GRealArray*) farray;
585
586 g_return_val_if_fail (array, NULL);
587
588 if (length > array->len)
589 {
590 g_array_maybe_expand (array, length - array->len);
591
592 if (array->clear)
593 g_array_elt_zero (array, array->len, length - array->len);
594 }
595 else if (length < array->len)
596 g_array_remove_range (farray, length, array->len - length);
597
598 array->len = length;
599
600 g_array_zero_terminate (array);
601
602 return farray;
603 }
604
605 /**
606 * g_array_remove_index:
607 * @array: a #GArray
608 * @index_: the index of the element to remove
609 *
610 * Removes the element at the given index from a #GArray. The following
611 * elements are moved down one place.
612 *
613 * Returns: the #GArray
614 */
615 GArray*
g_array_remove_index(GArray * farray,guint index_)616 g_array_remove_index (GArray *farray,
617 guint index_)
618 {
619 GRealArray* array = (GRealArray*) farray;
620
621 g_return_val_if_fail (array, NULL);
622
623 g_return_val_if_fail (index_ < array->len, NULL);
624
625 if (array->clear_func != NULL)
626 array->clear_func (g_array_elt_pos (array, index_));
627
628 if (index_ != array->len - 1)
629 memmove (g_array_elt_pos (array, index_),
630 g_array_elt_pos (array, index_ + 1),
631 g_array_elt_len (array, array->len - index_ - 1));
632
633 array->len -= 1;
634
635 if (G_UNLIKELY (g_mem_gc_friendly))
636 g_array_elt_zero (array, array->len, 1);
637 else
638 g_array_zero_terminate (array);
639
640 return farray;
641 }
642
643 /**
644 * g_array_remove_index_fast:
645 * @array: a @GArray
646 * @index_: the index of the element to remove
647 *
648 * Removes the element at the given index from a #GArray. The last
649 * element in the array is used to fill in the space, so this function
650 * does not preserve the order of the #GArray. But it is faster than
651 * g_array_remove_index().
652 *
653 * Returns: the #GArray
654 */
655 GArray*
g_array_remove_index_fast(GArray * farray,guint index_)656 g_array_remove_index_fast (GArray *farray,
657 guint index_)
658 {
659 GRealArray* array = (GRealArray*) farray;
660
661 g_return_val_if_fail (array, NULL);
662
663 g_return_val_if_fail (index_ < array->len, NULL);
664
665 if (array->clear_func != NULL)
666 array->clear_func (g_array_elt_pos (array, index_));
667
668 if (index_ != array->len - 1)
669 memcpy (g_array_elt_pos (array, index_),
670 g_array_elt_pos (array, array->len - 1),
671 g_array_elt_len (array, 1));
672
673 array->len -= 1;
674
675 if (G_UNLIKELY (g_mem_gc_friendly))
676 g_array_elt_zero (array, array->len, 1);
677 else
678 g_array_zero_terminate (array);
679
680 return farray;
681 }
682
683 /**
684 * g_array_remove_range:
685 * @array: a @GArray
686 * @index_: the index of the first element to remove
687 * @length: the number of elements to remove
688 *
689 * Removes the given number of elements starting at the given index
690 * from a #GArray. The following elements are moved to close the gap.
691 *
692 * Returns: the #GArray
693 *
694 * Since: 2.4
695 */
696 GArray*
g_array_remove_range(GArray * farray,guint index_,guint length)697 g_array_remove_range (GArray *farray,
698 guint index_,
699 guint length)
700 {
701 GRealArray *array = (GRealArray*) farray;
702
703 g_return_val_if_fail (array, NULL);
704 g_return_val_if_fail (index_ <= array->len, NULL);
705 g_return_val_if_fail (index_ + length <= array->len, NULL);
706
707 if (array->clear_func != NULL)
708 {
709 guint i;
710
711 for (i = 0; i < length; i++)
712 array->clear_func (g_array_elt_pos (array, index_ + i));
713 }
714
715 if (index_ + length != array->len)
716 memmove (g_array_elt_pos (array, index_),
717 g_array_elt_pos (array, index_ + length),
718 (array->len - (index_ + length)) * array->elt_size);
719
720 array->len -= length;
721 if (G_UNLIKELY (g_mem_gc_friendly))
722 g_array_elt_zero (array, array->len, length);
723 else
724 g_array_zero_terminate (array);
725
726 return farray;
727 }
728
729 /**
730 * g_array_sort:
731 * @array: a #GArray
732 * @compare_func: comparison function
733 *
734 * Sorts a #GArray using @compare_func which should be a qsort()-style
735 * comparison function (returns less than zero for first arg is less
736 * than second arg, zero for equal, greater zero if first arg is
737 * greater than second arg).
738 *
739 * This is guaranteed to be a stable sort since version 2.32.
740 */
741 void
g_array_sort(GArray * farray,GCompareFunc compare_func)742 g_array_sort (GArray *farray,
743 GCompareFunc compare_func)
744 {
745 GRealArray *array = (GRealArray*) farray;
746
747 g_return_if_fail (array != NULL);
748
749 /* Don't use qsort as we want a guaranteed stable sort */
750 g_qsort_with_data (array->data,
751 array->len,
752 array->elt_size,
753 (GCompareDataFunc)compare_func,
754 NULL);
755 }
756
757 /**
758 * g_array_sort_with_data:
759 * @array: a #GArray
760 * @compare_func: comparison function
761 * @user_data: data to pass to @compare_func
762 *
763 * Like g_array_sort(), but the comparison function receives an extra
764 * user data argument.
765 *
766 * This is guaranteed to be a stable sort since version 2.32.
767 *
768 * There used to be a comment here about making the sort stable by
769 * using the addresses of the elements in the comparison function.
770 * This did not actually work, so any such code should be removed.
771 */
772 void
g_array_sort_with_data(GArray * farray,GCompareDataFunc compare_func,gpointer user_data)773 g_array_sort_with_data (GArray *farray,
774 GCompareDataFunc compare_func,
775 gpointer user_data)
776 {
777 GRealArray *array = (GRealArray*) farray;
778
779 g_return_if_fail (array != NULL);
780
781 g_qsort_with_data (array->data,
782 array->len,
783 array->elt_size,
784 compare_func,
785 user_data);
786 }
787
788 /**
789 * g_array_binary_search:
790 * @array: a #GArray.
791 * @target: a pointer to the item to look up.
792 * @compare_func: A #GCompareFunc used to locate @target.
793 * @out_match_index: (optional) (out caller-allocates): return location
794 * for the index of the element, if found.
795 *
796 * Checks whether @target exists in @array by performing a binary
797 * search based on the given comparison function @compare_func which
798 * get pointers to items as arguments. If the element is found, %TRUE
799 * is returned and the element’s index is returned in @out_match_index
800 * (if non-%NULL). Otherwise, %FALSE is returned and @out_match_index
801 * is undefined. If @target exists multiple times in @array, the index
802 * of the first instance is returned. This search is using a binary
803 * search, so the @array must absolutely be sorted to return a correct
804 * result (if not, the function may produce false-negative).
805 *
806 * This example defines a comparison function and search an element in a #GArray:
807 * |[<!-- language="C" -->
808 * static gint*
809 * cmpint (gconstpointer a, gconstpointer b)
810 * {
811 * const gint *_a = a;
812 * const gint *_b = b;
813 *
814 * return *_a - *_b;
815 * }
816 * ...
817 * gint i = 424242;
818 * guint matched_index;
819 * gboolean result = g_array_binary_search (garray, &i, cmpint, &matched_index);
820 * ...
821 * ]|
822 *
823 * Returns: %TRUE if @target is one of the elements of @array, %FALSE otherwise.
824 *
825 * Since: 2.62
826 */
827 gboolean
g_array_binary_search(GArray * array,gconstpointer target,GCompareFunc compare_func,guint * out_match_index)828 g_array_binary_search (GArray *array,
829 gconstpointer target,
830 GCompareFunc compare_func,
831 guint *out_match_index)
832 {
833 gboolean result = FALSE;
834 GRealArray *_array = (GRealArray *) array;
835 guint left, middle, right;
836 gint val;
837
838 g_return_val_if_fail (_array != NULL, FALSE);
839 g_return_val_if_fail (compare_func != NULL, FALSE);
840
841 if (G_LIKELY(_array->len))
842 {
843 left = 0;
844 right = _array->len - 1;
845
846 while (left <= right)
847 {
848 middle = left + (right - left) / 2;
849
850 val = compare_func (_array->data + (_array->elt_size * middle), target);
851 if (val == 0)
852 {
853 result = TRUE;
854 break;
855 }
856 else if (val < 0)
857 left = middle + 1;
858 else if (/* val > 0 && */ middle > 0)
859 right = middle - 1;
860 else
861 break; /* element not found */
862 }
863 }
864
865 if (result && out_match_index != NULL)
866 *out_match_index = middle;
867
868 return result;
869 }
870
871 /* Returns the smallest power of 2 greater than n, or n if
872 * such power does not fit in a guint
873 */
874 static guint
g_nearest_pow(guint num)875 g_nearest_pow (guint num)
876 {
877 guint n = num - 1;
878
879 g_assert (num > 0);
880
881 n |= n >> 1;
882 n |= n >> 2;
883 n |= n >> 4;
884 n |= n >> 8;
885 n |= n >> 16;
886 #if SIZEOF_INT == 8
887 n |= n >> 32;
888 #endif
889
890 return n + 1;
891 }
892
893 static void
g_array_maybe_expand(GRealArray * array,guint len)894 g_array_maybe_expand (GRealArray *array,
895 guint len)
896 {
897 guint want_alloc;
898
899 /* Detect potential overflow */
900 if G_UNLIKELY ((G_MAXUINT - array->len) < len)
901 g_error ("adding %u to array would overflow", len);
902
903 want_alloc = g_array_elt_len (array, array->len + len +
904 array->zero_terminated);
905
906 if (want_alloc > array->alloc)
907 {
908 want_alloc = g_nearest_pow (want_alloc);
909 want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
910
911 array->data = g_realloc (array->data, want_alloc);
912
913 if (G_UNLIKELY (g_mem_gc_friendly))
914 memset (array->data + array->alloc, 0, want_alloc - array->alloc);
915
916 array->alloc = want_alloc;
917 }
918 }
919
920 /**
921 * SECTION:arrays_pointer
922 * @title: Pointer Arrays
923 * @short_description: arrays of pointers to any type of data, which
924 * grow automatically as new elements are added
925 *
926 * Pointer Arrays are similar to Arrays but are used only for storing
927 * pointers.
928 *
929 * If you remove elements from the array, elements at the end of the
930 * array are moved into the space previously occupied by the removed
931 * element. This means that you should not rely on the index of particular
932 * elements remaining the same. You should also be careful when deleting
933 * elements while iterating over the array.
934 *
935 * To create a pointer array, use g_ptr_array_new().
936 *
937 * To add elements to a pointer array, use g_ptr_array_add().
938 *
939 * To remove elements from a pointer array, use g_ptr_array_remove(),
940 * g_ptr_array_remove_index() or g_ptr_array_remove_index_fast().
941 *
942 * To access an element of a pointer array, use g_ptr_array_index().
943 *
944 * To set the size of a pointer array, use g_ptr_array_set_size().
945 *
946 * To free a pointer array, use g_ptr_array_free().
947 *
948 * An example using a #GPtrArray:
949 * |[<!-- language="C" -->
950 * GPtrArray *array;
951 * gchar *string1 = "one";
952 * gchar *string2 = "two";
953 * gchar *string3 = "three";
954 *
955 * array = g_ptr_array_new ();
956 * g_ptr_array_add (array, (gpointer) string1);
957 * g_ptr_array_add (array, (gpointer) string2);
958 * g_ptr_array_add (array, (gpointer) string3);
959 *
960 * if (g_ptr_array_index (array, 0) != (gpointer) string1)
961 * g_print ("ERROR: got %p instead of %p\n",
962 * g_ptr_array_index (array, 0), string1);
963 *
964 * g_ptr_array_free (array, TRUE);
965 * ]|
966 */
967
968 typedef struct _GRealPtrArray GRealPtrArray;
969
970 /**
971 * GPtrArray:
972 * @pdata: points to the array of pointers, which may be moved when the
973 * array grows
974 * @len: number of pointers in the array
975 *
976 * Contains the public fields of a pointer array.
977 */
978 struct _GRealPtrArray
979 {
980 gpointer *pdata;
981 guint len;
982 guint alloc;
983 gatomicrefcount ref_count;
984 GDestroyNotify element_free_func;
985 };
986
987 /**
988 * g_ptr_array_index:
989 * @array: a #GPtrArray
990 * @index_: the index of the pointer to return
991 *
992 * Returns the pointer at the given index of the pointer array.
993 *
994 * This does not perform bounds checking on the given @index_,
995 * so you are responsible for checking it against the array length.
996 *
997 * Returns: the pointer at the given index
998 */
999
1000 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
1001 guint len);
1002
1003 /**
1004 * g_ptr_array_new:
1005 *
1006 * Creates a new #GPtrArray with a reference count of 1.
1007 *
1008 * Returns: the new #GPtrArray
1009 */
1010 GPtrArray*
g_ptr_array_new(void)1011 g_ptr_array_new (void)
1012 {
1013 return g_ptr_array_sized_new (0);
1014 }
1015
1016 /**
1017 * g_ptr_array_copy:
1018 * @array: #GPtrArray to duplicate
1019 * @func: (nullable): a copy function used to copy every element in the array
1020 * @user_data: user data passed to the copy function @func, or %NULL
1021 *
1022 * Makes a full (deep) copy of a #GPtrArray.
1023 *
1024 * @func, as a #GCopyFunc, takes two arguments, the data to be copied
1025 * and a @user_data pointer. On common processor architectures, it's safe to
1026 * pass %NULL as @user_data if the copy function takes only one argument. You
1027 * may get compiler warnings from this though if compiling with GCC’s
1028 * `-Wcast-function-type` warning.
1029 *
1030 * If @func is %NULL, then only the pointers (and not what they are
1031 * pointing to) are copied to the new #GPtrArray.
1032 *
1033 * The copy of @array will have the same #GDestroyNotify for its elements as
1034 * @array.
1035 *
1036 * Returns: (transfer full): a deep copy of the initial #GPtrArray.
1037 *
1038 * Since: 2.62
1039 **/
1040 GPtrArray *
g_ptr_array_copy(GPtrArray * array,GCopyFunc func,gpointer user_data)1041 g_ptr_array_copy (GPtrArray *array,
1042 GCopyFunc func,
1043 gpointer user_data)
1044 {
1045 gsize i;
1046 GPtrArray *new_array;
1047
1048 g_return_val_if_fail (array != NULL, NULL);
1049
1050 new_array = g_ptr_array_sized_new (array->len);
1051 g_ptr_array_set_free_func (new_array, ((GRealPtrArray *) array)->element_free_func);
1052
1053 if (func != NULL)
1054 {
1055 for (i = 0; i < array->len; i++)
1056 new_array->pdata[i] = func (array->pdata[i], user_data);
1057 }
1058 else
1059 {
1060 memcpy (new_array->pdata, array->pdata,
1061 array->len * sizeof (*array->pdata));
1062 }
1063
1064 new_array->len = array->len;
1065
1066 return new_array;
1067 }
1068
1069 /**
1070 * g_ptr_array_sized_new:
1071 * @reserved_size: number of pointers preallocated
1072 *
1073 * Creates a new #GPtrArray with @reserved_size pointers preallocated
1074 * and a reference count of 1. This avoids frequent reallocation, if
1075 * you are going to add many pointers to the array. Note however that
1076 * the size of the array is still 0.
1077 *
1078 * Returns: the new #GPtrArray
1079 */
1080 GPtrArray*
g_ptr_array_sized_new(guint reserved_size)1081 g_ptr_array_sized_new (guint reserved_size)
1082 {
1083 GRealPtrArray *array;
1084
1085 array = g_slice_new (GRealPtrArray);
1086
1087 array->pdata = NULL;
1088 array->len = 0;
1089 array->alloc = 0;
1090 array->element_free_func = NULL;
1091
1092 g_atomic_ref_count_init (&array->ref_count);
1093
1094 if (reserved_size != 0)
1095 g_ptr_array_maybe_expand (array, reserved_size);
1096
1097 return (GPtrArray*) array;
1098 }
1099
1100 /**
1101 * g_array_copy:
1102 * @array: A #GArray.
1103 *
1104 * Create a shallow copy of a #GArray. If the array elements consist of
1105 * pointers to data, the pointers are copied but the actual data is not.
1106 *
1107 * Returns: (transfer container): A copy of @array.
1108 *
1109 * Since: 2.62
1110 **/
1111 GArray *
g_array_copy(GArray * array)1112 g_array_copy (GArray *array)
1113 {
1114 GRealArray *rarray = (GRealArray *) array;
1115 GRealArray *new_rarray;
1116
1117 g_return_val_if_fail (rarray != NULL, NULL);
1118
1119 new_rarray =
1120 (GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear,
1121 rarray->elt_size, rarray->len);
1122 new_rarray->len = rarray->len;
1123 memcpy (new_rarray->data, rarray->data, rarray->alloc);
1124
1125 return (GArray *) new_rarray;
1126 }
1127
1128 /**
1129 * g_ptr_array_new_with_free_func:
1130 * @element_free_func: (nullable): A function to free elements with
1131 * destroy @array or %NULL
1132 *
1133 * Creates a new #GPtrArray with a reference count of 1 and use
1134 * @element_free_func for freeing each element when the array is destroyed
1135 * either via g_ptr_array_unref(), when g_ptr_array_free() is called with
1136 * @free_segment set to %TRUE or when removing elements.
1137 *
1138 * Returns: A new #GPtrArray
1139 *
1140 * Since: 2.22
1141 */
1142 GPtrArray*
g_ptr_array_new_with_free_func(GDestroyNotify element_free_func)1143 g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
1144 {
1145 GPtrArray *array;
1146
1147 array = g_ptr_array_new ();
1148 g_ptr_array_set_free_func (array, element_free_func);
1149
1150 return array;
1151 }
1152
1153 /**
1154 * g_ptr_array_new_full:
1155 * @reserved_size: number of pointers preallocated
1156 * @element_free_func: (nullable): A function to free elements with
1157 * destroy @array or %NULL
1158 *
1159 * Creates a new #GPtrArray with @reserved_size pointers preallocated
1160 * and a reference count of 1. This avoids frequent reallocation, if
1161 * you are going to add many pointers to the array. Note however that
1162 * the size of the array is still 0. It also set @element_free_func
1163 * for freeing each element when the array is destroyed either via
1164 * g_ptr_array_unref(), when g_ptr_array_free() is called with
1165 * @free_segment set to %TRUE or when removing elements.
1166 *
1167 * Returns: A new #GPtrArray
1168 *
1169 * Since: 2.30
1170 */
1171 GPtrArray*
g_ptr_array_new_full(guint reserved_size,GDestroyNotify element_free_func)1172 g_ptr_array_new_full (guint reserved_size,
1173 GDestroyNotify element_free_func)
1174 {
1175 GPtrArray *array;
1176
1177 array = g_ptr_array_sized_new (reserved_size);
1178 g_ptr_array_set_free_func (array, element_free_func);
1179
1180 return array;
1181 }
1182
1183 /**
1184 * g_ptr_array_set_free_func:
1185 * @array: A #GPtrArray
1186 * @element_free_func: (nullable): A function to free elements with
1187 * destroy @array or %NULL
1188 *
1189 * Sets a function for freeing each element when @array is destroyed
1190 * either via g_ptr_array_unref(), when g_ptr_array_free() is called
1191 * with @free_segment set to %TRUE or when removing elements.
1192 *
1193 * Since: 2.22
1194 */
1195 void
g_ptr_array_set_free_func(GPtrArray * array,GDestroyNotify element_free_func)1196 g_ptr_array_set_free_func (GPtrArray *array,
1197 GDestroyNotify element_free_func)
1198 {
1199 GRealPtrArray *rarray = (GRealPtrArray *)array;
1200
1201 g_return_if_fail (array);
1202
1203 rarray->element_free_func = element_free_func;
1204 }
1205
1206 /**
1207 * g_ptr_array_ref:
1208 * @array: a #GPtrArray
1209 *
1210 * Atomically increments the reference count of @array by one.
1211 * This function is thread-safe and may be called from any thread.
1212 *
1213 * Returns: The passed in #GPtrArray
1214 *
1215 * Since: 2.22
1216 */
1217 GPtrArray*
g_ptr_array_ref(GPtrArray * array)1218 g_ptr_array_ref (GPtrArray *array)
1219 {
1220 GRealPtrArray *rarray = (GRealPtrArray *)array;
1221
1222 g_return_val_if_fail (array, NULL);
1223
1224 g_atomic_ref_count_inc (&rarray->ref_count);
1225
1226 return array;
1227 }
1228
1229 static gpointer *ptr_array_free (GPtrArray *, ArrayFreeFlags);
1230
1231 /**
1232 * g_ptr_array_unref:
1233 * @array: A #GPtrArray
1234 *
1235 * Atomically decrements the reference count of @array by one. If the
1236 * reference count drops to 0, the effect is the same as calling
1237 * g_ptr_array_free() with @free_segment set to %TRUE. This function
1238 * is thread-safe and may be called from any thread.
1239 *
1240 * Since: 2.22
1241 */
1242 void
g_ptr_array_unref(GPtrArray * array)1243 g_ptr_array_unref (GPtrArray *array)
1244 {
1245 GRealPtrArray *rarray = (GRealPtrArray *)array;
1246
1247 g_return_if_fail (array);
1248
1249 if (g_atomic_ref_count_dec (&rarray->ref_count))
1250 ptr_array_free (array, FREE_SEGMENT);
1251 }
1252
1253 /**
1254 * g_ptr_array_free:
1255 * @array: a #GPtrArray
1256 * @free_seg: if %TRUE the actual pointer array is freed as well
1257 *
1258 * Frees the memory allocated for the #GPtrArray. If @free_seg is %TRUE
1259 * it frees the memory block holding the elements as well. Pass %FALSE
1260 * if you want to free the #GPtrArray wrapper but preserve the
1261 * underlying array for use elsewhere. If the reference count of @array
1262 * is greater than one, the #GPtrArray wrapper is preserved but the
1263 * size of @array will be set to zero.
1264 *
1265 * If array contents point to dynamically-allocated memory, they should
1266 * be freed separately if @free_seg is %TRUE and no #GDestroyNotify
1267 * function has been set for @array.
1268 *
1269 * This function is not thread-safe. If using a #GPtrArray from multiple
1270 * threads, use only the atomic g_ptr_array_ref() and g_ptr_array_unref()
1271 * functions.
1272 *
1273 * Returns: the pointer array if @free_seg is %FALSE, otherwise %NULL.
1274 * The pointer array should be freed using g_free().
1275 */
1276 gpointer*
g_ptr_array_free(GPtrArray * array,gboolean free_segment)1277 g_ptr_array_free (GPtrArray *array,
1278 gboolean free_segment)
1279 {
1280 GRealPtrArray *rarray = (GRealPtrArray *)array;
1281 ArrayFreeFlags flags;
1282
1283 g_return_val_if_fail (rarray, NULL);
1284
1285 flags = (free_segment ? FREE_SEGMENT : 0);
1286
1287 /* if others are holding a reference, preserve the wrapper but
1288 * do free/return the data
1289 */
1290 if (!g_atomic_ref_count_dec (&rarray->ref_count))
1291 flags |= PRESERVE_WRAPPER;
1292
1293 return ptr_array_free (array, flags);
1294 }
1295
1296 static gpointer *
ptr_array_free(GPtrArray * array,ArrayFreeFlags flags)1297 ptr_array_free (GPtrArray *array,
1298 ArrayFreeFlags flags)
1299 {
1300 GRealPtrArray *rarray = (GRealPtrArray *)array;
1301 gpointer *segment;
1302
1303 if (flags & FREE_SEGMENT)
1304 {
1305 /* Data here is stolen and freed manually. It is an
1306 * error to attempt to access the array data (including
1307 * mutating the array bounds) during destruction).
1308 *
1309 * https://bugzilla.gnome.org/show_bug.cgi?id=769064
1310 */
1311 gpointer *stolen_pdata = g_steal_pointer (&rarray->pdata);
1312 if (rarray->element_free_func != NULL)
1313 {
1314 gsize i;
1315 for (i = 0; i < rarray->len; ++i)
1316 rarray->element_free_func (stolen_pdata[i]);
1317 }
1318
1319 g_free (stolen_pdata);
1320 segment = NULL;
1321 }
1322 else
1323 segment = rarray->pdata;
1324
1325 if (flags & PRESERVE_WRAPPER)
1326 {
1327 rarray->pdata = NULL;
1328 rarray->len = 0;
1329 rarray->alloc = 0;
1330 }
1331 else
1332 {
1333 g_slice_free1 (sizeof (GRealPtrArray), rarray);
1334 }
1335
1336 return segment;
1337 }
1338
1339 static void
g_ptr_array_maybe_expand(GRealPtrArray * array,guint len)1340 g_ptr_array_maybe_expand (GRealPtrArray *array,
1341 guint len)
1342 {
1343 /* Detect potential overflow */
1344 if G_UNLIKELY ((G_MAXUINT - array->len) < len)
1345 g_error ("adding %u to array would overflow", len);
1346
1347 if ((array->len + len) > array->alloc)
1348 {
1349 guint old_alloc = array->alloc;
1350 array->alloc = g_nearest_pow (array->len + len);
1351 array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
1352 array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc);
1353 if (G_UNLIKELY (g_mem_gc_friendly))
1354 for ( ; old_alloc < array->alloc; old_alloc++)
1355 array->pdata [old_alloc] = NULL;
1356 }
1357 }
1358
1359 /**
1360 * g_ptr_array_set_size:
1361 * @array: a #GPtrArray
1362 * @length: the new length of the pointer array
1363 *
1364 * Sets the size of the array. When making the array larger,
1365 * newly-added elements will be set to %NULL. When making it smaller,
1366 * if @array has a non-%NULL #GDestroyNotify function then it will be
1367 * called for the removed elements.
1368 */
1369 void
g_ptr_array_set_size(GPtrArray * array,gint length)1370 g_ptr_array_set_size (GPtrArray *array,
1371 gint length)
1372 {
1373 GRealPtrArray *rarray = (GRealPtrArray *)array;
1374 guint length_unsigned;
1375
1376 g_return_if_fail (rarray);
1377 g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL));
1378 g_return_if_fail (length >= 0);
1379
1380 length_unsigned = (guint) length;
1381
1382 if (length_unsigned > rarray->len)
1383 {
1384 guint i;
1385 g_ptr_array_maybe_expand (rarray, (length_unsigned - rarray->len));
1386 /* This is not
1387 * memset (array->pdata + array->len, 0,
1388 * sizeof (gpointer) * (length_unsigned - array->len));
1389 * to make it really portable. Remember (void*)NULL needn't be
1390 * bitwise zero. It of course is silly not to use memset (..,0,..).
1391 */
1392 for (i = rarray->len; i < length_unsigned; i++)
1393 rarray->pdata[i] = NULL;
1394 }
1395 else if (length_unsigned < rarray->len)
1396 g_ptr_array_remove_range (array, length_unsigned, rarray->len - length_unsigned);
1397
1398 rarray->len = length_unsigned;
1399 }
1400
1401 static gpointer
ptr_array_remove_index(GPtrArray * array,guint index_,gboolean fast,gboolean free_element)1402 ptr_array_remove_index (GPtrArray *array,
1403 guint index_,
1404 gboolean fast,
1405 gboolean free_element)
1406 {
1407 GRealPtrArray *rarray = (GRealPtrArray *) array;
1408 gpointer result;
1409
1410 g_return_val_if_fail (rarray, NULL);
1411 g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL);
1412
1413 g_return_val_if_fail (index_ < rarray->len, NULL);
1414
1415 result = rarray->pdata[index_];
1416
1417 if (rarray->element_free_func != NULL && free_element)
1418 rarray->element_free_func (rarray->pdata[index_]);
1419
1420 if (index_ != rarray->len - 1 && !fast)
1421 memmove (rarray->pdata + index_, rarray->pdata + index_ + 1,
1422 sizeof (gpointer) * (rarray->len - index_ - 1));
1423 else if (index_ != rarray->len - 1)
1424 rarray->pdata[index_] = rarray->pdata[rarray->len - 1];
1425
1426 rarray->len -= 1;
1427
1428 if (G_UNLIKELY (g_mem_gc_friendly))
1429 rarray->pdata[rarray->len] = NULL;
1430
1431 return result;
1432 }
1433
1434 /**
1435 * g_ptr_array_remove_index:
1436 * @array: a #GPtrArray
1437 * @index_: the index of the pointer to remove
1438 *
1439 * Removes the pointer at the given index from the pointer array.
1440 * The following elements are moved down one place. If @array has
1441 * a non-%NULL #GDestroyNotify function it is called for the removed
1442 * element. If so, the return value from this function will potentially point
1443 * to freed memory (depending on the #GDestroyNotify implementation).
1444 *
1445 * Returns: (nullable): the pointer which was removed
1446 */
1447 gpointer
g_ptr_array_remove_index(GPtrArray * array,guint index_)1448 g_ptr_array_remove_index (GPtrArray *array,
1449 guint index_)
1450 {
1451 return ptr_array_remove_index (array, index_, FALSE, TRUE);
1452 }
1453
1454 /**
1455 * g_ptr_array_remove_index_fast:
1456 * @array: a #GPtrArray
1457 * @index_: the index of the pointer to remove
1458 *
1459 * Removes the pointer at the given index from the pointer array.
1460 * The last element in the array is used to fill in the space, so
1461 * this function does not preserve the order of the array. But it
1462 * is faster than g_ptr_array_remove_index(). If @array has a non-%NULL
1463 * #GDestroyNotify function it is called for the removed element. If so, the
1464 * return value from this function will potentially point to freed memory
1465 * (depending on the #GDestroyNotify implementation).
1466 *
1467 * Returns: (nullable): the pointer which was removed
1468 */
1469 gpointer
g_ptr_array_remove_index_fast(GPtrArray * array,guint index_)1470 g_ptr_array_remove_index_fast (GPtrArray *array,
1471 guint index_)
1472 {
1473 return ptr_array_remove_index (array, index_, TRUE, TRUE);
1474 }
1475
1476 /**
1477 * g_ptr_array_steal_index:
1478 * @array: a #GPtrArray
1479 * @index_: the index of the pointer to steal
1480 *
1481 * Removes the pointer at the given index from the pointer array.
1482 * The following elements are moved down one place. The #GDestroyNotify for
1483 * @array is *not* called on the removed element; ownership is transferred to
1484 * the caller of this function.
1485 *
1486 * Returns: (transfer full) (nullable): the pointer which was removed
1487 * Since: 2.58
1488 */
1489 gpointer
g_ptr_array_steal_index(GPtrArray * array,guint index_)1490 g_ptr_array_steal_index (GPtrArray *array,
1491 guint index_)
1492 {
1493 return ptr_array_remove_index (array, index_, FALSE, FALSE);
1494 }
1495
1496 /**
1497 * g_ptr_array_steal_index_fast:
1498 * @array: a #GPtrArray
1499 * @index_: the index of the pointer to steal
1500 *
1501 * Removes the pointer at the given index from the pointer array.
1502 * The last element in the array is used to fill in the space, so
1503 * this function does not preserve the order of the array. But it
1504 * is faster than g_ptr_array_steal_index(). The #GDestroyNotify for @array is
1505 * *not* called on the removed element; ownership is transferred to the caller
1506 * of this function.
1507 *
1508 * Returns: (transfer full) (nullable): the pointer which was removed
1509 * Since: 2.58
1510 */
1511 gpointer
g_ptr_array_steal_index_fast(GPtrArray * array,guint index_)1512 g_ptr_array_steal_index_fast (GPtrArray *array,
1513 guint index_)
1514 {
1515 return ptr_array_remove_index (array, index_, TRUE, FALSE);
1516 }
1517
1518 /**
1519 * g_ptr_array_remove_range:
1520 * @array: a @GPtrArray
1521 * @index_: the index of the first pointer to remove
1522 * @length: the number of pointers to remove
1523 *
1524 * Removes the given number of pointers starting at the given index
1525 * from a #GPtrArray. The following elements are moved to close the
1526 * gap. If @array has a non-%NULL #GDestroyNotify function it is
1527 * called for the removed elements.
1528 *
1529 * Returns: the @array
1530 *
1531 * Since: 2.4
1532 */
1533 GPtrArray*
g_ptr_array_remove_range(GPtrArray * array,guint index_,guint length)1534 g_ptr_array_remove_range (GPtrArray *array,
1535 guint index_,
1536 guint length)
1537 {
1538 GRealPtrArray *rarray = (GRealPtrArray *)array;
1539 guint n;
1540
1541 g_return_val_if_fail (rarray != NULL, NULL);
1542 g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL);
1543 g_return_val_if_fail (index_ <= rarray->len, NULL);
1544 g_return_val_if_fail (index_ + length <= rarray->len, NULL);
1545
1546 if (rarray->element_free_func != NULL)
1547 {
1548 for (n = index_; n < index_ + length; n++)
1549 rarray->element_free_func (rarray->pdata[n]);
1550 }
1551
1552 if (index_ + length != rarray->len)
1553 {
1554 memmove (&rarray->pdata[index_],
1555 &rarray->pdata[index_ + length],
1556 (rarray->len - (index_ + length)) * sizeof (gpointer));
1557 }
1558
1559 rarray->len -= length;
1560 if (G_UNLIKELY (g_mem_gc_friendly))
1561 {
1562 guint i;
1563 for (i = 0; i < length; i++)
1564 rarray->pdata[rarray->len + i] = NULL;
1565 }
1566
1567 return array;
1568 }
1569
1570 /**
1571 * g_ptr_array_remove:
1572 * @array: a #GPtrArray
1573 * @data: the pointer to remove
1574 *
1575 * Removes the first occurrence of the given pointer from the pointer
1576 * array. The following elements are moved down one place. If @array
1577 * has a non-%NULL #GDestroyNotify function it is called for the
1578 * removed element.
1579 *
1580 * It returns %TRUE if the pointer was removed, or %FALSE if the
1581 * pointer was not found.
1582 *
1583 * Returns: %TRUE if the pointer is removed, %FALSE if the pointer
1584 * is not found in the array
1585 */
1586 gboolean
g_ptr_array_remove(GPtrArray * array,gpointer data)1587 g_ptr_array_remove (GPtrArray *array,
1588 gpointer data)
1589 {
1590 guint i;
1591
1592 g_return_val_if_fail (array, FALSE);
1593 g_return_val_if_fail (array->len == 0 || (array->len != 0 && array->pdata != NULL), FALSE);
1594
1595 for (i = 0; i < array->len; i += 1)
1596 {
1597 if (array->pdata[i] == data)
1598 {
1599 g_ptr_array_remove_index (array, i);
1600 return TRUE;
1601 }
1602 }
1603
1604 return FALSE;
1605 }
1606
1607 /**
1608 * g_ptr_array_remove_fast:
1609 * @array: a #GPtrArray
1610 * @data: the pointer to remove
1611 *
1612 * Removes the first occurrence of the given pointer from the pointer
1613 * array. The last element in the array is used to fill in the space,
1614 * so this function does not preserve the order of the array. But it
1615 * is faster than g_ptr_array_remove(). If @array has a non-%NULL
1616 * #GDestroyNotify function it is called for the removed element.
1617 *
1618 * It returns %TRUE if the pointer was removed, or %FALSE if the
1619 * pointer was not found.
1620 *
1621 * Returns: %TRUE if the pointer was found in the array
1622 */
1623 gboolean
g_ptr_array_remove_fast(GPtrArray * array,gpointer data)1624 g_ptr_array_remove_fast (GPtrArray *array,
1625 gpointer data)
1626 {
1627 GRealPtrArray *rarray = (GRealPtrArray *)array;
1628 guint i;
1629
1630 g_return_val_if_fail (rarray, FALSE);
1631 g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), FALSE);
1632
1633 for (i = 0; i < rarray->len; i += 1)
1634 {
1635 if (rarray->pdata[i] == data)
1636 {
1637 g_ptr_array_remove_index_fast (array, i);
1638 return TRUE;
1639 }
1640 }
1641
1642 return FALSE;
1643 }
1644
1645 /**
1646 * g_ptr_array_add:
1647 * @array: a #GPtrArray
1648 * @data: the pointer to add
1649 *
1650 * Adds a pointer to the end of the pointer array. The array will grow
1651 * in size automatically if necessary.
1652 */
1653 void
g_ptr_array_add(GPtrArray * array,gpointer data)1654 g_ptr_array_add (GPtrArray *array,
1655 gpointer data)
1656 {
1657 GRealPtrArray *rarray = (GRealPtrArray *)array;
1658
1659 g_return_if_fail (rarray);
1660 g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL));
1661
1662 g_ptr_array_maybe_expand (rarray, 1);
1663
1664 rarray->pdata[rarray->len++] = data;
1665 }
1666
1667 /**
1668 * g_ptr_array_extend:
1669 * @array_to_extend: a #GPtrArray.
1670 * @array: (transfer none): a #GPtrArray to add to the end of @array_to_extend.
1671 * @func: (nullable): a copy function used to copy every element in the array
1672 * @user_data: user data passed to the copy function @func, or %NULL
1673 *
1674 * Adds all pointers of @array to the end of the array @array_to_extend.
1675 * The array will grow in size automatically if needed. @array_to_extend is
1676 * modified in-place.
1677 *
1678 * @func, as a #GCopyFunc, takes two arguments, the data to be copied
1679 * and a @user_data pointer. On common processor architectures, it's safe to
1680 * pass %NULL as @user_data if the copy function takes only one argument. You
1681 * may get compiler warnings from this though if compiling with GCC’s
1682 * `-Wcast-function-type` warning.
1683 *
1684 * If @func is %NULL, then only the pointers (and not what they are
1685 * pointing to) are copied to the new #GPtrArray.
1686 *
1687 * Since: 2.62
1688 **/
1689 void
g_ptr_array_extend(GPtrArray * array_to_extend,GPtrArray * array,GCopyFunc func,gpointer user_data)1690 g_ptr_array_extend (GPtrArray *array_to_extend,
1691 GPtrArray *array,
1692 GCopyFunc func,
1693 gpointer user_data)
1694 {
1695 GRealPtrArray *rarray_to_extend = (GRealPtrArray *) array_to_extend;
1696 gsize i;
1697
1698 g_return_if_fail (array_to_extend != NULL);
1699 g_return_if_fail (array != NULL);
1700
1701 g_ptr_array_maybe_expand (rarray_to_extend, array->len);
1702
1703 if (func != NULL)
1704 {
1705 for (i = 0; i < array->len; i++)
1706 rarray_to_extend->pdata[i + rarray_to_extend->len] =
1707 func (array->pdata[i], user_data);
1708 }
1709 else
1710 {
1711 memcpy (rarray_to_extend->pdata + rarray_to_extend->len, array->pdata,
1712 array->len * sizeof (*array->pdata));
1713 }
1714
1715 rarray_to_extend->len += array->len;
1716 }
1717
1718 /**
1719 * g_ptr_array_extend_and_steal:
1720 * @array_to_extend: (transfer none): a #GPtrArray.
1721 * @array: (transfer container): a #GPtrArray to add to the end of
1722 * @array_to_extend.
1723 *
1724 * Adds all the pointers in @array to the end of @array_to_extend, transferring
1725 * ownership of each element from @array to @array_to_extend and modifying
1726 * @array_to_extend in-place. @array is then freed.
1727 *
1728 * As with g_ptr_array_free(), @array will be destroyed if its reference count
1729 * is 1. If its reference count is higher, it will be decremented and the
1730 * length of @array set to zero.
1731 *
1732 * Since: 2.62
1733 **/
1734 void
g_ptr_array_extend_and_steal(GPtrArray * array_to_extend,GPtrArray * array)1735 g_ptr_array_extend_and_steal (GPtrArray *array_to_extend,
1736 GPtrArray *array)
1737 {
1738 gpointer *pdata;
1739
1740 g_ptr_array_extend (array_to_extend, array, NULL, NULL);
1741
1742 /* Get rid of @array without triggering the GDestroyNotify attached
1743 * to the elements moved from @array to @array_to_extend. */
1744 pdata = g_steal_pointer (&array->pdata);
1745 array->len = 0;
1746 g_ptr_array_unref (array);
1747 g_free (pdata);
1748 }
1749
1750 /**
1751 * g_ptr_array_insert:
1752 * @array: a #GPtrArray
1753 * @index_: the index to place the new element at, or -1 to append
1754 * @data: the pointer to add.
1755 *
1756 * Inserts an element into the pointer array at the given index. The
1757 * array will grow in size automatically if necessary.
1758 *
1759 * Since: 2.40
1760 */
1761 void
g_ptr_array_insert(GPtrArray * array,gint index_,gpointer data)1762 g_ptr_array_insert (GPtrArray *array,
1763 gint index_,
1764 gpointer data)
1765 {
1766 GRealPtrArray *rarray = (GRealPtrArray *)array;
1767
1768 g_return_if_fail (rarray);
1769 g_return_if_fail (index_ >= -1);
1770 g_return_if_fail (index_ <= (gint)rarray->len);
1771
1772 g_ptr_array_maybe_expand (rarray, 1);
1773
1774 if (index_ < 0)
1775 index_ = rarray->len;
1776
1777 if ((guint) index_ < rarray->len)
1778 memmove (&(rarray->pdata[index_ + 1]),
1779 &(rarray->pdata[index_]),
1780 (rarray->len - index_) * sizeof (gpointer));
1781
1782 rarray->len++;
1783 rarray->pdata[index_] = data;
1784 }
1785
1786 /**
1787 * g_ptr_array_sort:
1788 * @array: a #GPtrArray
1789 * @compare_func: comparison function
1790 *
1791 * Sorts the array, using @compare_func which should be a qsort()-style
1792 * comparison function (returns less than zero for first arg is less
1793 * than second arg, zero for equal, greater than zero if irst arg is
1794 * greater than second arg).
1795 *
1796 * Note that the comparison function for g_ptr_array_sort() doesn't
1797 * take the pointers from the array as arguments, it takes pointers to
1798 * the pointers in the array.
1799 *
1800 * This is guaranteed to be a stable sort since version 2.32.
1801 */
1802 void
g_ptr_array_sort(GPtrArray * array,GCompareFunc compare_func)1803 g_ptr_array_sort (GPtrArray *array,
1804 GCompareFunc compare_func)
1805 {
1806 g_return_if_fail (array != NULL);
1807
1808 /* Don't use qsort as we want a guaranteed stable sort */
1809 g_qsort_with_data (array->pdata,
1810 array->len,
1811 sizeof (gpointer),
1812 (GCompareDataFunc)compare_func,
1813 NULL);
1814 }
1815
1816 /**
1817 * g_ptr_array_sort_with_data:
1818 * @array: a #GPtrArray
1819 * @compare_func: comparison function
1820 * @user_data: data to pass to @compare_func
1821 *
1822 * Like g_ptr_array_sort(), but the comparison function has an extra
1823 * user data argument.
1824 *
1825 * Note that the comparison function for g_ptr_array_sort_with_data()
1826 * doesn't take the pointers from the array as arguments, it takes
1827 * pointers to the pointers in the array.
1828 *
1829 * This is guaranteed to be a stable sort since version 2.32.
1830 */
1831 void
g_ptr_array_sort_with_data(GPtrArray * array,GCompareDataFunc compare_func,gpointer user_data)1832 g_ptr_array_sort_with_data (GPtrArray *array,
1833 GCompareDataFunc compare_func,
1834 gpointer user_data)
1835 {
1836 g_return_if_fail (array != NULL);
1837
1838 g_qsort_with_data (array->pdata,
1839 array->len,
1840 sizeof (gpointer),
1841 compare_func,
1842 user_data);
1843 }
1844
1845 /**
1846 * g_ptr_array_foreach:
1847 * @array: a #GPtrArray
1848 * @func: the function to call for each array element
1849 * @user_data: user data to pass to the function
1850 *
1851 * Calls a function for each element of a #GPtrArray. @func must not
1852 * add elements to or remove elements from the array.
1853 *
1854 * Since: 2.4
1855 */
1856 void
g_ptr_array_foreach(GPtrArray * array,GFunc func,gpointer user_data)1857 g_ptr_array_foreach (GPtrArray *array,
1858 GFunc func,
1859 gpointer user_data)
1860 {
1861 guint i;
1862
1863 g_return_if_fail (array);
1864
1865 for (i = 0; i < array->len; i++)
1866 (*func) (array->pdata[i], user_data);
1867 }
1868
1869 /**
1870 * g_ptr_array_find: (skip)
1871 * @haystack: pointer array to be searched
1872 * @needle: pointer to look for
1873 * @index_: (optional) (out caller-allocates): return location for the index of
1874 * the element, if found
1875 *
1876 * Checks whether @needle exists in @haystack. If the element is found, %TRUE is
1877 * returned and the element’s index is returned in @index_ (if non-%NULL).
1878 * Otherwise, %FALSE is returned and @index_ is undefined. If @needle exists
1879 * multiple times in @haystack, the index of the first instance is returned.
1880 *
1881 * This does pointer comparisons only. If you want to use more complex equality
1882 * checks, such as string comparisons, use g_ptr_array_find_with_equal_func().
1883 *
1884 * Returns: %TRUE if @needle is one of the elements of @haystack
1885 * Since: 2.54
1886 */
1887 gboolean
g_ptr_array_find(GPtrArray * haystack,gconstpointer needle,guint * index_)1888 g_ptr_array_find (GPtrArray *haystack,
1889 gconstpointer needle,
1890 guint *index_)
1891 {
1892 return g_ptr_array_find_with_equal_func (haystack, needle, NULL, index_);
1893 }
1894
1895 /**
1896 * g_ptr_array_find_with_equal_func: (skip)
1897 * @haystack: pointer array to be searched
1898 * @needle: pointer to look for
1899 * @equal_func: (nullable): the function to call for each element, which should
1900 * return %TRUE when the desired element is found; or %NULL to use pointer
1901 * equality
1902 * @index_: (optional) (out caller-allocates): return location for the index of
1903 * the element, if found
1904 *
1905 * Checks whether @needle exists in @haystack, using the given @equal_func.
1906 * If the element is found, %TRUE is returned and the element’s index is
1907 * returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_
1908 * is undefined. If @needle exists multiple times in @haystack, the index of
1909 * the first instance is returned.
1910 *
1911 * @equal_func is called with the element from the array as its first parameter,
1912 * and @needle as its second parameter. If @equal_func is %NULL, pointer
1913 * equality is used.
1914 *
1915 * Returns: %TRUE if @needle is one of the elements of @haystack
1916 * Since: 2.54
1917 */
1918 gboolean
g_ptr_array_find_with_equal_func(GPtrArray * haystack,gconstpointer needle,GEqualFunc equal_func,guint * index_)1919 g_ptr_array_find_with_equal_func (GPtrArray *haystack,
1920 gconstpointer needle,
1921 GEqualFunc equal_func,
1922 guint *index_)
1923 {
1924 guint i;
1925
1926 g_return_val_if_fail (haystack != NULL, FALSE);
1927
1928 if (equal_func == NULL)
1929 equal_func = g_direct_equal;
1930
1931 for (i = 0; i < haystack->len; i++)
1932 {
1933 if (equal_func (g_ptr_array_index (haystack, i), needle))
1934 {
1935 if (index_ != NULL)
1936 *index_ = i;
1937 return TRUE;
1938 }
1939 }
1940
1941 return FALSE;
1942 }
1943
1944 /**
1945 * SECTION:arrays_byte
1946 * @title: Byte Arrays
1947 * @short_description: arrays of bytes
1948 *
1949 * #GByteArray is a mutable array of bytes based on #GArray, to provide arrays
1950 * of bytes which grow automatically as elements are added.
1951 *
1952 * To create a new #GByteArray use g_byte_array_new(). To add elements to a
1953 * #GByteArray, use g_byte_array_append(), and g_byte_array_prepend().
1954 *
1955 * To set the size of a #GByteArray, use g_byte_array_set_size().
1956 *
1957 * To free a #GByteArray, use g_byte_array_free().
1958 *
1959 * An example for using a #GByteArray:
1960 * |[<!-- language="C" -->
1961 * GByteArray *gbarray;
1962 * gint i;
1963 *
1964 * gbarray = g_byte_array_new ();
1965 * for (i = 0; i < 10000; i++)
1966 * g_byte_array_append (gbarray, (guint8*) "abcd", 4);
1967 *
1968 * for (i = 0; i < 10000; i++)
1969 * {
1970 * g_assert (gbarray->data[4*i] == 'a');
1971 * g_assert (gbarray->data[4*i+1] == 'b');
1972 * g_assert (gbarray->data[4*i+2] == 'c');
1973 * g_assert (gbarray->data[4*i+3] == 'd');
1974 * }
1975 *
1976 * g_byte_array_free (gbarray, TRUE);
1977 * ]|
1978 *
1979 * See #GBytes if you are interested in an immutable object representing a
1980 * sequence of bytes.
1981 */
1982
1983 /**
1984 * GByteArray:
1985 * @data: a pointer to the element data. The data may be moved as
1986 * elements are added to the #GByteArray
1987 * @len: the number of elements in the #GByteArray
1988 *
1989 * Contains the public fields of a GByteArray.
1990 */
1991
1992 /**
1993 * g_byte_array_new:
1994 *
1995 * Creates a new #GByteArray with a reference count of 1.
1996 *
1997 * Returns: (transfer full): the new #GByteArray
1998 */
1999 GByteArray*
g_byte_array_new(void)2000 g_byte_array_new (void)
2001 {
2002 return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, 0);
2003 }
2004
2005 /**
2006 * g_byte_array_new_take:
2007 * @data: (transfer full) (array length=len): byte data for the array
2008 * @len: length of @data
2009 *
2010 * Create byte array containing the data. The data will be owned by the array
2011 * and will be freed with g_free(), i.e. it could be allocated using g_strdup().
2012 *
2013 * Do not use it if @len is greater than %G_MAXUINT. #GByteArray
2014 * stores the length of its data in #guint, which may be shorter than
2015 * #gsize.
2016 *
2017 * Since: 2.32
2018 *
2019 * Returns: (transfer full): a new #GByteArray
2020 */
2021 GByteArray*
g_byte_array_new_take(guint8 * data,gsize len)2022 g_byte_array_new_take (guint8 *data,
2023 gsize len)
2024 {
2025 GByteArray *array;
2026 GRealArray *real;
2027
2028 g_return_val_if_fail (len <= G_MAXUINT, NULL);
2029
2030 array = g_byte_array_new ();
2031 real = (GRealArray *)array;
2032 g_assert (real->data == NULL);
2033 g_assert (real->len == 0);
2034
2035 real->data = data;
2036 real->len = len;
2037 real->alloc = len;
2038
2039 return array;
2040 }
2041
2042 /**
2043 * g_byte_array_sized_new:
2044 * @reserved_size: number of bytes preallocated
2045 *
2046 * Creates a new #GByteArray with @reserved_size bytes preallocated.
2047 * This avoids frequent reallocation, if you are going to add many
2048 * bytes to the array. Note however that the size of the array is still
2049 * 0.
2050 *
2051 * Returns: the new #GByteArray
2052 */
2053 GByteArray*
g_byte_array_sized_new(guint reserved_size)2054 g_byte_array_sized_new (guint reserved_size)
2055 {
2056 return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, reserved_size);
2057 }
2058
2059 /**
2060 * g_byte_array_free:
2061 * @array: a #GByteArray
2062 * @free_segment: if %TRUE the actual byte data is freed as well
2063 *
2064 * Frees the memory allocated by the #GByteArray. If @free_segment is
2065 * %TRUE it frees the actual byte data. If the reference count of
2066 * @array is greater than one, the #GByteArray wrapper is preserved but
2067 * the size of @array will be set to zero.
2068 *
2069 * Returns: the element data if @free_segment is %FALSE, otherwise
2070 * %NULL. The element data should be freed using g_free().
2071 */
2072 guint8*
g_byte_array_free(GByteArray * array,gboolean free_segment)2073 g_byte_array_free (GByteArray *array,
2074 gboolean free_segment)
2075 {
2076 return (guint8 *)g_array_free ((GArray *)array, free_segment);
2077 }
2078
2079 /**
2080 * g_byte_array_free_to_bytes:
2081 * @array: (transfer full): a #GByteArray
2082 *
2083 * Transfers the data from the #GByteArray into a new immutable #GBytes.
2084 *
2085 * The #GByteArray is freed unless the reference count of @array is greater
2086 * than one, the #GByteArray wrapper is preserved but the size of @array
2087 * will be set to zero.
2088 *
2089 * This is identical to using g_bytes_new_take() and g_byte_array_free()
2090 * together.
2091 *
2092 * Since: 2.32
2093 *
2094 * Returns: (transfer full): a new immutable #GBytes representing same
2095 * byte data that was in the array
2096 */
2097 GBytes*
g_byte_array_free_to_bytes(GByteArray * array)2098 g_byte_array_free_to_bytes (GByteArray *array)
2099 {
2100 gsize length;
2101
2102 g_return_val_if_fail (array != NULL, NULL);
2103
2104 length = array->len;
2105 return g_bytes_new_take (g_byte_array_free (array, FALSE), length);
2106 }
2107
2108 /**
2109 * g_byte_array_ref:
2110 * @array: A #GByteArray
2111 *
2112 * Atomically increments the reference count of @array by one.
2113 * This function is thread-safe and may be called from any thread.
2114 *
2115 * Returns: The passed in #GByteArray
2116 *
2117 * Since: 2.22
2118 */
2119 GByteArray*
g_byte_array_ref(GByteArray * array)2120 g_byte_array_ref (GByteArray *array)
2121 {
2122 return (GByteArray *)g_array_ref ((GArray *)array);
2123 }
2124
2125 /**
2126 * g_byte_array_unref:
2127 * @array: A #GByteArray
2128 *
2129 * Atomically decrements the reference count of @array by one. If the
2130 * reference count drops to 0, all memory allocated by the array is
2131 * released. This function is thread-safe and may be called from any
2132 * thread.
2133 *
2134 * Since: 2.22
2135 */
2136 void
g_byte_array_unref(GByteArray * array)2137 g_byte_array_unref (GByteArray *array)
2138 {
2139 g_array_unref ((GArray *)array);
2140 }
2141
2142 /**
2143 * g_byte_array_append:
2144 * @array: a #GByteArray
2145 * @data: the byte data to be added
2146 * @len: the number of bytes to add
2147 *
2148 * Adds the given bytes to the end of the #GByteArray.
2149 * The array will grow in size automatically if necessary.
2150 *
2151 * Returns: the #GByteArray
2152 */
2153 GByteArray*
g_byte_array_append(GByteArray * array,const guint8 * data,guint len)2154 g_byte_array_append (GByteArray *array,
2155 const guint8 *data,
2156 guint len)
2157 {
2158 g_array_append_vals ((GArray *)array, (guint8 *)data, len);
2159
2160 return array;
2161 }
2162
2163 /**
2164 * g_byte_array_prepend:
2165 * @array: a #GByteArray
2166 * @data: the byte data to be added
2167 * @len: the number of bytes to add
2168 *
2169 * Adds the given data to the start of the #GByteArray.
2170 * The array will grow in size automatically if necessary.
2171 *
2172 * Returns: the #GByteArray
2173 */
2174 GByteArray*
g_byte_array_prepend(GByteArray * array,const guint8 * data,guint len)2175 g_byte_array_prepend (GByteArray *array,
2176 const guint8 *data,
2177 guint len)
2178 {
2179 g_array_prepend_vals ((GArray *)array, (guint8 *)data, len);
2180
2181 return array;
2182 }
2183
2184 /**
2185 * g_byte_array_set_size:
2186 * @array: a #GByteArray
2187 * @length: the new size of the #GByteArray
2188 *
2189 * Sets the size of the #GByteArray, expanding it if necessary.
2190 *
2191 * Returns: the #GByteArray
2192 */
2193 GByteArray*
g_byte_array_set_size(GByteArray * array,guint length)2194 g_byte_array_set_size (GByteArray *array,
2195 guint length)
2196 {
2197 g_array_set_size ((GArray *)array, length);
2198
2199 return array;
2200 }
2201
2202 /**
2203 * g_byte_array_remove_index:
2204 * @array: a #GByteArray
2205 * @index_: the index of the byte to remove
2206 *
2207 * Removes the byte at the given index from a #GByteArray.
2208 * The following bytes are moved down one place.
2209 *
2210 * Returns: the #GByteArray
2211 **/
2212 GByteArray*
g_byte_array_remove_index(GByteArray * array,guint index_)2213 g_byte_array_remove_index (GByteArray *array,
2214 guint index_)
2215 {
2216 g_array_remove_index ((GArray *)array, index_);
2217
2218 return array;
2219 }
2220
2221 /**
2222 * g_byte_array_remove_index_fast:
2223 * @array: a #GByteArray
2224 * @index_: the index of the byte to remove
2225 *
2226 * Removes the byte at the given index from a #GByteArray. The last
2227 * element in the array is used to fill in the space, so this function
2228 * does not preserve the order of the #GByteArray. But it is faster
2229 * than g_byte_array_remove_index().
2230 *
2231 * Returns: the #GByteArray
2232 */
2233 GByteArray*
g_byte_array_remove_index_fast(GByteArray * array,guint index_)2234 g_byte_array_remove_index_fast (GByteArray *array,
2235 guint index_)
2236 {
2237 g_array_remove_index_fast ((GArray *)array, index_);
2238
2239 return array;
2240 }
2241
2242 /**
2243 * g_byte_array_remove_range:
2244 * @array: a @GByteArray
2245 * @index_: the index of the first byte to remove
2246 * @length: the number of bytes to remove
2247 *
2248 * Removes the given number of bytes starting at the given index from a
2249 * #GByteArray. The following elements are moved to close the gap.
2250 *
2251 * Returns: the #GByteArray
2252 *
2253 * Since: 2.4
2254 */
2255 GByteArray*
g_byte_array_remove_range(GByteArray * array,guint index_,guint length)2256 g_byte_array_remove_range (GByteArray *array,
2257 guint index_,
2258 guint length)
2259 {
2260 g_return_val_if_fail (array, NULL);
2261 g_return_val_if_fail (index_ <= array->len, NULL);
2262 g_return_val_if_fail (index_ + length <= array->len, NULL);
2263
2264 return (GByteArray *)g_array_remove_range ((GArray *)array, index_, length);
2265 }
2266
2267 /**
2268 * g_byte_array_sort:
2269 * @array: a #GByteArray
2270 * @compare_func: comparison function
2271 *
2272 * Sorts a byte array, using @compare_func which should be a
2273 * qsort()-style comparison function (returns less than zero for first
2274 * arg is less than second arg, zero for equal, greater than zero if
2275 * first arg is greater than second arg).
2276 *
2277 * If two array elements compare equal, their order in the sorted array
2278 * is undefined. If you want equal elements to keep their order (i.e.
2279 * you want a stable sort) you can write a comparison function that,
2280 * if two elements would otherwise compare equal, compares them by
2281 * their addresses.
2282 */
2283 void
g_byte_array_sort(GByteArray * array,GCompareFunc compare_func)2284 g_byte_array_sort (GByteArray *array,
2285 GCompareFunc compare_func)
2286 {
2287 g_array_sort ((GArray *)array, compare_func);
2288 }
2289
2290 /**
2291 * g_byte_array_sort_with_data:
2292 * @array: a #GByteArray
2293 * @compare_func: comparison function
2294 * @user_data: data to pass to @compare_func
2295 *
2296 * Like g_byte_array_sort(), but the comparison function takes an extra
2297 * user data argument.
2298 */
2299 void
g_byte_array_sort_with_data(GByteArray * array,GCompareDataFunc compare_func,gpointer user_data)2300 g_byte_array_sort_with_data (GByteArray *array,
2301 GCompareDataFunc compare_func,
2302 gpointer user_data)
2303 {
2304 g_array_sort_with_data ((GArray *)array, compare_func, user_data);
2305 }
2306