1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
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/.
40 #include "gmessages.h"
46 #define MIN_ARRAY_SIZE 16
48 typedef struct _GRealArray GRealArray;
56 guint zero_terminated : 1;
58 volatile gint ref_count;
61 #define g_array_elt_len(array,i) ((array)->elt_size * (i))
62 #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
63 #define g_array_elt_zero(array, pos, len) \
64 (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
65 #define g_array_zero_terminate(array) G_STMT_START{ \
66 if ((array)->zero_terminated) \
67 g_array_elt_zero ((array), (array)->len, 1); \
70 static guint g_nearest_pow (gint num) G_GNUC_CONST;
71 static void g_array_maybe_expand (GRealArray *array,
75 g_array_new (gboolean zero_terminated,
79 return (GArray*) g_array_sized_new (zero_terminated, clear, elt_size, 0);
82 GArray* g_array_sized_new (gboolean zero_terminated,
87 GRealArray *array = g_slice_new (GRealArray);
92 array->zero_terminated = (zero_terminated ? 1 : 0);
93 array->clear = (clear ? 1 : 0);
94 array->elt_size = elt_size;
97 if (array->zero_terminated || reserved_size != 0)
99 g_array_maybe_expand (array, reserved_size);
100 g_array_zero_terminate(array);
103 return (GArray*) array;
110 * Atomically increments the reference count of @array by one. This
111 * function is MT-safe and may be called from any thread.
113 * Returns: The passed in #GArray.
118 g_array_ref (GArray *array)
120 GRealArray *rarray = (GRealArray*) array;
121 g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
122 g_atomic_int_inc (&rarray->ref_count);
130 * Atomically decrements the reference count of @array by one. If the
131 * reference count drops to 0, all memory allocated by the array is
132 * released. This function is MT-safe and may be called from any
138 g_array_unref (GArray *array)
140 GRealArray *rarray = (GRealArray*) array;
141 g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
142 if (g_atomic_int_dec_and_test (&rarray->ref_count))
143 g_array_free (array, TRUE);
147 * g_array_get_element_size:
150 * Gets the size of the elements in @array.
152 * Returns: Size of each element, in bytes.
157 g_array_get_element_size (GArray *array)
159 GRealArray *rarray = (GRealArray*) array;
160 return rarray->elt_size;
164 g_array_free (GArray *farray,
165 gboolean free_segment)
167 GRealArray *array = (GRealArray*) farray;
169 gboolean preserve_wrapper;
171 g_return_val_if_fail (array, NULL);
173 /* if others are holding a reference, preserve the wrapper but do free/return the data */
174 preserve_wrapper = FALSE;
175 if (g_atomic_int_get (&array->ref_count) > 1)
176 preserve_wrapper = TRUE;
180 g_free (array->data);
184 segment = (gchar*) array->data;
186 if (preserve_wrapper)
194 g_slice_free1 (sizeof (GRealArray), array);
201 g_array_append_vals (GArray *farray,
205 GRealArray *array = (GRealArray*) farray;
207 g_array_maybe_expand (array, len);
209 memcpy (g_array_elt_pos (array, array->len), data,
210 g_array_elt_len (array, len));
214 g_array_zero_terminate (array);
220 g_array_prepend_vals (GArray *farray,
224 GRealArray *array = (GRealArray*) farray;
226 g_array_maybe_expand (array, len);
228 g_memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0),
229 g_array_elt_len (array, array->len));
231 memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
235 g_array_zero_terminate (array);
241 g_array_insert_vals (GArray *farray,
246 GRealArray *array = (GRealArray*) farray;
248 g_array_maybe_expand (array, len);
250 g_memmove (g_array_elt_pos (array, len + index_),
251 g_array_elt_pos (array, index_),
252 g_array_elt_len (array, array->len - index_));
254 memcpy (g_array_elt_pos (array, index_), data, g_array_elt_len (array, len));
258 g_array_zero_terminate (array);
264 g_array_set_size (GArray *farray,
267 GRealArray *array = (GRealArray*) farray;
268 if (length > array->len)
270 g_array_maybe_expand (array, length - array->len);
273 g_array_elt_zero (array, array->len, length - array->len);
275 else if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
276 g_array_elt_zero (array, length, array->len - length);
280 g_array_zero_terminate (array);
286 g_array_remove_index (GArray *farray,
289 GRealArray* array = (GRealArray*) farray;
291 g_return_val_if_fail (array, NULL);
293 g_return_val_if_fail (index_ < array->len, NULL);
295 if (index_ != array->len - 1)
296 g_memmove (g_array_elt_pos (array, index_),
297 g_array_elt_pos (array, index_ + 1),
298 g_array_elt_len (array, array->len - index_ - 1));
302 if (G_UNLIKELY (g_mem_gc_friendly))
303 g_array_elt_zero (array, array->len, 1);
305 g_array_zero_terminate (array);
311 g_array_remove_index_fast (GArray *farray,
314 GRealArray* array = (GRealArray*) farray;
316 g_return_val_if_fail (array, NULL);
318 g_return_val_if_fail (index_ < array->len, NULL);
320 if (index_ != array->len - 1)
321 memcpy (g_array_elt_pos (array, index_),
322 g_array_elt_pos (array, array->len - 1),
323 g_array_elt_len (array, 1));
327 if (G_UNLIKELY (g_mem_gc_friendly))
328 g_array_elt_zero (array, array->len, 1);
330 g_array_zero_terminate (array);
336 g_array_remove_range (GArray *farray,
340 GRealArray *array = (GRealArray*) farray;
342 g_return_val_if_fail (array, NULL);
343 g_return_val_if_fail (index_ < array->len, NULL);
344 g_return_val_if_fail (index_ + length <= array->len, NULL);
346 if (index_ + length != array->len)
347 g_memmove (g_array_elt_pos (array, index_),
348 g_array_elt_pos (array, index_ + length),
349 (array->len - (index_ + length)) * array->elt_size);
351 array->len -= length;
352 if (G_UNLIKELY (g_mem_gc_friendly))
353 g_array_elt_zero (array, array->len, length);
355 g_array_zero_terminate (array);
361 g_array_sort (GArray *farray,
362 GCompareFunc compare_func)
364 GRealArray *array = (GRealArray*) farray;
366 g_return_if_fail (array != NULL);
375 g_array_sort_with_data (GArray *farray,
376 GCompareDataFunc compare_func,
379 GRealArray *array = (GRealArray*) farray;
381 g_return_if_fail (array != NULL);
383 g_qsort_with_data (array->data,
390 /* Returns the smallest power of 2 greater than n, or n if
391 * such power does not fit in a guint
394 g_nearest_pow (gint num)
398 while (n < num && n > 0)
405 g_array_maybe_expand (GRealArray *array,
408 guint want_alloc = g_array_elt_len (array, array->len + len +
409 array->zero_terminated);
411 if (want_alloc > array->alloc)
413 want_alloc = g_nearest_pow (want_alloc);
414 want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
416 array->data = g_realloc (array->data, want_alloc);
418 if (G_UNLIKELY (g_mem_gc_friendly))
419 memset (array->data + array->alloc, 0, want_alloc - array->alloc);
421 array->alloc = want_alloc;
428 typedef struct _GRealPtrArray GRealPtrArray;
430 struct _GRealPtrArray
435 volatile gint ref_count;
436 GDestroyNotify element_free_func;
439 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
443 g_ptr_array_new (void)
445 return g_ptr_array_sized_new (0);
449 g_ptr_array_sized_new (guint reserved_size)
451 GRealPtrArray *array = g_slice_new (GRealPtrArray);
456 array->ref_count = 1;
457 array->element_free_func = NULL;
459 if (reserved_size != 0)
460 g_ptr_array_maybe_expand (array, reserved_size);
462 return (GPtrArray*) array;
466 * g_ptr_array_new_with_free_func:
467 * @element_free_func: A function to free elements with destroy @array or %NULL.
469 * Creates a new #GPtrArray with a reference count of 1 and use @element_free_func
470 * for freeing each element when the array is destroyed either via
471 * g_ptr_array_unref(), when g_ptr_array_free() is called with @free_segment
472 * set to %TRUE or when removing elements.
474 * Returns: A new #GPtrArray.
479 g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
483 array = g_ptr_array_new ();
484 g_ptr_array_set_free_func (array, element_free_func);
489 * g_ptr_array_set_free_func:
490 * @array: A #GPtrArray.
491 * @element_free_func: A function to free elements with destroy @array or %NULL.
493 * Sets a function for freeing each element when @array is destroyed
494 * either via g_ptr_array_unref(), when g_ptr_array_free() is called
495 * with @free_segment set to %TRUE or when removing elements.
500 g_ptr_array_set_free_func (GPtrArray *array,
501 GDestroyNotify element_free_func)
503 GRealPtrArray* rarray = (GRealPtrArray*) array;
504 rarray->element_free_func = element_free_func;
511 * Atomically increments the reference count of @array by one. This
512 * function is MT-safe and may be called from any thread.
514 * Returns: The passed in #GPtrArray.
519 g_ptr_array_ref (GPtrArray *array)
521 GRealPtrArray *rarray = (GRealPtrArray*) array;
522 g_return_val_if_fail (g_atomic_int_get (&rarray->ref_count) > 0, array);
523 g_atomic_int_inc (&rarray->ref_count);
529 * @array: A #GPtrArray.
531 * Atomically decrements the reference count of @array by one. If the
532 * reference count drops to 0, the effect is the same as calling
533 * g_ptr_array_free() with @free_segment set to %TRUE. This function
534 * is MT-safe and may be called from any thread.
539 g_ptr_array_unref (GPtrArray *array)
541 GRealPtrArray *rarray = (GRealPtrArray*) array;
542 g_return_if_fail (g_atomic_int_get (&rarray->ref_count) > 0);
543 if (g_atomic_int_dec_and_test (&rarray->ref_count))
544 g_ptr_array_free (array, TRUE);
548 g_ptr_array_free (GPtrArray *farray,
549 gboolean free_segment)
551 GRealPtrArray *array = (GRealPtrArray*) farray;
553 gboolean preserve_wrapper;
555 g_return_val_if_fail (array, NULL);
557 /* if others are holding a reference, preserve the wrapper but do free/return the data */
558 preserve_wrapper = FALSE;
559 if (g_atomic_int_get (&array->ref_count) > 1)
560 preserve_wrapper = TRUE;
564 if (array->element_free_func != NULL)
565 g_ptr_array_foreach (farray, (GFunc) array->element_free_func, NULL);
566 g_free (array->pdata);
570 segment = array->pdata;
572 if (preserve_wrapper)
580 g_slice_free1 (sizeof (GRealPtrArray), array);
587 g_ptr_array_maybe_expand (GRealPtrArray *array,
590 if ((array->len + len) > array->alloc)
592 guint old_alloc = array->alloc;
593 array->alloc = g_nearest_pow (array->len + len);
594 array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
595 array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc);
596 if (G_UNLIKELY (g_mem_gc_friendly))
597 for ( ; old_alloc < array->alloc; old_alloc++)
598 array->pdata [old_alloc] = NULL;
603 g_ptr_array_set_size (GPtrArray *farray,
606 GRealPtrArray* array = (GRealPtrArray*) farray;
608 g_return_if_fail (array);
610 if (length > array->len)
613 g_ptr_array_maybe_expand (array, (length - array->len));
615 * memset (array->pdata + array->len, 0,
616 * sizeof (gpointer) * (length - array->len));
617 * to make it really portable. Remember (void*)NULL needn't be
618 * bitwise zero. It of course is silly not to use memset (..,0,..).
620 for (i = array->len; i < length; i++)
621 array->pdata[i] = NULL;
623 else if (length < array->len)
624 g_ptr_array_remove_range (farray, length, array->len - length);
630 g_ptr_array_remove_index (GPtrArray *farray,
633 GRealPtrArray* array = (GRealPtrArray*) farray;
636 g_return_val_if_fail (array, NULL);
638 g_return_val_if_fail (index_ < array->len, NULL);
640 result = array->pdata[index_];
642 if (array->element_free_func != NULL)
643 array->element_free_func (array->pdata[index_]);
645 if (index_ != array->len - 1)
646 g_memmove (array->pdata + index_, array->pdata + index_ + 1,
647 sizeof (gpointer) * (array->len - index_ - 1));
651 if (G_UNLIKELY (g_mem_gc_friendly))
652 array->pdata[array->len] = NULL;
658 g_ptr_array_remove_index_fast (GPtrArray *farray,
661 GRealPtrArray* array = (GRealPtrArray*) farray;
664 g_return_val_if_fail (array, NULL);
666 g_return_val_if_fail (index_ < array->len, NULL);
668 result = array->pdata[index_];
670 if (index_ != array->len - 1)
672 if (array->element_free_func != NULL)
673 array->element_free_func (array->pdata[index_]);
674 array->pdata[index_] = array->pdata[array->len - 1];
679 if (G_UNLIKELY (g_mem_gc_friendly))
680 array->pdata[array->len] = NULL;
686 g_ptr_array_remove_range (GPtrArray *farray,
690 GRealPtrArray* array = (GRealPtrArray*) farray;
693 g_return_if_fail (array);
694 g_return_if_fail (index_ < array->len);
695 g_return_if_fail (index_ + length <= array->len);
697 if (array->element_free_func != NULL)
699 for (n = index_; n < index_ + length; n++)
700 array->element_free_func (array->pdata[n]);
703 if (index_ + length != array->len)
705 g_memmove (&array->pdata[index_],
706 &array->pdata[index_ + length],
707 (array->len - (index_ + length)) * sizeof (gpointer));
710 array->len -= length;
711 if (G_UNLIKELY (g_mem_gc_friendly))
714 for (i = 0; i < length; i++)
715 array->pdata[array->len + i] = NULL;
720 g_ptr_array_remove (GPtrArray *farray,
723 GRealPtrArray* array = (GRealPtrArray*) farray;
726 g_return_val_if_fail (array, FALSE);
728 for (i = 0; i < array->len; i += 1)
730 if (array->pdata[i] == data)
732 g_ptr_array_remove_index (farray, i);
741 g_ptr_array_remove_fast (GPtrArray *farray,
744 GRealPtrArray* array = (GRealPtrArray*) farray;
747 g_return_val_if_fail (array, FALSE);
749 for (i = 0; i < array->len; i += 1)
751 if (array->pdata[i] == data)
753 g_ptr_array_remove_index_fast (farray, i);
762 g_ptr_array_add (GPtrArray *farray,
765 GRealPtrArray* array = (GRealPtrArray*) farray;
767 g_return_if_fail (array);
769 g_ptr_array_maybe_expand (array, 1);
771 array->pdata[array->len++] = data;
775 g_ptr_array_sort (GPtrArray *array,
776 GCompareFunc compare_func)
778 g_return_if_fail (array != NULL);
787 g_ptr_array_sort_with_data (GPtrArray *array,
788 GCompareDataFunc compare_func,
791 g_return_if_fail (array != NULL);
793 g_qsort_with_data (array->pdata,
801 * g_ptr_array_foreach:
802 * @array: a #GPtrArray
803 * @func: the function to call for each array element
804 * @user_data: user data to pass to the function
806 * Calls a function for each element of a #GPtrArray.
811 g_ptr_array_foreach (GPtrArray *array,
817 g_return_if_fail (array);
819 for (i = 0; i < array->len; i++)
820 (*func) (array->pdata[i], user_data);
826 GByteArray* g_byte_array_new (void)
828 return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, 0);
831 GByteArray* g_byte_array_sized_new (guint reserved_size)
833 return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, reserved_size);
836 guint8* g_byte_array_free (GByteArray *array,
837 gboolean free_segment)
839 return (guint8*) g_array_free ((GArray*) array, free_segment);
844 * @array: A #GByteArray.
846 * Atomically increments the reference count of @array by one. This
847 * function is MT-safe and may be called from any thread.
849 * Returns: The passed in #GByteArray.
854 g_byte_array_ref (GByteArray *array)
856 return (GByteArray *) g_array_ref ((GArray *) array);
860 * g_byte_array_unref:
861 * @array: A #GByteArray.
863 * Atomically decrements the reference count of @array by one. If the
864 * reference count drops to 0, all memory allocated by the array is
865 * released. This function is MT-safe and may be called from any
871 g_byte_array_unref (GByteArray *array)
873 g_array_unref ((GArray *) array);
876 GByteArray* g_byte_array_append (GByteArray *array,
880 g_array_append_vals ((GArray*) array, (guint8*)data, len);
885 GByteArray* g_byte_array_prepend (GByteArray *array,
889 g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
894 GByteArray* g_byte_array_set_size (GByteArray *array,
897 g_array_set_size ((GArray*) array, length);
902 GByteArray* g_byte_array_remove_index (GByteArray *array,
905 g_array_remove_index ((GArray*) array, index_);
910 GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
913 g_array_remove_index_fast ((GArray*) array, index_);
919 g_byte_array_remove_range (GByteArray *array,
923 g_return_val_if_fail (array, NULL);
924 g_return_val_if_fail (index_ < array->len, NULL);
925 g_return_val_if_fail (index_ + length <= array->len, NULL);
927 return (GByteArray *)g_array_remove_range ((GArray*) array, index_, length);
931 g_byte_array_sort (GByteArray *array,
932 GCompareFunc compare_func)
934 g_array_sort ((GArray *) array, compare_func);
938 g_byte_array_sort_with_data (GByteArray *array,
939 GCompareDataFunc compare_func,
942 g_array_sort_with_data ((GArray *) array, compare_func, user_data);
945 #define __G_ARRAY_C__
946 #include "galiasdef.c"