* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/*
+ * MT safe
+ */
+
#include <string.h>
#include "glib.h"
#define MIN_ARRAY_SIZE 16
-
typedef struct _GRealArray GRealArray;
struct _GRealArray
guint8 *data;
guint len;
guint alloc;
- guint zero_terminated;
+ guint elt_size;
+ guint zero_terminated : 1;
+ guint clear : 1;
};
+#define g_array_elt_len(array,i) ((array)->elt_size * (i))
+#define g_array_elt_pos(array,i) ((array)->data + g_array_elt_len((array),(i)))
+#define g_array_elt_zero(array, pos, len) \
+ (memset (g_array_elt_pos ((array), pos), 0, g_array_elt_len ((array), len)))
+#define g_array_zero_terminate(array) G_STMT_START{ \
+ if ((array)->zero_terminated) \
+ g_array_elt_zero ((array), (array)->len, 1); \
+}G_STMT_END
static gint g_nearest_pow (gint num);
static void g_array_maybe_expand (GRealArray *array,
gint len);
-
static GMemChunk *array_mem_chunk = NULL;
-
+G_LOCK_DEFINE_STATIC (array_mem_chunk);
GArray*
-g_array_new (gboolean zero_terminated)
+g_array_new (gboolean zero_terminated,
+ gboolean clear,
+ guint elt_size)
+{
+ return (GArray*) g_array_sized_new (zero_terminated, clear, elt_size, 0);
+}
+
+GArray* g_array_sized_new (gboolean zero_terminated,
+ gboolean clear,
+ guint elt_size,
+ guint reserved_size)
{
GRealArray *array;
+ G_LOCK (array_mem_chunk);
if (!array_mem_chunk)
array_mem_chunk = g_mem_chunk_new ("array mem chunk",
sizeof (GRealArray),
1024, G_ALLOC_AND_FREE);
array = g_chunk_new (GRealArray, array_mem_chunk);
+ G_UNLOCK (array_mem_chunk);
- array->data = NULL;
- array->len = 0;
- array->alloc = 0;
+ array->data = NULL;
+ array->len = 0;
+ array->alloc = 0;
array->zero_terminated = (zero_terminated ? 1 : 0);
+ array->clear = (clear ? 1 : 0);
+ array->elt_size = elt_size;
+
+ if (array->zero_terminated || reserved_size != 0)
+ {
+ g_array_maybe_expand (array, reserved_size);
+ g_array_zero_terminate(array);
+ }
return (GArray*) array;
}
if (free_segment)
g_free (array->data);
+ G_LOCK (array_mem_chunk);
g_mem_chunk_free (array_mem_chunk, array);
+ G_UNLOCK (array_mem_chunk);
}
GArray*
-g_rarray_append (GArray *array,
- gpointer data,
- gint size)
+g_array_append_vals (GArray *farray,
+ gconstpointer data,
+ guint len)
{
- g_array_maybe_expand ((GRealArray*) array, size);
+ GRealArray *array = (GRealArray*) farray;
- memcpy (array->data + array->len, data, size);
+ g_array_maybe_expand (array, len);
- array->len += size;
+ memcpy (g_array_elt_pos (array, array->len), data,
+ g_array_elt_len (array, len));
- return array;
+ array->len += len;
+
+ g_array_zero_terminate (array);
+
+ return farray;
}
GArray*
-g_rarray_prepend (GArray *array,
- gpointer data,
- gint size)
+g_array_prepend_vals (GArray *farray,
+ gconstpointer data,
+ guint len)
{
- g_array_maybe_expand ((GRealArray*) array, size);
+ GRealArray *array = (GRealArray*) farray;
- g_memmove (array->data + size, array->data, array->len);
- memcpy (array->data, data, size);
+ g_array_maybe_expand (array, len);
- array->len += size;
+ g_memmove (g_array_elt_pos (array, len), g_array_elt_pos (array, 0),
+ g_array_elt_len (array, array->len));
- return array;
+ memcpy (g_array_elt_pos (array, 0), data, g_array_elt_len (array, len));
+
+ array->len += len;
+
+ g_array_zero_terminate (array);
+
+ return farray;
}
GArray*
-g_rarray_truncate (GArray *array,
- gint length,
- gint size)
+g_array_insert_vals (GArray *farray,
+ guint index,
+ gconstpointer data,
+ guint len)
{
- if (array->data)
- memset (array->data + length * size, 0, size);
- array->len = length * size;
- return array;
+ GRealArray *array = (GRealArray*) farray;
+
+ g_array_maybe_expand (array, len);
+
+ g_memmove (g_array_elt_pos (array, len + index),
+ g_array_elt_pos (array, index),
+ g_array_elt_len (array, array->len - index));
+
+ memcpy (g_array_elt_pos (array, index), data, g_array_elt_len (array, len));
+
+ array->len += len;
+
+ g_array_zero_terminate (array);
+
+ return farray;
}
+GArray*
+g_array_set_size (GArray *farray,
+ guint length)
+{
+ GRealArray *array = (GRealArray*) farray;
+ if (length > array->len)
+ {
+ g_array_maybe_expand (array, length - array->len);
+
+ if (array->clear)
+ g_array_elt_zero (array, array->len, length - array->len);
+ }
+#ifdef ENABLE_GC_FRIENDLY
+ else if (length < array->len)
+ g_array_elt_zero (array, length, array->len - length);
+#endif /* ENABLE_GC_FRIENDLY */
+
+ array->len = length;
+
+ g_array_zero_terminate (array);
+
+ return farray;
+}
+
+GArray*
+g_array_remove_index (GArray* farray,
+ guint index)
+{
+ GRealArray* array = (GRealArray*) farray;
+
+ g_return_val_if_fail (array, NULL);
+
+ g_return_val_if_fail (index < array->len, NULL);
+
+ if (index != array->len - 1)
+ g_memmove (g_array_elt_pos (array, index),
+ g_array_elt_pos (array, index + 1),
+ g_array_elt_len (array, array->len - index - 1));
+
+ array->len -= 1;
+
+#ifdef ENABLE_GC_FRIENDLY
+ g_array_elt_zero (array, array->len, 1);
+#else /* !ENABLE_GC_FRIENDLY */
+ g_array_zero_terminate (array);
+#endif /* ENABLE_GC_FRIENDLY */
+
+ return farray;
+}
+
+GArray*
+g_array_remove_index_fast (GArray* farray,
+ guint index)
+{
+ GRealArray* array = (GRealArray*) farray;
+
+ g_return_val_if_fail (array, NULL);
+
+ g_return_val_if_fail (index < array->len, NULL);
+
+ if (index != array->len - 1)
+ g_memmove (g_array_elt_pos (array, index),
+ g_array_elt_pos (array, array->len - 1),
+ g_array_elt_len (array, 1));
+
+ array->len -= 1;
+
+#ifdef ENABLE_GC_FRIENDLY
+ g_array_elt_zero (array, array->len, 1);
+#else /* !ENABLE_GC_FRIENDLY */
+ g_array_zero_terminate (array);
+#endif /* ENABLE_GC_FRIENDLY */
+
+ return farray;
+}
static gint
g_nearest_pow (gint num)
g_array_maybe_expand (GRealArray *array,
gint len)
{
- guint old_alloc;
+ guint want_alloc = g_array_elt_len (array, array->len + len +
+ array->zero_terminated);
- if ((array->len + len) > array->alloc)
+ if (want_alloc > array->alloc)
{
- old_alloc = array->alloc;
+ want_alloc = g_nearest_pow (want_alloc);
+ want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
- array->alloc = g_nearest_pow (array->len + array->zero_terminated + len);
- array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
- array->data = g_realloc (array->data, array->alloc);
+ array->data = g_realloc (array->data, want_alloc);
- memset (array->data + old_alloc, 0, array->alloc - old_alloc);
+#ifdef ENABLE_GC_FRIENDLY
+ memset (array->data + array->alloc, 0, want_alloc - array->alloc);
+#endif /* ENABLE_GC_FRIENDLY */
+
+ array->alloc = want_alloc;
}
}
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len);
-
static GMemChunk *ptr_array_mem_chunk = NULL;
-
+G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
GPtrArray*
-g_ptr_array_new ()
+g_ptr_array_new (void)
+{
+ return g_ptr_array_sized_new (0);
+}
+
+GPtrArray*
+g_ptr_array_sized_new (guint reserved_size)
{
GRealPtrArray *array;
+ G_LOCK (ptr_array_mem_chunk);
if (!ptr_array_mem_chunk)
ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
sizeof (GRealPtrArray),
1024, G_ALLOC_AND_FREE);
array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
+ G_UNLOCK (ptr_array_mem_chunk);
array->pdata = NULL;
array->len = 0;
array->alloc = 0;
- return (GPtrArray*) array;
+ if (reserved_size != 0)
+ g_ptr_array_maybe_expand (array, reserved_size);
+
+ return (GPtrArray*) array;
}
void
if (free_segment)
g_free (array->pdata);
+ G_LOCK (ptr_array_mem_chunk);
g_mem_chunk_free (ptr_array_mem_chunk, array);
+ G_UNLOCK (ptr_array_mem_chunk);
}
static void
g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len)
{
- guint old_alloc;
-
if ((array->len + len) > array->alloc)
{
- old_alloc = array->alloc;
-
+#ifdef ENABLE_GC_FRIENDLY
+ guint old_alloc = array->alloc;
+#endif /* ENABLE_GC_FRIENDLY */
array->alloc = g_nearest_pow (array->len + len);
array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
- if (array->pdata)
- array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
- else
- array->pdata = g_new0 (gpointer, array->alloc);
-
- memset (array->pdata + old_alloc, 0, array->alloc - old_alloc);
+ array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc);
+#ifdef ENABLE_GC_FRIENDLY
+ for ( ; old_alloc < array->alloc; old_alloc++)
+ array->pdata [old_alloc] = NULL;
+#endif /* ENABLE_GC_FRIENDLY */
}
}
g_return_if_fail (array);
if (length > array->len)
- g_ptr_array_maybe_expand (array, (length - array->len));
+ {
+ int i;
+ g_ptr_array_maybe_expand (array, (length - array->len));
+ /* This is not
+ * memset (array->pdata + array->len, 0,
+ * sizeof (gpointer) * (length - array->len));
+ * to make it really portable. Remember (void*)NULL needn't be
+ * bitwise zero. It of course is silly not to use memset (..,0,..).
+ */
+ for (i = array->len; i < length; i++)
+ array->pdata[i] = NULL;
+ }
+#ifdef ENABLE_GC_FRIENDLY
+ else if (length < array->len)
+ {
+ int i;
+ for (i = length; i < array->len; i++)
+ array->pdata[i] = NULL;
+ }
+#endif /* ENABLE_GC_FRIENDLY */
array->len = length;
}
-void
+gpointer
g_ptr_array_remove_index (GPtrArray* farray,
- gint index)
+ guint index)
{
GRealPtrArray* array = (GRealPtrArray*) farray;
+ gpointer result;
- g_return_if_fail (array);
+ g_return_val_if_fail (array, NULL);
+
+ g_return_val_if_fail (index < array->len, NULL);
+
+ result = array->pdata[index];
+
+ if (index != array->len - 1)
+ g_memmove (array->pdata + index, array->pdata + index + 1,
+ sizeof (gpointer) * (array->len - index - 1));
+
+ array->len -= 1;
+
+#ifdef ENABLE_GC_FRIENDLY
+ array->pdata[array->len] = NULL;
+#endif /* ENABLE_GC_FRIENDLY */
+
+ return result;
+}
- g_return_if_fail (index < array->len);
+gpointer
+g_ptr_array_remove_index_fast (GPtrArray* farray,
+ guint index)
+{
+ GRealPtrArray* array = (GRealPtrArray*) farray;
+ gpointer result;
- array->pdata[index] = array->pdata[array->len - 1];
+ g_return_val_if_fail (array, NULL);
- array->pdata[array->len - 1] = NULL;
+ g_return_val_if_fail (index < array->len, NULL);
+
+ result = array->pdata[index];
+
+ if (index != array->len - 1)
+ array->pdata[index] = array->pdata[array->len - 1];
array->len -= 1;
+
+#ifdef ENABLE_GC_FRIENDLY
+ array->pdata[array->len] = NULL;
+#endif /* ENABLE_GC_FRIENDLY */
+
+ return result;
}
gboolean
return FALSE;
}
+gboolean
+g_ptr_array_remove_fast (GPtrArray* farray,
+ gpointer data)
+{
+ GRealPtrArray* array = (GRealPtrArray*) farray;
+ int i;
+
+ g_return_val_if_fail (array, FALSE);
+
+ for (i = 0; i < array->len; i += 1)
+ {
+ if (array->pdata[i] == data)
+ {
+ g_ptr_array_remove_index_fast (farray, i);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
void
g_ptr_array_add (GPtrArray* farray,
gpointer data)
array->pdata[array->len++] = data;
}
-/* Byte arrays
+/* Byte arrays
*/
GByteArray* g_byte_array_new (void)
{
- return (GByteArray*) g_array_new (FALSE);
+ return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, 0);
+}
+
+GByteArray* g_byte_array_sized_new (guint reserved_size)
+{
+ return (GByteArray*) g_array_sized_new (FALSE, FALSE, 1, reserved_size);
}
void g_byte_array_free (GByteArray *array,
- gint free_segment)
+ gboolean free_segment)
{
g_array_free ((GArray*) array, free_segment);
}
const guint8 *data,
guint len)
{
- g_rarray_append ((GArray*) array, (guint8*)data, len);
+ g_array_append_vals ((GArray*) array, (guint8*)data, len);
return array;
}
const guint8 *data,
guint len)
{
- g_rarray_prepend ((GArray*) array, (guint8*)data, len);
+ g_array_prepend_vals ((GArray*) array, (guint8*)data, len);
+
+ return array;
+}
+
+GByteArray* g_byte_array_set_size (GByteArray *array,
+ guint length)
+{
+ g_array_set_size ((GArray*) array, length);
+
+ return array;
+}
+
+GByteArray* g_byte_array_remove_index (GByteArray *array,
+ guint index)
+{
+ g_array_remove_index((GArray*) array, index);
return array;
}
-GByteArray* g_byte_array_truncate (GByteArray *array,
- gint length)
+GByteArray* g_byte_array_remove_index_fast (GByteArray *array,
+ guint index)
{
- g_rarray_truncate ((GArray*) array, length, 1);
+ g_array_remove_index_fast((GArray*) array, index);
return array;
}