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/.
38 #define MIN_ARRAY_SIZE 16
40 typedef struct _GRealArray GRealArray;
48 guint zero_terminated : 1;
52 #define g_array_elt_len(array,i) ((array)->elt_size * (i))
53 #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
54 #define g_array_elt_zero(array, pos, len) \
55 (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
56 #define g_array_zero_terminate(array) G_STMT_START{ \
57 if ((array)->zero_terminated) \
58 g_array_elt_zero ((array), (array)->len, 1); \
61 static gint g_nearest_pow (gint num) G_GNUC_CONST;
62 static void g_array_maybe_expand (GRealArray *array,
65 static GMemChunk *array_mem_chunk = NULL;
66 G_LOCK_DEFINE_STATIC (array_mem_chunk);
69 g_array_new (gboolean zero_terminated,
73 return (GArray*) g_array_sized_new (zero_terminated, clear, elt_size, 0);
76 GArray* g_array_sized_new (gboolean zero_terminated,
83 G_LOCK (array_mem_chunk);
85 array_mem_chunk = g_mem_chunk_new ("array mem chunk",
87 1024, G_ALLOC_AND_FREE);
89 array = g_chunk_new (GRealArray, array_mem_chunk);
90 G_UNLOCK (array_mem_chunk);
95 array->zero_terminated = (zero_terminated ? 1 : 0);
96 array->clear = (clear ? 1 : 0);
97 array->elt_size = elt_size;
99 if (array->zero_terminated || reserved_size != 0)
101 g_array_maybe_expand (array, reserved_size);
102 g_array_zero_terminate(array);
105 return (GArray*) array;
109 g_array_free (GArray *array,
110 gboolean free_segment)
114 g_return_val_if_fail (array, NULL);
118 g_free (array->data);
122 segment = array->data;
124 G_LOCK (array_mem_chunk);
125 g_mem_chunk_free (array_mem_chunk, array);
126 G_UNLOCK (array_mem_chunk);
132 g_array_append_vals (GArray *farray,
136 GRealArray *array = (GRealArray*) farray;
138 g_array_maybe_expand (array, len);
140 memcpy (g_array_elt_pos (array, array->len), data,
141 g_array_elt_len (array, len));
145 g_array_zero_terminate (array);
151 g_array_prepend_vals (GArray *farray,
155 GRealArray *array = (GRealArray*) farray;
157 g_array_maybe_expand (array, len);
159 g_memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0),
160 g_array_elt_len (array, array->len));
162 memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
166 g_array_zero_terminate (array);
172 g_array_insert_vals (GArray *farray,
177 GRealArray *array = (GRealArray*) farray;
179 g_array_maybe_expand (array, len);
181 g_memmove (g_array_elt_pos (array, len + index),
182 g_array_elt_pos (array, index),
183 g_array_elt_len (array, array->len - index));
185 memcpy (g_array_elt_pos (array, index), data, g_array_elt_len (array, len));
189 g_array_zero_terminate (array);
195 g_array_set_size (GArray *farray,
198 GRealArray *array = (GRealArray*) farray;
199 if (length > array->len)
201 g_array_maybe_expand (array, length - array->len);
204 g_array_elt_zero (array, array->len, length - array->len);
206 #ifdef ENABLE_GC_FRIENDLY
207 else if (length < array->len)
208 g_array_elt_zero (array, length, array->len - length);
209 #endif /* ENABLE_GC_FRIENDLY */
213 g_array_zero_terminate (array);
219 g_array_remove_index (GArray* farray,
222 GRealArray* array = (GRealArray*) farray;
224 g_return_val_if_fail (array, NULL);
226 g_return_val_if_fail (index < array->len, NULL);
228 if (index != array->len - 1)
229 g_memmove (g_array_elt_pos (array, index),
230 g_array_elt_pos (array, index + 1),
231 g_array_elt_len (array, array->len - index - 1));
235 #ifdef ENABLE_GC_FRIENDLY
236 g_array_elt_zero (array, array->len, 1);
237 #else /* !ENABLE_GC_FRIENDLY */
238 g_array_zero_terminate (array);
239 #endif /* ENABLE_GC_FRIENDLY */
245 g_array_remove_index_fast (GArray* farray,
248 GRealArray* array = (GRealArray*) farray;
250 g_return_val_if_fail (array, NULL);
252 g_return_val_if_fail (index < array->len, NULL);
254 if (index != array->len - 1)
255 memcpy (g_array_elt_pos (array, index),
256 g_array_elt_pos (array, array->len - 1),
257 g_array_elt_len (array, 1));
261 #ifdef ENABLE_GC_FRIENDLY
262 g_array_elt_zero (array, array->len, 1);
263 #else /* !ENABLE_GC_FRIENDLY */
264 g_array_zero_terminate (array);
265 #endif /* ENABLE_GC_FRIENDLY */
271 g_array_remove_range (GArray *farray,
275 GRealArray *array = (GRealArray*) farray;
277 g_return_val_if_fail (array, NULL);
278 g_return_val_if_fail (index_ < array->len, NULL);
279 g_return_val_if_fail (index_ + length <= array->len, NULL);
281 if (index_ + length != array->len)
282 g_memmove (g_array_elt_pos (array, index_),
283 g_array_elt_pos (array, index_ + length),
284 (array->len - (index_ + length)) * array->elt_size);
286 array->len -= length;
287 #ifdef ENABLE_GC_FRIENDLY
288 g_array_elt_zero (array, array->len, length);
289 #else /* !ENABLE_GC_FRIENDLY */
290 g_array_zero_terminate (array);
291 #endif /* ENABLE_GC_FRIENDLY */
297 g_array_sort (GArray *farray,
298 GCompareFunc compare_func)
300 GRealArray *array = (GRealArray*) farray;
302 g_return_if_fail (array != NULL);
311 g_array_sort_with_data (GArray *farray,
312 GCompareDataFunc compare_func,
315 GRealArray *array = (GRealArray*) farray;
317 g_return_if_fail (array != NULL);
319 g_qsort_with_data (array->data,
328 g_nearest_pow (gint num)
339 g_array_maybe_expand (GRealArray *array,
342 guint want_alloc = g_array_elt_len (array, array->len + len +
343 array->zero_terminated);
345 if (want_alloc > array->alloc)
347 want_alloc = g_nearest_pow (want_alloc);
348 want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
350 array->data = g_realloc (array->data, want_alloc);
352 #ifdef ENABLE_GC_FRIENDLY
353 memset (array->data + array->alloc, 0, want_alloc - array->alloc);
354 #endif /* ENABLE_GC_FRIENDLY */
356 array->alloc = want_alloc;
363 typedef struct _GRealPtrArray GRealPtrArray;
365 struct _GRealPtrArray
372 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
375 static GMemChunk *ptr_array_mem_chunk = NULL;
376 G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
380 g_ptr_array_new (void)
382 return g_ptr_array_sized_new (0);
386 g_ptr_array_sized_new (guint reserved_size)
388 GRealPtrArray *array;
390 G_LOCK (ptr_array_mem_chunk);
391 if (!ptr_array_mem_chunk)
392 ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
393 sizeof (GRealPtrArray),
394 1024, G_ALLOC_AND_FREE);
396 array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
397 G_UNLOCK (ptr_array_mem_chunk);
403 if (reserved_size != 0)
404 g_ptr_array_maybe_expand (array, reserved_size);
406 return (GPtrArray*) array;
410 g_ptr_array_free (GPtrArray *array,
411 gboolean free_segment)
415 g_return_val_if_fail (array, NULL);
419 g_free (array->pdata);
423 segment = array->pdata;
425 G_LOCK (ptr_array_mem_chunk);
426 g_mem_chunk_free (ptr_array_mem_chunk, array);
427 G_UNLOCK (ptr_array_mem_chunk);
433 g_ptr_array_maybe_expand (GRealPtrArray *array,
436 if ((array->len + len) > array->alloc)
438 #ifdef ENABLE_GC_FRIENDLY
439 guint old_alloc = array->alloc;
440 #endif /* ENABLE_GC_FRIENDLY */
441 array->alloc = g_nearest_pow (array->len + len);
442 array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
443 array->pdata = g_realloc (array->pdata, sizeof (gpointer) * array->alloc);
444 #ifdef ENABLE_GC_FRIENDLY
445 for ( ; old_alloc < array->alloc; old_alloc++)
446 array->pdata [old_alloc] = NULL;
447 #endif /* ENABLE_GC_FRIENDLY */
452 g_ptr_array_set_size (GPtrArray *farray,
455 GRealPtrArray* array = (GRealPtrArray*) farray;
457 g_return_if_fail (array);
459 if (length > array->len)
462 g_ptr_array_maybe_expand (array, (length - array->len));
464 * memset (array->pdata + array->len, 0,
465 * sizeof (gpointer) * (length - array->len));
466 * to make it really portable. Remember (void*)NULL needn't be
467 * bitwise zero. It of course is silly not to use memset (..,0,..).
469 for (i = array->len; i < length; i++)
470 array->pdata[i] = NULL;
472 #ifdef ENABLE_GC_FRIENDLY
473 else if (length < array->len)
476 for (i = length; i < array->len; i++)
477 array->pdata[i] = NULL;
479 #endif /* ENABLE_GC_FRIENDLY */
485 g_ptr_array_remove_index (GPtrArray* farray,
488 GRealPtrArray* array = (GRealPtrArray*) farray;
491 g_return_val_if_fail (array, NULL);
493 g_return_val_if_fail (index < array->len, NULL);
495 result = array->pdata[index];
497 if (index != array->len - 1)
498 g_memmove (array->pdata + index, array->pdata + index + 1,
499 sizeof (gpointer) * (array->len - index - 1));
503 #ifdef ENABLE_GC_FRIENDLY
504 array->pdata[array->len] = NULL;
505 #endif /* ENABLE_GC_FRIENDLY */
511 g_ptr_array_remove_index_fast (GPtrArray* farray,
514 GRealPtrArray* array = (GRealPtrArray*) farray;
517 g_return_val_if_fail (array, NULL);
519 g_return_val_if_fail (index < array->len, NULL);
521 result = array->pdata[index];
523 if (index != array->len - 1)
524 array->pdata[index] = array->pdata[array->len - 1];
528 #ifdef ENABLE_GC_FRIENDLY
529 array->pdata[array->len] = NULL;
530 #endif /* ENABLE_GC_FRIENDLY */
536 g_ptr_array_remove_range (GPtrArray* farray,
540 GRealPtrArray* array = (GRealPtrArray*) farray;
542 g_return_if_fail (array);
543 g_return_if_fail (index_ < array->len);
544 g_return_if_fail (index_ + length <= array->len);
546 if (index_ + length != array->len)
547 g_memmove (&array->pdata[index_],
548 &array->pdata[index_ + length],
549 (array->len - (index_ + length)) * sizeof (gpointer));
551 array->len -= length;
552 #ifdef ENABLE_GC_FRIENDLY
555 for (i = 0; i < length; i++)
556 array->pdata[array->len + i] = NULL;
558 #endif /* ENABLE_GC_FRIENDLY */
562 g_ptr_array_remove (GPtrArray* farray,
565 GRealPtrArray* array = (GRealPtrArray*) farray;
568 g_return_val_if_fail (array, FALSE);
570 for (i = 0; i < array->len; i += 1)
572 if (array->pdata[i] == data)
574 g_ptr_array_remove_index (farray, i);
583 g_ptr_array_remove_fast (GPtrArray* farray,
586 GRealPtrArray* array = (GRealPtrArray*) farray;
589 g_return_val_if_fail (array, FALSE);
591 for (i = 0; i < array->len; i += 1)
593 if (array->pdata[i] == data)
595 g_ptr_array_remove_index_fast (farray, i);
604 g_ptr_array_add (GPtrArray* farray,
607 GRealPtrArray* array = (GRealPtrArray*) farray;
609 g_return_if_fail (array);
611 g_ptr_array_maybe_expand (array, 1);
613 array->pdata[array->len++] = data;
617 g_ptr_array_sort (GPtrArray *array,
618 GCompareFunc compare_func)
620 g_return_if_fail (array != NULL);
629 g_ptr_array_sort_with_data (GPtrArray *array,
630 GCompareDataFunc compare_func,
633 g_return_if_fail (array != NULL);
635 g_qsort_with_data (array->pdata,
643 * g_ptr_array_foreach:
644 * @array: a #GPtrArray
645 * @func: the function to call for each array element
646 * @user_data: user data to pass to the function
648 * Calls a function for each element of a #GPtrArray.
653 g_ptr_array_foreach (GPtrArray *array,
659 g_return_if_fail (array);
661 for (i = 0; i < array->len; i++)
662 (*func) (array->pdata[i], user_data);
668 GByteArray* g_byte_array_new (void)
670 return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, 0);
673 GByteArray* g_byte_array_sized_new (guint reserved_size)
675 return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, reserved_size);
678 guint8* g_byte_array_free (GByteArray *array,
679 gboolean free_segment)
681 return (guint8*) g_array_free ((GArray*) array, free_segment);
684 GByteArray* g_byte_array_append (GByteArray *array,
688 g_array_append_vals ((GArray*) array, (guint8*)data, len);
693 GByteArray* g_byte_array_prepend (GByteArray *array,
697 g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
702 GByteArray* g_byte_array_set_size (GByteArray *array,
705 g_array_set_size ((GArray*) array, length);
710 GByteArray* g_byte_array_remove_index (GByteArray *array,
713 g_array_remove_index((GArray*) array, index);
718 GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
721 g_array_remove_index_fast((GArray*) array, index);
727 g_byte_array_remove_range (GByteArray *array,
731 g_return_val_if_fail (array, NULL);
732 g_return_val_if_fail (index_ < array->len, NULL);
733 g_return_val_if_fail (index_ + length <= array->len, NULL);
735 return (GByteArray *)g_array_remove_range ((GArray*) array, index_, length);
739 g_byte_array_sort (GByteArray *array,
740 GCompareFunc compare_func)
742 g_array_sort ((GArray *) array, compare_func);
746 g_byte_array_sort_with_data (GByteArray *array,
747 GCompareDataFunc compare_func,
750 g_array_sort_with_data ((GArray *) array, compare_func, user_data);