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/.
35 #define MIN_ARRAY_SIZE 16
37 typedef struct _GRealArray GRealArray
;
45 guint zero_terminated
: 1;
49 #define g_array_elt_len(array,i) ((array)->elt_size * (i))
50 #define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
51 #define g_array_elt_zero(array, pos, len) \
52 (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
53 #define g_array_zero_terminate(array) G_STMT_START{ \
54 if ((array)->zero_terminated) \
55 g_array_elt_zero ((array), (array)->len, 1); \
58 static gint
g_nearest_pow (gint num
);
59 static void g_array_maybe_expand (GRealArray
*array
,
62 static GMemChunk
*array_mem_chunk
= NULL
;
63 G_LOCK_DEFINE_STATIC (array_mem_chunk
);
66 g_array_new (gboolean zero_terminated
,
70 return (GArray
*) g_array_sized_new (zero_terminated
, clear
, elt_size
, 0);
73 GArray
* g_array_sized_new (gboolean zero_terminated
,
80 G_LOCK (array_mem_chunk
);
82 array_mem_chunk
= g_mem_chunk_new ("array mem chunk",
84 1024, G_ALLOC_AND_FREE
);
86 array
= g_chunk_new (GRealArray
, array_mem_chunk
);
87 G_UNLOCK (array_mem_chunk
);
92 array
->zero_terminated
= (zero_terminated
? 1 : 0);
93 array
->clear
= (clear
? 1 : 0);
94 array
->elt_size
= elt_size
;
96 if (array
->zero_terminated
|| reserved_size
!= 0)
98 g_array_maybe_expand (array
, reserved_size
);
99 g_array_zero_terminate(array
);
102 return (GArray
*) array
;
106 g_array_free (GArray
*array
,
107 gboolean free_segment
)
111 g_return_val_if_fail (array
, NULL
);
115 g_free (array
->data
);
119 segment
= array
->data
;
121 G_LOCK (array_mem_chunk
);
122 g_mem_chunk_free (array_mem_chunk
, array
);
123 G_UNLOCK (array_mem_chunk
);
129 g_array_append_vals (GArray
*farray
,
133 GRealArray
*array
= (GRealArray
*) farray
;
135 g_array_maybe_expand (array
, len
);
137 memcpy (g_array_elt_pos (array
, array
->len
), data
,
138 g_array_elt_len (array
, len
));
142 g_array_zero_terminate (array
);
148 g_array_prepend_vals (GArray
*farray
,
152 GRealArray
*array
= (GRealArray
*) farray
;
154 g_array_maybe_expand (array
, len
);
156 g_memmove (g_array_elt_pos (array
, len
), g_array_elt_pos (array
, 0),
157 g_array_elt_len (array
, array
->len
));
159 memcpy (g_array_elt_pos (array
, 0), data
, g_array_elt_len (array
, len
));
163 g_array_zero_terminate (array
);
169 g_array_insert_vals (GArray
*farray
,
174 GRealArray
*array
= (GRealArray
*) farray
;
176 g_array_maybe_expand (array
, len
);
178 g_memmove (g_array_elt_pos (array
, len
+ index
),
179 g_array_elt_pos (array
, index
),
180 g_array_elt_len (array
, array
->len
- index
));
182 memcpy (g_array_elt_pos (array
, index
), data
, g_array_elt_len (array
, len
));
186 g_array_zero_terminate (array
);
192 g_array_set_size (GArray
*farray
,
195 GRealArray
*array
= (GRealArray
*) farray
;
196 if (length
> array
->len
)
198 g_array_maybe_expand (array
, length
- array
->len
);
201 g_array_elt_zero (array
, array
->len
, length
- array
->len
);
203 #ifdef ENABLE_GC_FRIENDLY
204 else if (length
< array
->len
)
205 g_array_elt_zero (array
, length
, array
->len
- length
);
206 #endif /* ENABLE_GC_FRIENDLY */
210 g_array_zero_terminate (array
);
216 g_array_remove_index (GArray
* farray
,
219 GRealArray
* array
= (GRealArray
*) farray
;
221 g_return_val_if_fail (array
, NULL
);
223 g_return_val_if_fail (index
< array
->len
, NULL
);
225 if (index
!= array
->len
- 1)
226 g_memmove (g_array_elt_pos (array
, index
),
227 g_array_elt_pos (array
, index
+ 1),
228 g_array_elt_len (array
, array
->len
- index
- 1));
232 #ifdef ENABLE_GC_FRIENDLY
233 g_array_elt_zero (array
, array
->len
, 1);
234 #else /* !ENABLE_GC_FRIENDLY */
235 g_array_zero_terminate (array
);
236 #endif /* ENABLE_GC_FRIENDLY */
242 g_array_remove_index_fast (GArray
* farray
,
245 GRealArray
* array
= (GRealArray
*) farray
;
247 g_return_val_if_fail (array
, NULL
);
249 g_return_val_if_fail (index
< array
->len
, NULL
);
251 if (index
!= array
->len
- 1)
252 g_memmove (g_array_elt_pos (array
, index
),
253 g_array_elt_pos (array
, array
->len
- 1),
254 g_array_elt_len (array
, 1));
258 #ifdef ENABLE_GC_FRIENDLY
259 g_array_elt_zero (array
, array
->len
, 1);
260 #else /* !ENABLE_GC_FRIENDLY */
261 g_array_zero_terminate (array
);
262 #endif /* ENABLE_GC_FRIENDLY */
268 g_nearest_pow (gint num
)
279 g_array_maybe_expand (GRealArray
*array
,
282 guint want_alloc
= g_array_elt_len (array
, array
->len
+ len
+
283 array
->zero_terminated
);
285 if (want_alloc
> array
->alloc
)
287 want_alloc
= g_nearest_pow (want_alloc
);
288 want_alloc
= MAX (want_alloc
, MIN_ARRAY_SIZE
);
290 array
->data
= g_realloc (array
->data
, want_alloc
);
292 #ifdef ENABLE_GC_FRIENDLY
293 memset (array
->data
+ array
->alloc
, 0, want_alloc
- array
->alloc
);
294 #endif /* ENABLE_GC_FRIENDLY */
296 array
->alloc
= want_alloc
;
303 typedef struct _GRealPtrArray GRealPtrArray
;
305 struct _GRealPtrArray
312 static void g_ptr_array_maybe_expand (GRealPtrArray
*array
,
315 static GMemChunk
*ptr_array_mem_chunk
= NULL
;
316 G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk
);
320 g_ptr_array_new (void)
322 return g_ptr_array_sized_new (0);
326 g_ptr_array_sized_new (guint reserved_size
)
328 GRealPtrArray
*array
;
330 G_LOCK (ptr_array_mem_chunk
);
331 if (!ptr_array_mem_chunk
)
332 ptr_array_mem_chunk
= g_mem_chunk_new ("array mem chunk",
333 sizeof (GRealPtrArray
),
334 1024, G_ALLOC_AND_FREE
);
336 array
= g_chunk_new (GRealPtrArray
, ptr_array_mem_chunk
);
337 G_UNLOCK (ptr_array_mem_chunk
);
343 if (reserved_size
!= 0)
344 g_ptr_array_maybe_expand (array
, reserved_size
);
346 return (GPtrArray
*) array
;
350 g_ptr_array_free (GPtrArray
*array
,
351 gboolean free_segment
)
355 g_return_val_if_fail (array
, NULL
);
359 g_free (array
->pdata
);
363 segment
= array
->pdata
;
365 G_LOCK (ptr_array_mem_chunk
);
366 g_mem_chunk_free (ptr_array_mem_chunk
, array
);
367 G_UNLOCK (ptr_array_mem_chunk
);
373 g_ptr_array_maybe_expand (GRealPtrArray
*array
,
376 if ((array
->len
+ len
) > array
->alloc
)
378 #ifdef ENABLE_GC_FRIENDLY
379 guint old_alloc
= array
->alloc
;
380 #endif /* ENABLE_GC_FRIENDLY */
381 array
->alloc
= g_nearest_pow (array
->len
+ len
);
382 array
->alloc
= MAX (array
->alloc
, MIN_ARRAY_SIZE
);
383 array
->pdata
= g_realloc (array
->pdata
, sizeof(gpointer
) * array
->alloc
);
384 #ifdef ENABLE_GC_FRIENDLY
385 for ( ; old_alloc
< array
->alloc
; old_alloc
++)
386 array
->pdata
[old_alloc
] = NULL
;
387 #endif /* ENABLE_GC_FRIENDLY */
392 g_ptr_array_set_size (GPtrArray
*farray
,
395 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
397 g_return_if_fail (array
);
399 if (length
> array
->len
)
402 g_ptr_array_maybe_expand (array
, (length
- array
->len
));
404 * memset (array->pdata + array->len, 0,
405 * sizeof (gpointer) * (length - array->len));
406 * to make it really portable. Remember (void*)NULL needn't be
407 * bitwise zero. It of course is silly not to use memset (..,0,..).
409 for (i
= array
->len
; i
< length
; i
++)
410 array
->pdata
[i
] = NULL
;
412 #ifdef ENABLE_GC_FRIENDLY
413 else if (length
< array
->len
)
416 for (i
= length
; i
< array
->len
; i
++)
417 array
->pdata
[i
] = NULL
;
419 #endif /* ENABLE_GC_FRIENDLY */
425 g_ptr_array_remove_index (GPtrArray
* farray
,
428 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
431 g_return_val_if_fail (array
, NULL
);
433 g_return_val_if_fail (index
< array
->len
, NULL
);
435 result
= array
->pdata
[index
];
437 if (index
!= array
->len
- 1)
438 g_memmove (array
->pdata
+ index
, array
->pdata
+ index
+ 1,
439 sizeof (gpointer
) * (array
->len
- index
- 1));
443 #ifdef ENABLE_GC_FRIENDLY
444 array
->pdata
[array
->len
] = NULL
;
445 #endif /* ENABLE_GC_FRIENDLY */
451 g_ptr_array_remove_index_fast (GPtrArray
* farray
,
454 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
457 g_return_val_if_fail (array
, NULL
);
459 g_return_val_if_fail (index
< array
->len
, NULL
);
461 result
= array
->pdata
[index
];
463 if (index
!= array
->len
- 1)
464 array
->pdata
[index
] = array
->pdata
[array
->len
- 1];
468 #ifdef ENABLE_GC_FRIENDLY
469 array
->pdata
[array
->len
] = NULL
;
470 #endif /* ENABLE_GC_FRIENDLY */
476 g_ptr_array_remove (GPtrArray
* farray
,
479 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
482 g_return_val_if_fail (array
, FALSE
);
484 for (i
= 0; i
< array
->len
; i
+= 1)
486 if (array
->pdata
[i
] == data
)
488 g_ptr_array_remove_index (farray
, i
);
497 g_ptr_array_remove_fast (GPtrArray
* farray
,
500 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
503 g_return_val_if_fail (array
, FALSE
);
505 for (i
= 0; i
< array
->len
; i
+= 1)
507 if (array
->pdata
[i
] == data
)
509 g_ptr_array_remove_index_fast (farray
, i
);
518 g_ptr_array_add (GPtrArray
* farray
,
521 GRealPtrArray
* array
= (GRealPtrArray
*) farray
;
523 g_return_if_fail (array
);
525 g_ptr_array_maybe_expand (array
, 1);
527 array
->pdata
[array
->len
++] = data
;
533 GByteArray
* g_byte_array_new (void)
535 return (GByteArray
*) g_array_sized_new (FALSE
, FALSE
, 1, 0);
538 GByteArray
* g_byte_array_sized_new (guint reserved_size
)
540 return (GByteArray
*) g_array_sized_new (FALSE
, FALSE
, 1, reserved_size
);
543 guint8
* g_byte_array_free (GByteArray
*array
,
544 gboolean free_segment
)
546 return (guint8
*) g_array_free ((GArray
*) array
, free_segment
);
549 GByteArray
* g_byte_array_append (GByteArray
*array
,
553 g_array_append_vals ((GArray
*) array
, (guint8
*)data
, len
);
558 GByteArray
* g_byte_array_prepend (GByteArray
*array
,
562 g_array_prepend_vals ((GArray
*) array
, (guint8
*)data
, len
);
567 GByteArray
* g_byte_array_set_size (GByteArray
*array
,
570 g_array_set_size ((GArray
*) array
, length
);
575 GByteArray
* g_byte_array_remove_index (GByteArray
*array
,
578 g_array_remove_index((GArray
*) array
, index
);
583 GByteArray
* g_byte_array_remove_index_fast (GByteArray
*array
,
586 g_array_remove_index_fast((GArray
*) array
, index
);