nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
||
3 | * |
||
4 | * This library is free software; you can redistribute it and/or |
||
5 | * modify it under the terms of the GNU Lesser General Public |
||
6 | * License as published by the Free Software Foundation; either |
||
7 | * version 2 of the License, or (at your option) any later version. |
||
8 | * |
||
9 | * This library is distributed in the hope that it will be useful, |
||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
12 | * Lesser General Public License for more details. |
||
13 | * |
||
14 | * You should have received a copy of the GNU Lesser General Public |
||
15 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
16 | */ |
||
17 | |||
18 | /* |
||
19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
||
20 | * file for a list of people on the GLib Team. See the ChangeLog |
||
21 | * files for a list of changes. These files are distributed with |
||
22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
||
23 | */ |
||
24 | |||
25 | /* |
||
26 | * MT safe |
||
27 | */ |
||
28 | |||
29 | #include "config.h" |
||
30 | |||
31 | #include <string.h> |
||
32 | #include <stdlib.h> |
||
33 | |||
34 | #include "garray.h" |
||
35 | |||
36 | #include "gbytes.h" |
||
37 | #include "gslice.h" |
||
38 | #include "gmem.h" |
||
39 | #include "gtestutils.h" |
||
40 | #include "gthread.h" |
||
41 | #include "gmessages.h" |
||
42 | #include "gqsort.h" |
||
43 | |||
44 | |||
45 | /** |
||
46 | * SECTION:arrays |
||
47 | * @title: Arrays |
||
48 | * @short_description: arrays of arbitrary elements which grow |
||
49 | * automatically as elements are added |
||
50 | * |
||
51 | * Arrays are similar to standard C arrays, except that they grow |
||
52 | * automatically as elements are added. |
||
53 | * |
||
54 | * Array elements can be of any size (though all elements of one array |
||
55 | * are the same size), and the array can be automatically cleared to |
||
56 | * '0's and zero-terminated. |
||
57 | * |
||
58 | * To create a new array use g_array_new(). |
||
59 | * |
||
60 | * To add elements to an array, use g_array_append_val(), |
||
61 | * g_array_append_vals(), g_array_prepend_val(), and |
||
62 | * g_array_prepend_vals(). |
||
63 | * |
||
64 | * To access an element of an array, use g_array_index(). |
||
65 | * |
||
66 | * To set the size of an array, use g_array_set_size(). |
||
67 | * |
||
68 | * To free an array, use g_array_free(). |
||
69 | * |
||
70 | * Here is an example that stores integers in a #GArray: |
||
71 | * |[<!-- language="C" --> |
||
72 | * GArray *garray; |
||
73 | * gint i; |
||
74 | * // We create a new array to store gint values. |
||
75 | * // We don't want it zero-terminated or cleared to 0's. |
||
76 | * garray = g_array_new (FALSE, FALSE, sizeof (gint)); |
||
77 | * for (i = 0; i < 10000; i++) |
||
78 | * g_array_append_val (garray, i); |
||
79 | * for (i = 0; i < 10000; i++) |
||
80 | * if (g_array_index (garray, gint, i) != i) |
||
81 | * g_print ("ERROR: got %d instead of %d\n", |
||
82 | * g_array_index (garray, gint, i), i); |
||
83 | * g_array_free (garray, TRUE); |
||
84 | * ]| |
||
85 | */ |
||
86 | |||
87 | #define MIN_ARRAY_SIZE 16 |
||
88 | |||
89 | typedef struct _GRealArray GRealArray; |
||
90 | |||
91 | /** |
||
92 | * GArray: |
||
93 | * @data: a pointer to the element data. The data may be moved as |
||
94 | * elements are added to the #GArray. |
||
95 | * @len: the number of elements in the #GArray not including the |
||
96 | * possible terminating zero element. |
||
97 | * |
||
98 | * Contains the public fields of a GArray. |
||
99 | */ |
||
100 | struct _GRealArray |
||
101 | { |
||
102 | guint8 *data; |
||
103 | guint len; |
||
104 | guint alloc; |
||
105 | guint elt_size; |
||
106 | guint zero_terminated : 1; |
||
107 | guint clear : 1; |
||
108 | gint ref_count; |
||
109 | GDestroyNotify clear_func; |
||
110 | }; |
||
111 | |||
112 | /** |
||
113 | * g_array_index: |
||
114 | * @a: a #GArray |
||
115 | * @t: the type of the elements |
||
116 | * @i: the index of the element to return |
||
117 | * |
||
118 | * Returns the element of a #GArray at the given index. The return |
||
119 | * value is cast to the given type. |
||
120 | * |
||
121 | * This example gets a pointer to an element in a #GArray: |
||
122 | * |[<!-- language="C" --> |
||
123 | * EDayViewEvent *event; |
||
124 | * // This gets a pointer to the 4th element in the array of |
||
125 | * // EDayViewEvent structs. |
||
126 | * event = &g_array_index (events, EDayViewEvent, 3); |
||
127 | * ]| |
||
128 | * |
||
129 | * Returns: the element of the #GArray at the index given by @i |
||
130 | */ |
||
131 | |||
132 | #define g_array_elt_len(array,i) ((array)->elt_size * (i)) |
||
133 | #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i))) |
||
134 | #define g_array_elt_zero(array, pos, len) \ |
||
135 | (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len))) |
||
136 | #define g_array_zero_terminate(array) G_STMT_START{ \ |
||
137 | if ((array)->zero_terminated) \ |
||
138 | g_array_elt_zero ((array), (array)->len, 1); \ |
||
139 | }G_STMT_END |
||
140 | |||
141 | static guint g_nearest_pow (gint num) G_GNUC_CONST; |
||
142 | static void g_array_maybe_expand (GRealArray *array, |
||
143 | gint len); |
||
144 | |||
145 | /** |
||
146 | * g_array_new: |
||
147 | * @zero_terminated: %TRUE if the array should have an extra element at |
||
148 | * the end which is set to 0 |
||
149 | * @clear_: %TRUE if #GArray elements should be automatically cleared |
||
150 | * to 0 when they are allocated |
||
151 | * @element_size: the size of each element in bytes |
||
152 | * |
||
153 | * Creates a new #GArray with a reference count of 1. |
||
154 | * |
||
155 | * Returns: the new #GArray |
||
156 | */ |
||
157 | GArray* |
||
158 | g_array_new (gboolean zero_terminated, |
||
159 | gboolean clear, |
||
160 | guint elt_size) |
||
161 | { |
||
162 | g_return_val_if_fail (elt_size > 0, NULL); |
||
163 | |||
164 | return g_array_sized_new (zero_terminated, clear, elt_size, 0); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * g_array_sized_new: |
||
169 | * @zero_terminated: %TRUE if the array should have an extra element at |
||
170 | * the end with all bits cleared |
||
171 | * @clear_: %TRUE if all bits in the array should be cleared to 0 on |
||
172 | * allocation |
||
173 | * @element_size: size of each element in the array |
||
174 | * @reserved_size: number of elements preallocated |
||
175 | * |
||
176 | * Creates a new #GArray with @reserved_size elements preallocated and |
||
177 | * a reference count of 1. This avoids frequent reallocation, if you |
||
178 | * are going to add many elements to the array. Note however that the |
||
179 | * size of the array is still 0. |
||
180 | * |
||
181 | * Returns: the new #GArray |
||
182 | */ |
||
183 | GArray* |
||
184 | g_array_sized_new (gboolean zero_terminated, |
||
185 | gboolean clear, |
||
186 | guint elt_size, |
||
187 | guint reserved_size) |
||
188 | { |
||
189 | GRealArray *array; |
||
190 | |||
191 | g_return_val_if_fail (elt_size > 0, NULL); |
||
192 | |||
193 | array = g_slice_new (GRealArray); |
||
194 | |||
195 | array->data = NULL; |
||
196 | array->len = 0; |
||
197 | array->alloc = 0; |
||
198 | array->zero_terminated = (zero_terminated ? 1 : 0); |
||
199 | array->clear = (clear ? 1 : 0); |
||
200 | array->elt_size = elt_size; |
||
201 | array->ref_count = 1; |
||
202 | array->clear_func = NULL; |
||
203 | |||
204 | if (array->zero_terminated || reserved_size != 0) |
||
205 | { |
||
206 | g_array_maybe_expand (array, reserved_size); |
||
207 | g_array_zero_terminate(array); |
||
208 | } |
||
209 | |||
210 | return (GArray*) array; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * g_array_set_clear_func: |
||
215 | * @array: A #GArray |
||
216 | * @clear_func: a function to clear an element of @array |
||
217 | * |
||
218 | * Sets a function to clear an element of @array. |
||
219 | * |
||
220 | * The @clear_func will be called when an element in the array |
||
221 | * data segment is removed and when the array is freed and data |
||
222 | * segment is deallocated as well. |
||
223 | * |
||
224 | * Note that in contrast with other uses of #GDestroyNotify |
||
225 | * functions, @clear_func is expected to clear the contents of |
||
226 | * the array element it is given, but not free the element itself. |
||
227 | * |
||
228 | * Since: 2.32 |
||
229 | */ |
||
230 | void |
||
231 | g_array_set_clear_func (GArray *array, |
||
232 | GDestroyNotify clear_func) |
||
233 | { |
||
234 | GRealArray *rarray = (GRealArray *) array; |
||
235 | |||
236 | g_return_if_fail (array != NULL); |
||
237 | |||
238 | rarray->clear_func = clear_func; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * g_array_ref: |
||
243 | * @array: A #GArray |
||
244 | * |
||
245 | * Atomically increments the reference count of @array by one. |
||
246 | * This function is MT-safe and may be called from any thread. |
||
247 | * |
||
248 | * Returns: The passed in #GArray |
||
249 | * |
||
250 | * Since: 2.22 |
||
251 | */ |
||
252 | GArray * |
||
253 | g_array_ref (GArray *array) |
||
254 | { |
||
255 | GRealArray *rarray = (GRealArray*) array; |
||
256 | g_return_val_if_fail (array, NULL); |
||
257 | |||
258 | g_atomic_int_inc (&rarray->ref_count); |
||
259 | |||
260 | return array; |
||
261 | } |
||
262 | |||
263 | typedef enum |
||
264 | { |
||
265 | FREE_SEGMENT = 1 << 0, |
||
266 | PRESERVE_WRAPPER = 1 << 1 |
||
267 | } ArrayFreeFlags; |
||
268 | |||
269 | static gchar *array_free (GRealArray *, ArrayFreeFlags); |
||
270 | |||
271 | /** |
||
272 | * g_array_unref: |
||
273 | * @array: A #GArray |
||
274 | * |
||
275 | * Atomically decrements the reference count of @array by one. If the |
||
276 | * reference count drops to 0, all memory allocated by the array is |
||
277 | * released. This function is MT-safe and may be called from any |
||
278 | * thread. |
||
279 | * |
||
280 | * Since: 2.22 |
||
281 | */ |
||
282 | void |
||
283 | g_array_unref (GArray *array) |
||
284 | { |
||
285 | GRealArray *rarray = (GRealArray*) array; |
||
286 | g_return_if_fail (array); |
||
287 | |||
288 | if (g_atomic_int_dec_and_test (&rarray->ref_count)) |
||
289 | array_free (rarray, FREE_SEGMENT); |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * g_array_get_element_size: |
||
294 | * @array: A #GArray |
||
295 | * |
||
296 | * Gets the size of the elements in @array. |
||
297 | * |
||
298 | * Returns: Size of each element, in bytes |
||
299 | * |
||
300 | * Since: 2.22 |
||
301 | */ |
||
302 | guint |
||
303 | g_array_get_element_size (GArray *array) |
||
304 | { |
||
305 | GRealArray *rarray = (GRealArray*) array; |
||
306 | |||
307 | g_return_val_if_fail (array, 0); |
||
308 | |||
309 | return rarray->elt_size; |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * g_array_free: |
||
314 | * @array: a #GArray |
||
315 | * @free_segment: if %TRUE the actual element data is freed as well |
||
316 | * |
||
317 | * Frees the memory allocated for the #GArray. If @free_segment is |
||
318 | * %TRUE it frees the memory block holding the elements as well and |
||
319 | * also each element if @array has a @element_free_func set. Pass |
||
320 | * %FALSE if you want to free the #GArray wrapper but preserve the |
||
321 | * underlying array for use elsewhere. If the reference count of @array |
||
322 | * is greater than one, the #GArray wrapper is preserved but the size |
||
323 | * of @array will be set to zero. |
||
324 | * |
||
325 | * If array elements contain dynamically-allocated memory, they should |
||
326 | * be freed separately. |
||
327 | * |
||
328 | * Returns: the element data if @free_segment is %FALSE, otherwise |
||
329 | * %NULL. The element data should be freed using g_free(). |
||
330 | */ |
||
331 | gchar* |
||
332 | g_array_free (GArray *farray, |
||
333 | gboolean free_segment) |
||
334 | { |
||
335 | GRealArray *array = (GRealArray*) farray; |
||
336 | ArrayFreeFlags flags; |
||
337 | |||
338 | g_return_val_if_fail (array, NULL); |
||
339 | |||
340 | flags = (free_segment ? FREE_SEGMENT : 0); |
||
341 | |||
342 | /* if others are holding a reference, preserve the wrapper but do free/return the data */ |
||
343 | if (!g_atomic_int_dec_and_test (&array->ref_count)) |
||
344 | flags |= PRESERVE_WRAPPER; |
||
345 | |||
346 | return array_free (array, flags); |
||
347 | } |
||
348 | |||
349 | static gchar * |
||
350 | array_free (GRealArray *array, |
||
351 | ArrayFreeFlags flags) |
||
352 | { |
||
353 | gchar *segment; |
||
354 | |||
355 | if (flags & FREE_SEGMENT) |
||
356 | { |
||
357 | if (array->clear_func != NULL) |
||
358 | { |
||
359 | guint i; |
||
360 | |||
361 | for (i = 0; i < array->len; i++) |
||
362 | array->clear_func (g_array_elt_pos (array, i)); |
||
363 | } |
||
364 | |||
365 | g_free (array->data); |
||
366 | segment = NULL; |
||
367 | } |
||
368 | else |
||
369 | segment = (gchar*) array->data; |
||
370 | |||
371 | if (flags & PRESERVE_WRAPPER) |
||
372 | { |
||
373 | array->data = NULL; |
||
374 | array->len = 0; |
||
375 | array->alloc = 0; |
||
376 | } |
||
377 | else |
||
378 | { |
||
379 | g_slice_free1 (sizeof (GRealArray), array); |
||
380 | } |
||
381 | |||
382 | return segment; |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * g_array_append_vals: |
||
387 | * @array: a #GArray |
||
388 | * @data: (not nullable): a pointer to the elements to append to the end of the array |
||
389 | * @len: the number of elements to append |
||
390 | * |
||
391 | * Adds @len elements onto the end of the array. |
||
392 | * |
||
393 | * Returns: the #GArray |
||
394 | */ |
||
395 | /** |
||
396 | * g_array_append_val: |
||
397 | * @a: a #GArray |
||
398 | * @v: the value to append to the #GArray |
||
399 | * |
||
400 | * Adds the value on to the end of the array. The array will grow in |
||
401 | * size automatically if necessary. |
||
402 | * |
||
403 | * g_array_append_val() is a macro which uses a reference to the value |
||
404 | * parameter @v. This means that you cannot use it with literal values |
||
405 | * such as "27". You must use variables. |
||
406 | * |
||
407 | * Returns: the #GArray |
||
408 | */ |
||
409 | GArray* |
||
410 | g_array_append_vals (GArray *farray, |
||
411 | gconstpointer data, |
||
412 | guint len) |
||
413 | { |
||
414 | GRealArray *array = (GRealArray*) farray; |
||
415 | |||
416 | g_return_val_if_fail (array, NULL); |
||
417 | |||
418 | g_array_maybe_expand (array, len); |
||
419 | |||
420 | memcpy (g_array_elt_pos (array, array->len), data, |
||
421 | g_array_elt_len (array, len)); |
||
422 | |||
423 | array->len += len; |
||
424 | |||
425 | g_array_zero_terminate (array); |
||
426 | |||
427 | return farray; |
||
428 | } |
||
429 | |||
430 | /** |
||
431 | * g_array_prepend_vals: |
||
432 | * @array: a #GArray |
||
433 | * @data: (not nullable): a pointer to the elements to prepend to the start of the array |
||
434 | * @len: the number of elements to prepend |
||
435 | * |
||
436 | * Adds @len elements onto the start of the array. |
||
437 | * |
||
438 | * This operation is slower than g_array_append_vals() since the |
||
439 | * existing elements in the array have to be moved to make space for |
||
440 | * the new elements. |
||
441 | * |
||
442 | * Returns: the #GArray |
||
443 | */ |
||
444 | /** |
||
445 | * g_array_prepend_val: |
||
446 | * @a: a #GArray |
||
447 | * @v: the value to prepend to the #GArray |
||
448 | * |
||
449 | * Adds the value on to the start of the array. The array will grow in |
||
450 | * size automatically if necessary. |
||
451 | * |
||
452 | * This operation is slower than g_array_append_val() since the |
||
453 | * existing elements in the array have to be moved to make space for |
||
454 | * the new element. |
||
455 | * |
||
456 | * g_array_prepend_val() is a macro which uses a reference to the value |
||
457 | * parameter @v. This means that you cannot use it with literal values |
||
458 | * such as "27". You must use variables. |
||
459 | * |
||
460 | * Returns: the #GArray |
||
461 | */ |
||
462 | GArray* |
||
463 | g_array_prepend_vals (GArray *farray, |
||
464 | gconstpointer data, |
||
465 | guint len) |
||
466 | { |
||
467 | GRealArray *array = (GRealArray*) farray; |
||
468 | |||
469 | g_return_val_if_fail (array, NULL); |
||
470 | |||
471 | g_array_maybe_expand (array, len); |
||
472 | |||
473 | memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0), |
||
474 | g_array_elt_len (array, array->len)); |
||
475 | |||
476 | memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len)); |
||
477 | |||
478 | array->len += len; |
||
479 | |||
480 | g_array_zero_terminate (array); |
||
481 | |||
482 | return farray; |
||
483 | } |
||
484 | |||
485 | /** |
||
486 | * g_array_insert_vals: |
||
487 | * @array: a #GArray |
||
488 | * @index_: the index to place the elements at |
||
489 | * @data: (not nullable): a pointer to the elements to insert |
||
490 | * @len: the number of elements to insert |
||
491 | * |
||
492 | * Inserts @len elements into a #GArray at the given index. |
||
493 | * |
||
494 | * Returns: the #GArray |
||
495 | */ |
||
496 | /** |
||
497 | * g_array_insert_val: |
||
498 | * @a: a #GArray |
||
499 | * @i: the index to place the element at |
||
500 | * @v: the value to insert into the array |
||
501 | * |
||
502 | * Inserts an element into an array at the given index. |
||
503 | * |
||
504 | * g_array_insert_val() is a macro which uses a reference to the value |
||
505 | * parameter @v. This means that you cannot use it with literal values |
||
506 | * such as "27". You must use variables. |
||
507 | * |
||
508 | * Returns: the #GArray |
||
509 | */ |
||
510 | GArray* |
||
511 | g_array_insert_vals (GArray *farray, |
||
512 | guint index_, |
||
513 | gconstpointer data, |
||
514 | guint len) |
||
515 | { |
||
516 | GRealArray *array = (GRealArray*) farray; |
||
517 | |||
518 | g_return_val_if_fail (array, NULL); |
||
519 | |||
520 | g_array_maybe_expand (array, len); |
||
521 | |||
522 | memmove (g_array_elt_pos (array, len + index_), |
||
523 | g_array_elt_pos (array, index_), |
||
524 | g_array_elt_len (array, array->len - index_)); |
||
525 | |||
526 | memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len)); |
||
527 | |||
528 | array->len += len; |
||
529 | |||
530 | g_array_zero_terminate (array); |
||
531 | |||
532 | return farray; |
||
533 | } |
||
534 | |||
535 | /** |
||
536 | * g_array_set_size: |
||
537 | * @array: a #GArray |
||
538 | * @length: the new size of the #GArray |
||
539 | * |
||
540 | * Sets the size of the array, expanding it if necessary. If the array |
||
541 | * was created with @clear_ set to %TRUE, the new elements are set to 0. |
||
542 | * |
||
543 | * Returns: the #GArray |
||
544 | */ |
||
545 | GArray* |
||
546 | g_array_set_size (GArray *farray, |
||
547 | guint length) |
||
548 | { |
||
549 | GRealArray *array = (GRealArray*) farray; |
||
550 | |||
551 | g_return_val_if_fail (array, NULL); |
||
552 | |||
553 | if (length > array->len) |
||
554 | { |
||
555 | g_array_maybe_expand (array, length - array->len); |
||
556 | |||
557 | if (array->clear) |
||
558 | g_array_elt_zero (array, array->len, length - array->len); |
||
559 | } |
||
560 | else if (length < array->len) |
||
561 | g_array_remove_range (farray, length, array->len - length); |
||
562 | |||
563 | array->len = length; |
||
564 | |||
565 | g_array_zero_terminate (array); |
||
566 | |||
567 | return farray; |
||
568 | } |
||
569 | |||
570 | /** |
||
571 | * g_array_remove_index: |
||
572 | * @array: a #GArray |
||
573 | * @index_: the index of the element to remove |
||
574 | * |
||
575 | * Removes the element at the given index from a #GArray. The following |
||
576 | * elements are moved down one place. |
||
577 | * |
||
578 | * Returns: the #GArray |
||
579 | */ |
||
580 | GArray* |
||
581 | g_array_remove_index (GArray *farray, |
||
582 | guint index_) |
||
583 | { |
||
584 | GRealArray* array = (GRealArray*) farray; |
||
585 | |||
586 | g_return_val_if_fail (array, NULL); |
||
587 | |||
588 | g_return_val_if_fail (index_ < array->len, NULL); |
||
589 | |||
590 | if (array->clear_func != NULL) |
||
591 | array->clear_func (g_array_elt_pos (array, index_)); |
||
592 | |||
593 | if (index_ != array->len - 1) |
||
594 | memmove (g_array_elt_pos (array, index_), |
||
595 | g_array_elt_pos (array, index_ + 1), |
||
596 | g_array_elt_len (array, array->len - index_ - 1)); |
||
597 | |||
598 | array->len -= 1; |
||
599 | |||
600 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
601 | g_array_elt_zero (array, array->len, 1); |
||
602 | else |
||
603 | g_array_zero_terminate (array); |
||
604 | |||
605 | return farray; |
||
606 | } |
||
607 | |||
608 | /** |
||
609 | * g_array_remove_index_fast: |
||
610 | * @array: a @GArray |
||
611 | * @index_: the index of the element to remove |
||
612 | * |
||
613 | * Removes the element at the given index from a #GArray. The last |
||
614 | * element in the array is used to fill in the space, so this function |
||
615 | * does not preserve the order of the #GArray. But it is faster than |
||
616 | * g_array_remove_index(). |
||
617 | * |
||
618 | * Returns: the #GArray |
||
619 | */ |
||
620 | GArray* |
||
621 | g_array_remove_index_fast (GArray *farray, |
||
622 | guint index_) |
||
623 | { |
||
624 | GRealArray* array = (GRealArray*) farray; |
||
625 | |||
626 | g_return_val_if_fail (array, NULL); |
||
627 | |||
628 | g_return_val_if_fail (index_ < array->len, NULL); |
||
629 | |||
630 | if (array->clear_func != NULL) |
||
631 | array->clear_func (g_array_elt_pos (array, index_)); |
||
632 | |||
633 | if (index_ != array->len - 1) |
||
634 | memcpy (g_array_elt_pos (array, index_), |
||
635 | g_array_elt_pos (array, array->len - 1), |
||
636 | g_array_elt_len (array, 1)); |
||
637 | |||
638 | array->len -= 1; |
||
639 | |||
640 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
641 | g_array_elt_zero (array, array->len, 1); |
||
642 | else |
||
643 | g_array_zero_terminate (array); |
||
644 | |||
645 | return farray; |
||
646 | } |
||
647 | |||
648 | /** |
||
649 | * g_array_remove_range: |
||
650 | * @array: a @GArray |
||
651 | * @index_: the index of the first element to remove |
||
652 | * @length: the number of elements to remove |
||
653 | * |
||
654 | * Removes the given number of elements starting at the given index |
||
655 | * from a #GArray. The following elements are moved to close the gap. |
||
656 | * |
||
657 | * Returns: the #GArray |
||
658 | * |
||
659 | * Since: 2.4 |
||
660 | */ |
||
661 | GArray* |
||
662 | g_array_remove_range (GArray *farray, |
||
663 | guint index_, |
||
664 | guint length) |
||
665 | { |
||
666 | GRealArray *array = (GRealArray*) farray; |
||
667 | |||
668 | g_return_val_if_fail (array, NULL); |
||
669 | g_return_val_if_fail (index_ <= array->len, NULL); |
||
670 | g_return_val_if_fail (index_ + length <= array->len, NULL); |
||
671 | |||
672 | if (array->clear_func != NULL) |
||
673 | { |
||
674 | guint i; |
||
675 | |||
676 | for (i = 0; i < length; i++) |
||
677 | array->clear_func (g_array_elt_pos (array, index_ + i)); |
||
678 | } |
||
679 | |||
680 | if (index_ + length != array->len) |
||
681 | memmove (g_array_elt_pos (array, index_), |
||
682 | g_array_elt_pos (array, index_ + length), |
||
683 | (array->len - (index_ + length)) * array->elt_size); |
||
684 | |||
685 | array->len -= length; |
||
686 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
687 | g_array_elt_zero (array, array->len, length); |
||
688 | else |
||
689 | g_array_zero_terminate (array); |
||
690 | |||
691 | return farray; |
||
692 | } |
||
693 | |||
694 | /** |
||
695 | * g_array_sort: |
||
696 | * @array: a #GArray |
||
697 | * @compare_func: comparison function |
||
698 | * |
||
699 | * Sorts a #GArray using @compare_func which should be a qsort()-style |
||
700 | * comparison function (returns less than zero for first arg is less |
||
701 | * than second arg, zero for equal, greater zero if first arg is |
||
702 | * greater than second arg). |
||
703 | * |
||
704 | * This is guaranteed to be a stable sort since version 2.32. |
||
705 | */ |
||
706 | void |
||
707 | g_array_sort (GArray *farray, |
||
708 | GCompareFunc compare_func) |
||
709 | { |
||
710 | GRealArray *array = (GRealArray*) farray; |
||
711 | |||
712 | g_return_if_fail (array != NULL); |
||
713 | |||
714 | /* Don't use qsort as we want a guaranteed stable sort */ |
||
715 | g_qsort_with_data (array->data, |
||
716 | array->len, |
||
717 | array->elt_size, |
||
718 | (GCompareDataFunc)compare_func, |
||
719 | NULL); |
||
720 | } |
||
721 | |||
722 | /** |
||
723 | * g_array_sort_with_data: |
||
724 | * @array: a #GArray |
||
725 | * @compare_func: comparison function |
||
726 | * @user_data: data to pass to @compare_func |
||
727 | * |
||
728 | * Like g_array_sort(), but the comparison function receives an extra |
||
729 | * user data argument. |
||
730 | * |
||
731 | * This is guaranteed to be a stable sort since version 2.32. |
||
732 | * |
||
733 | * There used to be a comment here about making the sort stable by |
||
734 | * using the addresses of the elements in the comparison function. |
||
735 | * This did not actually work, so any such code should be removed. |
||
736 | */ |
||
737 | void |
||
738 | g_array_sort_with_data (GArray *farray, |
||
739 | GCompareDataFunc compare_func, |
||
740 | gpointer user_data) |
||
741 | { |
||
742 | GRealArray *array = (GRealArray*) farray; |
||
743 | |||
744 | g_return_if_fail (array != NULL); |
||
745 | |||
746 | g_qsort_with_data (array->data, |
||
747 | array->len, |
||
748 | array->elt_size, |
||
749 | compare_func, |
||
750 | user_data); |
||
751 | } |
||
752 | |||
753 | /* Returns the smallest power of 2 greater than n, or n if |
||
754 | * such power does not fit in a guint |
||
755 | */ |
||
756 | static guint |
||
757 | g_nearest_pow (gint num) |
||
758 | { |
||
759 | guint n = 1; |
||
760 | |||
761 | while (n < num && n > 0) |
||
762 | n <<= 1; |
||
763 | |||
764 | return n ? n : num; |
||
765 | } |
||
766 | |||
767 | static void |
||
768 | g_array_maybe_expand (GRealArray *array, |
||
769 | gint len) |
||
770 | { |
||
771 | guint want_alloc = g_array_elt_len (array, array->len + len + |
||
772 | array->zero_terminated); |
||
773 | |||
774 | if (want_alloc > array->alloc) |
||
775 | { |
||
776 | want_alloc = g_nearest_pow (want_alloc); |
||
777 | want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE); |
||
778 | |||
779 | array->data = g_realloc (array->data, want_alloc); |
||
780 | |||
781 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
782 | memset (array->data + array->alloc, 0, want_alloc - array->alloc); |
||
783 | |||
784 | array->alloc = want_alloc; |
||
785 | } |
||
786 | } |
||
787 | |||
788 | /** |
||
789 | * SECTION:arrays_pointer |
||
790 | * @title: Pointer Arrays |
||
791 | * @short_description: arrays of pointers to any type of data, which |
||
792 | * grow automatically as new elements are added |
||
793 | * |
||
794 | * Pointer Arrays are similar to Arrays but are used only for storing |
||
795 | * pointers. |
||
796 | * |
||
797 | * If you remove elements from the array, elements at the end of the |
||
798 | * array are moved into the space previously occupied by the removed |
||
799 | * element. This means that you should not rely on the index of particular |
||
800 | * elements remaining the same. You should also be careful when deleting |
||
801 | * elements while iterating over the array. |
||
802 | * |
||
803 | * To create a pointer array, use g_ptr_array_new(). |
||
804 | * |
||
805 | * To add elements to a pointer array, use g_ptr_array_add(). |
||
806 | * |
||
807 | * To remove elements from a pointer array, use g_ptr_array_remove(), |
||
808 | * g_ptr_array_remove_index() or g_ptr_array_remove_index_fast(). |
||
809 | * |
||
810 | * To access an element of a pointer array, use g_ptr_array_index(). |
||
811 | * |
||
812 | * To set the size of a pointer array, use g_ptr_array_set_size(). |
||
813 | * |
||
814 | * To free a pointer array, use g_ptr_array_free(). |
||
815 | * |
||
816 | * An example using a #GPtrArray: |
||
817 | * |[<!-- language="C" --> |
||
818 | * GPtrArray *array; |
||
819 | * gchar *string1 = "one"; |
||
820 | * gchar *string2 = "two"; |
||
821 | * gchar *string3 = "three"; |
||
822 | * |
||
823 | * array = g_ptr_array_new (); |
||
824 | * g_ptr_array_add (array, (gpointer) string1); |
||
825 | * g_ptr_array_add (array, (gpointer) string2); |
||
826 | * g_ptr_array_add (array, (gpointer) string3); |
||
827 | * |
||
828 | * if (g_ptr_array_index (array, 0) != (gpointer) string1) |
||
829 | * g_print ("ERROR: got %p instead of %p\n", |
||
830 | * g_ptr_array_index (array, 0), string1); |
||
831 | * |
||
832 | * g_ptr_array_free (array, TRUE); |
||
833 | * ]| |
||
834 | */ |
||
835 | |||
836 | typedef struct _GRealPtrArray GRealPtrArray; |
||
837 | |||
838 | /** |
||
839 | * GPtrArray: |
||
840 | * @pdata: points to the array of pointers, which may be moved when the |
||
841 | * array grows |
||
842 | * @len: number of pointers in the array |
||
843 | * |
||
844 | * Contains the public fields of a pointer array. |
||
845 | */ |
||
846 | struct _GRealPtrArray |
||
847 | { |
||
848 | gpointer *pdata; |
||
849 | guint len; |
||
850 | guint alloc; |
||
851 | gint ref_count; |
||
852 | GDestroyNotify element_free_func; |
||
853 | }; |
||
854 | |||
855 | /** |
||
856 | * g_ptr_array_index: |
||
857 | * @array: a #GPtrArray |
||
858 | * @index_: the index of the pointer to return |
||
859 | * |
||
860 | * Returns the pointer at the given index of the pointer array. |
||
861 | * |
||
862 | * This does not perform bounds checking on the given @index_, |
||
863 | * so you are responsible for checking it against the array length. |
||
864 | * |
||
865 | * Returns: the pointer at the given index |
||
866 | */ |
||
867 | |||
868 | static void g_ptr_array_maybe_expand (GRealPtrArray *array, |
||
869 | gint len); |
||
870 | |||
871 | /** |
||
872 | * g_ptr_array_new: |
||
873 | * |
||
874 | * Creates a new #GPtrArray with a reference count of 1. |
||
875 | * |
||
876 | * Returns: the new #GPtrArray |
||
877 | */ |
||
878 | GPtrArray* |
||
879 | g_ptr_array_new (void) |
||
880 | { |
||
881 | return g_ptr_array_sized_new (0); |
||
882 | } |
||
883 | |||
884 | /** |
||
885 | * g_ptr_array_sized_new: |
||
886 | * @reserved_size: number of pointers preallocated |
||
887 | * |
||
888 | * Creates a new #GPtrArray with @reserved_size pointers preallocated |
||
889 | * and a reference count of 1. This avoids frequent reallocation, if |
||
890 | * you are going to add many pointers to the array. Note however that |
||
891 | * the size of the array is still 0. |
||
892 | * |
||
893 | * Returns: the new #GPtrArray |
||
894 | */ |
||
895 | GPtrArray* |
||
896 | g_ptr_array_sized_new (guint reserved_size) |
||
897 | { |
||
898 | GRealPtrArray *array; |
||
899 | |||
900 | array = g_slice_new (GRealPtrArray); |
||
901 | |||
902 | array->pdata = NULL; |
||
903 | array->len = 0; |
||
904 | array->alloc = 0; |
||
905 | array->ref_count = 1; |
||
906 | array->element_free_func = NULL; |
||
907 | |||
908 | if (reserved_size != 0) |
||
909 | g_ptr_array_maybe_expand (array, reserved_size); |
||
910 | |||
911 | return (GPtrArray*) array; |
||
912 | } |
||
913 | |||
914 | /** |
||
915 | * g_ptr_array_new_with_free_func: |
||
916 | * @element_free_func: (allow-none): A function to free elements with |
||
917 | * destroy @array or %NULL |
||
918 | * |
||
919 | * Creates a new #GPtrArray with a reference count of 1 and use |
||
920 | * @element_free_func for freeing each element when the array is destroyed |
||
921 | * either via g_ptr_array_unref(), when g_ptr_array_free() is called with |
||
922 | * @free_segment set to %TRUE or when removing elements. |
||
923 | * |
||
924 | * Returns: A new #GPtrArray |
||
925 | * |
||
926 | * Since: 2.22 |
||
927 | */ |
||
928 | GPtrArray* |
||
929 | g_ptr_array_new_with_free_func (GDestroyNotify element_free_func) |
||
930 | { |
||
931 | GPtrArray *array; |
||
932 | |||
933 | array = g_ptr_array_new (); |
||
934 | g_ptr_array_set_free_func (array, element_free_func); |
||
935 | |||
936 | return array; |
||
937 | } |
||
938 | |||
939 | /** |
||
940 | * g_ptr_array_new_full: |
||
941 | * @reserved_size: number of pointers preallocated |
||
942 | * @element_free_func: (allow-none): A function to free elements with |
||
943 | * destroy @array or %NULL |
||
944 | * |
||
945 | * Creates a new #GPtrArray with @reserved_size pointers preallocated |
||
946 | * and a reference count of 1. This avoids frequent reallocation, if |
||
947 | * you are going to add many pointers to the array. Note however that |
||
948 | * the size of the array is still 0. It also set @element_free_func |
||
949 | * for freeing each element when the array is destroyed either via |
||
950 | * g_ptr_array_unref(), when g_ptr_array_free() is called with |
||
951 | * @free_segment set to %TRUE or when removing elements. |
||
952 | * |
||
953 | * Returns: A new #GPtrArray |
||
954 | * |
||
955 | * Since: 2.30 |
||
956 | */ |
||
957 | GPtrArray* |
||
958 | g_ptr_array_new_full (guint reserved_size, |
||
959 | GDestroyNotify element_free_func) |
||
960 | { |
||
961 | GPtrArray *array; |
||
962 | |||
963 | array = g_ptr_array_sized_new (reserved_size); |
||
964 | g_ptr_array_set_free_func (array, element_free_func); |
||
965 | |||
966 | return array; |
||
967 | } |
||
968 | |||
969 | /** |
||
970 | * g_ptr_array_set_free_func: |
||
971 | * @array: A #GPtrArray |
||
972 | * @element_free_func: (allow-none): A function to free elements with |
||
973 | * destroy @array or %NULL |
||
974 | * |
||
975 | * Sets a function for freeing each element when @array is destroyed |
||
976 | * either via g_ptr_array_unref(), when g_ptr_array_free() is called |
||
977 | * with @free_segment set to %TRUE or when removing elements. |
||
978 | * |
||
979 | * Since: 2.22 |
||
980 | */ |
||
981 | void |
||
982 | g_ptr_array_set_free_func (GPtrArray *array, |
||
983 | GDestroyNotify element_free_func) |
||
984 | { |
||
985 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
986 | |||
987 | g_return_if_fail (array); |
||
988 | |||
989 | rarray->element_free_func = element_free_func; |
||
990 | } |
||
991 | |||
992 | /** |
||
993 | * g_ptr_array_ref: |
||
994 | * @array: a #GPtrArray |
||
995 | * |
||
996 | * Atomically increments the reference count of @array by one. |
||
997 | * This function is thread-safe and may be called from any thread. |
||
998 | * |
||
999 | * Returns: The passed in #GPtrArray |
||
1000 | * |
||
1001 | * Since: 2.22 |
||
1002 | */ |
||
1003 | GPtrArray* |
||
1004 | g_ptr_array_ref (GPtrArray *array) |
||
1005 | { |
||
1006 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1007 | |||
1008 | g_return_val_if_fail (array, NULL); |
||
1009 | |||
1010 | g_atomic_int_inc (&rarray->ref_count); |
||
1011 | |||
1012 | return array; |
||
1013 | } |
||
1014 | |||
1015 | static gpointer *ptr_array_free (GPtrArray *, ArrayFreeFlags); |
||
1016 | |||
1017 | /** |
||
1018 | * g_ptr_array_unref: |
||
1019 | * @array: A #GPtrArray |
||
1020 | * |
||
1021 | * Atomically decrements the reference count of @array by one. If the |
||
1022 | * reference count drops to 0, the effect is the same as calling |
||
1023 | * g_ptr_array_free() with @free_segment set to %TRUE. This function |
||
1024 | * is MT-safe and may be called from any thread. |
||
1025 | * |
||
1026 | * Since: 2.22 |
||
1027 | */ |
||
1028 | void |
||
1029 | g_ptr_array_unref (GPtrArray *array) |
||
1030 | { |
||
1031 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1032 | |||
1033 | g_return_if_fail (array); |
||
1034 | |||
1035 | if (g_atomic_int_dec_and_test (&rarray->ref_count)) |
||
1036 | ptr_array_free (array, FREE_SEGMENT); |
||
1037 | } |
||
1038 | |||
1039 | /** |
||
1040 | * g_ptr_array_free: |
||
1041 | * @array: a #GPtrArray |
||
1042 | * @free_seg: if %TRUE the actual pointer array is freed as well |
||
1043 | * |
||
1044 | * Frees the memory allocated for the #GPtrArray. If @free_seg is %TRUE |
||
1045 | * it frees the memory block holding the elements as well. Pass %FALSE |
||
1046 | * if you want to free the #GPtrArray wrapper but preserve the |
||
1047 | * underlying array for use elsewhere. If the reference count of @array |
||
1048 | * is greater than one, the #GPtrArray wrapper is preserved but the |
||
1049 | * size of @array will be set to zero. |
||
1050 | * |
||
1051 | * If array contents point to dynamically-allocated memory, they should |
||
1052 | * be freed separately if @free_seg is %TRUE and no #GDestroyNotify |
||
1053 | * function has been set for @array. |
||
1054 | * |
||
1055 | * Returns: the pointer array if @free_seg is %FALSE, otherwise %NULL. |
||
1056 | * The pointer array should be freed using g_free(). |
||
1057 | */ |
||
1058 | gpointer* |
||
1059 | g_ptr_array_free (GPtrArray *array, |
||
1060 | gboolean free_segment) |
||
1061 | { |
||
1062 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1063 | ArrayFreeFlags flags; |
||
1064 | |||
1065 | g_return_val_if_fail (rarray, NULL); |
||
1066 | |||
1067 | flags = (free_segment ? FREE_SEGMENT : 0); |
||
1068 | |||
1069 | /* if others are holding a reference, preserve the wrapper but |
||
1070 | * do free/return the data |
||
1071 | */ |
||
1072 | if (!g_atomic_int_dec_and_test (&rarray->ref_count)) |
||
1073 | flags |= PRESERVE_WRAPPER; |
||
1074 | |||
1075 | return ptr_array_free (array, flags); |
||
1076 | } |
||
1077 | |||
1078 | static gpointer * |
||
1079 | ptr_array_free (GPtrArray *array, |
||
1080 | ArrayFreeFlags flags) |
||
1081 | { |
||
1082 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1083 | gpointer *segment; |
||
1084 | |||
1085 | if (flags & FREE_SEGMENT) |
||
1086 | { |
||
1087 | if (rarray->element_free_func != NULL) |
||
1088 | g_ptr_array_foreach (array, (GFunc) rarray->element_free_func, NULL); |
||
1089 | g_free (rarray->pdata); |
||
1090 | segment = NULL; |
||
1091 | } |
||
1092 | else |
||
1093 | segment = rarray->pdata; |
||
1094 | |||
1095 | if (flags & PRESERVE_WRAPPER) |
||
1096 | { |
||
1097 | rarray->pdata = NULL; |
||
1098 | rarray->len = 0; |
||
1099 | rarray->alloc = 0; |
||
1100 | } |
||
1101 | else |
||
1102 | { |
||
1103 | g_slice_free1 (sizeof (GRealPtrArray), rarray); |
||
1104 | } |
||
1105 | |||
1106 | return segment; |
||
1107 | } |
||
1108 | |||
1109 | static void |
||
1110 | g_ptr_array_maybe_expand (GRealPtrArray *array, |
||
1111 | gint len) |
||
1112 | { |
||
1113 | if ((array->len + len) > array->alloc) |
||
1114 | { |
||
1115 | guint old_alloc = array->alloc; |
||
1116 | array->alloc = g_nearest_pow (array->len + len); |
||
1117 | array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE); |
||
1118 | array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc); |
||
1119 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
1120 | for ( ; old_alloc < array->alloc; old_alloc++) |
||
1121 | array->pdata [old_alloc] = NULL; |
||
1122 | } |
||
1123 | } |
||
1124 | |||
1125 | /** |
||
1126 | * g_ptr_array_set_size: |
||
1127 | * @array: a #GPtrArray |
||
1128 | * @length: the new length of the pointer array |
||
1129 | * |
||
1130 | * Sets the size of the array. When making the array larger, |
||
1131 | * newly-added elements will be set to %NULL. When making it smaller, |
||
1132 | * if @array has a non-%NULL #GDestroyNotify function then it will be |
||
1133 | * called for the removed elements. |
||
1134 | */ |
||
1135 | void |
||
1136 | g_ptr_array_set_size (GPtrArray *array, |
||
1137 | gint length) |
||
1138 | { |
||
1139 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1140 | |||
1141 | g_return_if_fail (rarray); |
||
1142 | |||
1143 | if (length > rarray->len) |
||
1144 | { |
||
1145 | int i; |
||
1146 | g_ptr_array_maybe_expand (rarray, (length - rarray->len)); |
||
1147 | /* This is not |
||
1148 | * memset (array->pdata + array->len, 0, |
||
1149 | * sizeof (gpointer) * (length - array->len)); |
||
1150 | * to make it really portable. Remember (void*)NULL needn't be |
||
1151 | * bitwise zero. It of course is silly not to use memset (..,0,..). |
||
1152 | */ |
||
1153 | for (i = rarray->len; i < length; i++) |
||
1154 | rarray->pdata[i] = NULL; |
||
1155 | } |
||
1156 | else if (length < rarray->len) |
||
1157 | g_ptr_array_remove_range (array, length, rarray->len - length); |
||
1158 | |||
1159 | rarray->len = length; |
||
1160 | } |
||
1161 | |||
1162 | /** |
||
1163 | * g_ptr_array_remove_index: |
||
1164 | * @array: a #GPtrArray |
||
1165 | * @index_: the index of the pointer to remove |
||
1166 | * |
||
1167 | * Removes the pointer at the given index from the pointer array. |
||
1168 | * The following elements are moved down one place. If @array has |
||
1169 | * a non-%NULL #GDestroyNotify function it is called for the removed |
||
1170 | * element. |
||
1171 | * |
||
1172 | * Returns: the pointer which was removed |
||
1173 | */ |
||
1174 | gpointer |
||
1175 | g_ptr_array_remove_index (GPtrArray *array, |
||
1176 | guint index_) |
||
1177 | { |
||
1178 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1179 | gpointer result; |
||
1180 | |||
1181 | g_return_val_if_fail (rarray, NULL); |
||
1182 | |||
1183 | g_return_val_if_fail (index_ < rarray->len, NULL); |
||
1184 | |||
1185 | result = rarray->pdata[index_]; |
||
1186 | |||
1187 | if (rarray->element_free_func != NULL) |
||
1188 | rarray->element_free_func (rarray->pdata[index_]); |
||
1189 | |||
1190 | if (index_ != rarray->len - 1) |
||
1191 | memmove (rarray->pdata + index_, rarray->pdata + index_ + 1, |
||
1192 | sizeof (gpointer) * (rarray->len - index_ - 1)); |
||
1193 | |||
1194 | rarray->len -= 1; |
||
1195 | |||
1196 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
1197 | rarray->pdata[rarray->len] = NULL; |
||
1198 | |||
1199 | return result; |
||
1200 | } |
||
1201 | |||
1202 | /** |
||
1203 | * g_ptr_array_remove_index_fast: |
||
1204 | * @array: a #GPtrArray |
||
1205 | * @index_: the index of the pointer to remove |
||
1206 | * |
||
1207 | * Removes the pointer at the given index from the pointer array. |
||
1208 | * The last element in the array is used to fill in the space, so |
||
1209 | * this function does not preserve the order of the array. But it |
||
1210 | * is faster than g_ptr_array_remove_index(). If @array has a non-%NULL |
||
1211 | * #GDestroyNotify function it is called for the removed element. |
||
1212 | * |
||
1213 | * Returns: the pointer which was removed |
||
1214 | */ |
||
1215 | gpointer |
||
1216 | g_ptr_array_remove_index_fast (GPtrArray *array, |
||
1217 | guint index_) |
||
1218 | { |
||
1219 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1220 | gpointer result; |
||
1221 | |||
1222 | g_return_val_if_fail (rarray, NULL); |
||
1223 | |||
1224 | g_return_val_if_fail (index_ < rarray->len, NULL); |
||
1225 | |||
1226 | result = rarray->pdata[index_]; |
||
1227 | |||
1228 | if (rarray->element_free_func != NULL) |
||
1229 | rarray->element_free_func (rarray->pdata[index_]); |
||
1230 | |||
1231 | if (index_ != rarray->len - 1) |
||
1232 | rarray->pdata[index_] = rarray->pdata[rarray->len - 1]; |
||
1233 | |||
1234 | rarray->len -= 1; |
||
1235 | |||
1236 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
1237 | rarray->pdata[rarray->len] = NULL; |
||
1238 | |||
1239 | return result; |
||
1240 | } |
||
1241 | |||
1242 | /** |
||
1243 | * g_ptr_array_remove_range: |
||
1244 | * @array: a @GPtrArray |
||
1245 | * @index_: the index of the first pointer to remove |
||
1246 | * @length: the number of pointers to remove |
||
1247 | * |
||
1248 | * Removes the given number of pointers starting at the given index |
||
1249 | * from a #GPtrArray. The following elements are moved to close the |
||
1250 | * gap. If @array has a non-%NULL #GDestroyNotify function it is |
||
1251 | * called for the removed elements. |
||
1252 | * |
||
1253 | * Returns: the @array |
||
1254 | * |
||
1255 | * Since: 2.4 |
||
1256 | */ |
||
1257 | GPtrArray* |
||
1258 | g_ptr_array_remove_range (GPtrArray *array, |
||
1259 | guint index_, |
||
1260 | guint length) |
||
1261 | { |
||
1262 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1263 | guint n; |
||
1264 | |||
1265 | g_return_val_if_fail (rarray != NULL, NULL); |
||
1266 | g_return_val_if_fail (index_ <= rarray->len, NULL); |
||
1267 | g_return_val_if_fail (index_ + length <= rarray->len, NULL); |
||
1268 | |||
1269 | if (rarray->element_free_func != NULL) |
||
1270 | { |
||
1271 | for (n = index_; n < index_ + length; n++) |
||
1272 | rarray->element_free_func (rarray->pdata[n]); |
||
1273 | } |
||
1274 | |||
1275 | if (index_ + length != rarray->len) |
||
1276 | { |
||
1277 | memmove (&rarray->pdata[index_], |
||
1278 | &rarray->pdata[index_ + length], |
||
1279 | (rarray->len - (index_ + length)) * sizeof (gpointer)); |
||
1280 | } |
||
1281 | |||
1282 | rarray->len -= length; |
||
1283 | if (G_UNLIKELY (g_mem_gc_friendly)) |
||
1284 | { |
||
1285 | guint i; |
||
1286 | for (i = 0; i < length; i++) |
||
1287 | rarray->pdata[rarray->len + i] = NULL; |
||
1288 | } |
||
1289 | |||
1290 | return array; |
||
1291 | } |
||
1292 | |||
1293 | /** |
||
1294 | * g_ptr_array_remove: |
||
1295 | * @array: a #GPtrArray |
||
1296 | * @data: the pointer to remove |
||
1297 | * |
||
1298 | * Removes the first occurrence of the given pointer from the pointer |
||
1299 | * array. The following elements are moved down one place. If @array |
||
1300 | * has a non-%NULL #GDestroyNotify function it is called for the |
||
1301 | * removed element. |
||
1302 | * |
||
1303 | * It returns %TRUE if the pointer was removed, or %FALSE if the |
||
1304 | * pointer was not found. |
||
1305 | * |
||
1306 | * Returns: %TRUE if the pointer is removed, %FALSE if the pointer |
||
1307 | * is not found in the array |
||
1308 | */ |
||
1309 | gboolean |
||
1310 | g_ptr_array_remove (GPtrArray *array, |
||
1311 | gpointer data) |
||
1312 | { |
||
1313 | guint i; |
||
1314 | |||
1315 | g_return_val_if_fail (array, FALSE); |
||
1316 | |||
1317 | for (i = 0; i < array->len; i += 1) |
||
1318 | { |
||
1319 | if (array->pdata[i] == data) |
||
1320 | { |
||
1321 | g_ptr_array_remove_index (array, i); |
||
1322 | return TRUE; |
||
1323 | } |
||
1324 | } |
||
1325 | |||
1326 | return FALSE; |
||
1327 | } |
||
1328 | |||
1329 | /** |
||
1330 | * g_ptr_array_remove_fast: |
||
1331 | * @array: a #GPtrArray |
||
1332 | * @data: the pointer to remove |
||
1333 | * |
||
1334 | * Removes the first occurrence of the given pointer from the pointer |
||
1335 | * array. The last element in the array is used to fill in the space, |
||
1336 | * so this function does not preserve the order of the array. But it |
||
1337 | * is faster than g_ptr_array_remove(). If @array has a non-%NULL |
||
1338 | * #GDestroyNotify function it is called for the removed element. |
||
1339 | * |
||
1340 | * It returns %TRUE if the pointer was removed, or %FALSE if the |
||
1341 | * pointer was not found. |
||
1342 | * |
||
1343 | * Returns: %TRUE if the pointer was found in the array |
||
1344 | */ |
||
1345 | gboolean |
||
1346 | g_ptr_array_remove_fast (GPtrArray *array, |
||
1347 | gpointer data) |
||
1348 | { |
||
1349 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1350 | guint i; |
||
1351 | |||
1352 | g_return_val_if_fail (rarray, FALSE); |
||
1353 | |||
1354 | for (i = 0; i < rarray->len; i += 1) |
||
1355 | { |
||
1356 | if (rarray->pdata[i] == data) |
||
1357 | { |
||
1358 | g_ptr_array_remove_index_fast (array, i); |
||
1359 | return TRUE; |
||
1360 | } |
||
1361 | } |
||
1362 | |||
1363 | return FALSE; |
||
1364 | } |
||
1365 | |||
1366 | /** |
||
1367 | * g_ptr_array_add: |
||
1368 | * @array: a #GPtrArray |
||
1369 | * @data: the pointer to add |
||
1370 | * |
||
1371 | * Adds a pointer to the end of the pointer array. The array will grow |
||
1372 | * in size automatically if necessary. |
||
1373 | */ |
||
1374 | void |
||
1375 | g_ptr_array_add (GPtrArray *array, |
||
1376 | gpointer data) |
||
1377 | { |
||
1378 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1379 | |||
1380 | g_return_if_fail (rarray); |
||
1381 | |||
1382 | g_ptr_array_maybe_expand (rarray, 1); |
||
1383 | |||
1384 | rarray->pdata[rarray->len++] = data; |
||
1385 | } |
||
1386 | |||
1387 | /** |
||
1388 | * g_ptr_array_insert: |
||
1389 | * @array: a #GPtrArray |
||
1390 | * @index_: the index to place the new element at, or -1 to append |
||
1391 | * @data: the pointer to add. |
||
1392 | * |
||
1393 | * Inserts an element into the pointer array at the given index. The |
||
1394 | * array will grow in size automatically if necessary. |
||
1395 | * |
||
1396 | * Since: 2.40 |
||
1397 | */ |
||
1398 | void |
||
1399 | g_ptr_array_insert (GPtrArray *array, |
||
1400 | gint index_, |
||
1401 | gpointer data) |
||
1402 | { |
||
1403 | GRealPtrArray *rarray = (GRealPtrArray *)array; |
||
1404 | |||
1405 | g_return_if_fail (rarray); |
||
1406 | g_return_if_fail (index_ >= -1); |
||
1407 | g_return_if_fail (index_ <= (gint)rarray->len); |
||
1408 | |||
1409 | g_ptr_array_maybe_expand (rarray, 1); |
||
1410 | |||
1411 | if (index_ < 0) |
||
1412 | index_ = rarray->len; |
||
1413 | |||
1414 | if (index_ < rarray->len) |
||
1415 | memmove (&(rarray->pdata[index_ + 1]), |
||
1416 | &(rarray->pdata[index_]), |
||
1417 | (rarray->len - index_) * sizeof (gpointer)); |
||
1418 | |||
1419 | rarray->len++; |
||
1420 | rarray->pdata[index_] = data; |
||
1421 | } |
||
1422 | |||
1423 | /** |
||
1424 | * g_ptr_array_sort: |
||
1425 | * @array: a #GPtrArray |
||
1426 | * @compare_func: comparison function |
||
1427 | * |
||
1428 | * Sorts the array, using @compare_func which should be a qsort()-style |
||
1429 | * comparison function (returns less than zero for first arg is less |
||
1430 | * than second arg, zero for equal, greater than zero if irst arg is |
||
1431 | * greater than second arg). |
||
1432 | * |
||
1433 | * Note that the comparison function for g_ptr_array_sort() doesn't |
||
1434 | * take the pointers from the array as arguments, it takes pointers to |
||
1435 | * the pointers in the array. |
||
1436 | * |
||
1437 | * This is guaranteed to be a stable sort since version 2.32. |
||
1438 | */ |
||
1439 | void |
||
1440 | g_ptr_array_sort (GPtrArray *array, |
||
1441 | GCompareFunc compare_func) |
||
1442 | { |
||
1443 | g_return_if_fail (array != NULL); |
||
1444 | |||
1445 | /* Don't use qsort as we want a guaranteed stable sort */ |
||
1446 | g_qsort_with_data (array->pdata, |
||
1447 | array->len, |
||
1448 | sizeof (gpointer), |
||
1449 | (GCompareDataFunc)compare_func, |
||
1450 | NULL); |
||
1451 | } |
||
1452 | |||
1453 | /** |
||
1454 | * g_ptr_array_sort_with_data: |
||
1455 | * @array: a #GPtrArray |
||
1456 | * @compare_func: comparison function |
||
1457 | * @user_data: data to pass to @compare_func |
||
1458 | * |
||
1459 | * Like g_ptr_array_sort(), but the comparison function has an extra |
||
1460 | * user data argument. |
||
1461 | * |
||
1462 | * Note that the comparison function for g_ptr_array_sort_with_data() |
||
1463 | * doesn't take the pointers from the array as arguments, it takes |
||
1464 | * pointers to the pointers in the array. |
||
1465 | * |
||
1466 | * This is guaranteed to be a stable sort since version 2.32. |
||
1467 | */ |
||
1468 | void |
||
1469 | g_ptr_array_sort_with_data (GPtrArray *array, |
||
1470 | GCompareDataFunc compare_func, |
||
1471 | gpointer user_data) |
||
1472 | { |
||
1473 | g_return_if_fail (array != NULL); |
||
1474 | |||
1475 | g_qsort_with_data (array->pdata, |
||
1476 | array->len, |
||
1477 | sizeof (gpointer), |
||
1478 | compare_func, |
||
1479 | user_data); |
||
1480 | } |
||
1481 | |||
1482 | /** |
||
1483 | * g_ptr_array_foreach: |
||
1484 | * @array: a #GPtrArray |
||
1485 | * @func: the function to call for each array element |
||
1486 | * @user_data: user data to pass to the function |
||
1487 | * |
||
1488 | * Calls a function for each element of a #GPtrArray. |
||
1489 | * |
||
1490 | * Since: 2.4 |
||
1491 | */ |
||
1492 | void |
||
1493 | g_ptr_array_foreach (GPtrArray *array, |
||
1494 | GFunc func, |
||
1495 | gpointer user_data) |
||
1496 | { |
||
1497 | guint i; |
||
1498 | |||
1499 | g_return_if_fail (array); |
||
1500 | |||
1501 | for (i = 0; i < array->len; i++) |
||
1502 | (*func) (array->pdata[i], user_data); |
||
1503 | } |
||
1504 | |||
1505 | /** |
||
1506 | * SECTION:arrays_byte |
||
1507 | * @title: Byte Arrays |
||
1508 | * @short_description: arrays of bytes |
||
1509 | * |
||
1510 | * #GByteArray is a mutable array of bytes based on #GArray, to provide arrays |
||
1511 | * of bytes which grow automatically as elements are added. |
||
1512 | * |
||
1513 | * To create a new #GByteArray use g_byte_array_new(). To add elements to a |
||
1514 | * #GByteArray, use g_byte_array_append(), and g_byte_array_prepend(). |
||
1515 | * |
||
1516 | * To set the size of a #GByteArray, use g_byte_array_set_size(). |
||
1517 | * |
||
1518 | * To free a #GByteArray, use g_byte_array_free(). |
||
1519 | * |
||
1520 | * An example for using a #GByteArray: |
||
1521 | * |[<!-- language="C" --> |
||
1522 | * GByteArray *gbarray; |
||
1523 | * gint i; |
||
1524 | * |
||
1525 | * gbarray = g_byte_array_new (); |
||
1526 | * for (i = 0; i < 10000; i++) |
||
1527 | * g_byte_array_append (gbarray, (guint8*) "abcd", 4); |
||
1528 | * |
||
1529 | * for (i = 0; i < 10000; i++) |
||
1530 | * { |
||
1531 | * g_assert (gbarray->data[4*i] == 'a'); |
||
1532 | * g_assert (gbarray->data[4*i+1] == 'b'); |
||
1533 | * g_assert (gbarray->data[4*i+2] == 'c'); |
||
1534 | * g_assert (gbarray->data[4*i+3] == 'd'); |
||
1535 | * } |
||
1536 | * |
||
1537 | * g_byte_array_free (gbarray, TRUE); |
||
1538 | * ]| |
||
1539 | * |
||
1540 | * See #GBytes if you are interested in an immutable object representing a |
||
1541 | * sequence of bytes. |
||
1542 | */ |
||
1543 | |||
1544 | /** |
||
1545 | * GByteArray: |
||
1546 | * @data: a pointer to the element data. The data may be moved as |
||
1547 | * elements are added to the #GByteArray |
||
1548 | * @len: the number of elements in the #GByteArray |
||
1549 | * |
||
1550 | * Contains the public fields of a GByteArray. |
||
1551 | */ |
||
1552 | |||
1553 | /** |
||
1554 | * g_byte_array_new: |
||
1555 | * |
||
1556 | * Creates a new #GByteArray with a reference count of 1. |
||
1557 | * |
||
1558 | * Returns: (transfer full): the new #GByteArray |
||
1559 | */ |
||
1560 | GByteArray* |
||
1561 | g_byte_array_new (void) |
||
1562 | { |
||
1563 | return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, 0); |
||
1564 | } |
||
1565 | |||
1566 | /** |
||
1567 | * g_byte_array_new_take: |
||
1568 | * @data: (transfer full) (array length=len): byte data for the array |
||
1569 | * @len: length of @data |
||
1570 | * |
||
1571 | * Create byte array containing the data. The data will be owned by the array |
||
1572 | * and will be freed with g_free(), i.e. it could be allocated using g_strdup(). |
||
1573 | * |
||
1574 | * Since: 2.32 |
||
1575 | * |
||
1576 | * Returns: (transfer full): a new #GByteArray |
||
1577 | */ |
||
1578 | GByteArray* |
||
1579 | g_byte_array_new_take (guint8 *data, |
||
1580 | gsize len) |
||
1581 | { |
||
1582 | GByteArray *array; |
||
1583 | GRealArray *real; |
||
1584 | |||
1585 | array = g_byte_array_new (); |
||
1586 | real = (GRealArray *)array; |
||
1587 | g_assert (real->data == NULL); |
||
1588 | g_assert (real->len == 0); |
||
1589 | |||
1590 | real->data = data; |
||
1591 | real->len = len; |
||
1592 | real->alloc = len; |
||
1593 | |||
1594 | return array; |
||
1595 | } |
||
1596 | |||
1597 | /** |
||
1598 | * g_byte_array_sized_new: |
||
1599 | * @reserved_size: number of bytes preallocated |
||
1600 | * |
||
1601 | * Creates a new #GByteArray with @reserved_size bytes preallocated. |
||
1602 | * This avoids frequent reallocation, if you are going to add many |
||
1603 | * bytes to the array. Note however that the size of the array is still |
||
1604 | * 0. |
||
1605 | * |
||
1606 | * Returns: the new #GByteArray |
||
1607 | */ |
||
1608 | GByteArray* |
||
1609 | g_byte_array_sized_new (guint reserved_size) |
||
1610 | { |
||
1611 | return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, reserved_size); |
||
1612 | } |
||
1613 | |||
1614 | /** |
||
1615 | * g_byte_array_free: |
||
1616 | * @array: a #GByteArray |
||
1617 | * @free_segment: if %TRUE the actual byte data is freed as well |
||
1618 | * |
||
1619 | * Frees the memory allocated by the #GByteArray. If @free_segment is |
||
1620 | * %TRUE it frees the actual byte data. If the reference count of |
||
1621 | * @array is greater than one, the #GByteArray wrapper is preserved but |
||
1622 | * the size of @array will be set to zero. |
||
1623 | * |
||
1624 | * Returns: the element data if @free_segment is %FALSE, otherwise |
||
1625 | * %NULL. The element data should be freed using g_free(). |
||
1626 | */ |
||
1627 | guint8* |
||
1628 | g_byte_array_free (GByteArray *array, |
||
1629 | gboolean free_segment) |
||
1630 | { |
||
1631 | return (guint8 *)g_array_free ((GArray *)array, free_segment); |
||
1632 | } |
||
1633 | |||
1634 | /** |
||
1635 | * g_byte_array_free_to_bytes: |
||
1636 | * @array: (transfer full): a #GByteArray |
||
1637 | * |
||
1638 | * Transfers the data from the #GByteArray into a new immutable #GBytes. |
||
1639 | * |
||
1640 | * The #GByteArray is freed unless the reference count of @array is greater |
||
1641 | * than one, the #GByteArray wrapper is preserved but the size of @array |
||
1642 | * will be set to zero. |
||
1643 | * |
||
1644 | * This is identical to using g_bytes_new_take() and g_byte_array_free() |
||
1645 | * together. |
||
1646 | * |
||
1647 | * Since: 2.32 |
||
1648 | * |
||
1649 | * Returns: (transfer full): a new immutable #GBytes representing same |
||
1650 | * byte data that was in the array |
||
1651 | */ |
||
1652 | GBytes* |
||
1653 | g_byte_array_free_to_bytes (GByteArray *array) |
||
1654 | { |
||
1655 | gsize length; |
||
1656 | |||
1657 | g_return_val_if_fail (array != NULL, NULL); |
||
1658 | |||
1659 | length = array->len; |
||
1660 | return g_bytes_new_take (g_byte_array_free (array, FALSE), length); |
||
1661 | } |
||
1662 | |||
1663 | /** |
||
1664 | * g_byte_array_ref: |
||
1665 | * @array: A #GByteArray |
||
1666 | * |
||
1667 | * Atomically increments the reference count of @array by one. |
||
1668 | * This function is thread-safe and may be called from any thread. |
||
1669 | * |
||
1670 | * Returns: The passed in #GByteArray |
||
1671 | * |
||
1672 | * Since: 2.22 |
||
1673 | */ |
||
1674 | GByteArray* |
||
1675 | g_byte_array_ref (GByteArray *array) |
||
1676 | { |
||
1677 | return (GByteArray *)g_array_ref ((GArray *)array); |
||
1678 | } |
||
1679 | |||
1680 | /** |
||
1681 | * g_byte_array_unref: |
||
1682 | * @array: A #GByteArray |
||
1683 | * |
||
1684 | * Atomically decrements the reference count of @array by one. If the |
||
1685 | * reference count drops to 0, all memory allocated by the array is |
||
1686 | * released. This function is thread-safe and may be called from any |
||
1687 | * thread. |
||
1688 | * |
||
1689 | * Since: 2.22 |
||
1690 | */ |
||
1691 | void |
||
1692 | g_byte_array_unref (GByteArray *array) |
||
1693 | { |
||
1694 | g_array_unref ((GArray *)array); |
||
1695 | } |
||
1696 | |||
1697 | /** |
||
1698 | * g_byte_array_append: |
||
1699 | * @array: a #GByteArray |
||
1700 | * @data: the byte data to be added |
||
1701 | * @len: the number of bytes to add |
||
1702 | * |
||
1703 | * Adds the given bytes to the end of the #GByteArray. |
||
1704 | * The array will grow in size automatically if necessary. |
||
1705 | * |
||
1706 | * Returns: the #GByteArray |
||
1707 | */ |
||
1708 | GByteArray* |
||
1709 | g_byte_array_append (GByteArray *array, |
||
1710 | const guint8 *data, |
||
1711 | guint len) |
||
1712 | { |
||
1713 | g_array_append_vals ((GArray *)array, (guint8 *)data, len); |
||
1714 | |||
1715 | return array; |
||
1716 | } |
||
1717 | |||
1718 | /** |
||
1719 | * g_byte_array_prepend: |
||
1720 | * @array: a #GByteArray |
||
1721 | * @data: the byte data to be added |
||
1722 | * @len: the number of bytes to add |
||
1723 | * |
||
1724 | * Adds the given data to the start of the #GByteArray. |
||
1725 | * The array will grow in size automatically if necessary. |
||
1726 | * |
||
1727 | * Returns: the #GByteArray |
||
1728 | */ |
||
1729 | GByteArray* |
||
1730 | g_byte_array_prepend (GByteArray *array, |
||
1731 | const guint8 *data, |
||
1732 | guint len) |
||
1733 | { |
||
1734 | g_array_prepend_vals ((GArray *)array, (guint8 *)data, len); |
||
1735 | |||
1736 | return array; |
||
1737 | } |
||
1738 | |||
1739 | /** |
||
1740 | * g_byte_array_set_size: |
||
1741 | * @array: a #GByteArray |
||
1742 | * @length: the new size of the #GByteArray |
||
1743 | * |
||
1744 | * Sets the size of the #GByteArray, expanding it if necessary. |
||
1745 | * |
||
1746 | * Returns: the #GByteArray |
||
1747 | */ |
||
1748 | GByteArray* |
||
1749 | g_byte_array_set_size (GByteArray *array, |
||
1750 | guint length) |
||
1751 | { |
||
1752 | g_array_set_size ((GArray *)array, length); |
||
1753 | |||
1754 | return array; |
||
1755 | } |
||
1756 | |||
1757 | /** |
||
1758 | * g_byte_array_remove_index: |
||
1759 | * @array: a #GByteArray |
||
1760 | * @index_: the index of the byte to remove |
||
1761 | * |
||
1762 | * Removes the byte at the given index from a #GByteArray. |
||
1763 | * The following bytes are moved down one place. |
||
1764 | * |
||
1765 | * Returns: the #GByteArray |
||
1766 | **/ |
||
1767 | GByteArray* |
||
1768 | g_byte_array_remove_index (GByteArray *array, |
||
1769 | guint index_) |
||
1770 | { |
||
1771 | g_array_remove_index ((GArray *)array, index_); |
||
1772 | |||
1773 | return array; |
||
1774 | } |
||
1775 | |||
1776 | /** |
||
1777 | * g_byte_array_remove_index_fast: |
||
1778 | * @array: a #GByteArray |
||
1779 | * @index_: the index of the byte to remove |
||
1780 | * |
||
1781 | * Removes the byte at the given index from a #GByteArray. The last |
||
1782 | * element in the array is used to fill in the space, so this function |
||
1783 | * does not preserve the order of the #GByteArray. But it is faster |
||
1784 | * than g_byte_array_remove_index(). |
||
1785 | * |
||
1786 | * Returns: the #GByteArray |
||
1787 | */ |
||
1788 | GByteArray* |
||
1789 | g_byte_array_remove_index_fast (GByteArray *array, |
||
1790 | guint index_) |
||
1791 | { |
||
1792 | g_array_remove_index_fast ((GArray *)array, index_); |
||
1793 | |||
1794 | return array; |
||
1795 | } |
||
1796 | |||
1797 | /** |
||
1798 | * g_byte_array_remove_range: |
||
1799 | * @array: a @GByteArray |
||
1800 | * @index_: the index of the first byte to remove |
||
1801 | * @length: the number of bytes to remove |
||
1802 | * |
||
1803 | * Removes the given number of bytes starting at the given index from a |
||
1804 | * #GByteArray. The following elements are moved to close the gap. |
||
1805 | * |
||
1806 | * Returns: the #GByteArray |
||
1807 | * |
||
1808 | * Since: 2.4 |
||
1809 | */ |
||
1810 | GByteArray* |
||
1811 | g_byte_array_remove_range (GByteArray *array, |
||
1812 | guint index_, |
||
1813 | guint length) |
||
1814 | { |
||
1815 | g_return_val_if_fail (array, NULL); |
||
1816 | g_return_val_if_fail (index_ <= array->len, NULL); |
||
1817 | g_return_val_if_fail (index_ + length <= array->len, NULL); |
||
1818 | |||
1819 | return (GByteArray *)g_array_remove_range ((GArray *)array, index_, length); |
||
1820 | } |
||
1821 | |||
1822 | /** |
||
1823 | * g_byte_array_sort: |
||
1824 | * @array: a #GByteArray |
||
1825 | * @compare_func: comparison function |
||
1826 | * |
||
1827 | * Sorts a byte array, using @compare_func which should be a |
||
1828 | * qsort()-style comparison function (returns less than zero for first |
||
1829 | * arg is less than second arg, zero for equal, greater than zero if |
||
1830 | * first arg is greater than second arg). |
||
1831 | * |
||
1832 | * If two array elements compare equal, their order in the sorted array |
||
1833 | * is undefined. If you want equal elements to keep their order (i.e. |
||
1834 | * you want a stable sort) you can write a comparison function that, |
||
1835 | * if two elements would otherwise compare equal, compares them by |
||
1836 | * their addresses. |
||
1837 | */ |
||
1838 | void |
||
1839 | g_byte_array_sort (GByteArray *array, |
||
1840 | GCompareFunc compare_func) |
||
1841 | { |
||
1842 | g_array_sort ((GArray *)array, compare_func); |
||
1843 | } |
||
1844 | |||
1845 | /** |
||
1846 | * g_byte_array_sort_with_data: |
||
1847 | * @array: a #GByteArray |
||
1848 | * @compare_func: comparison function |
||
1849 | * @user_data: data to pass to @compare_func |
||
1850 | * |
||
1851 | * Like g_byte_array_sort(), but the comparison function takes an extra |
||
1852 | * user data argument. |
||
1853 | */ |
||
1854 | void |
||
1855 | g_byte_array_sort_with_data (GByteArray *array, |
||
1856 | GCompareDataFunc compare_func, |
||
1857 | gpointer user_data) |
||
1858 | { |
||
1859 | g_array_sort_with_data ((GArray *)array, compare_func, user_data); |
||
1860 | } |