• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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