Coverage Report

Created: 2025-07-23 06:42

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