summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2009-10-31 12:12:52 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2009-10-31 12:12:52 +0800
commit015ce5f7fa6b07de7101a70b2893426f248ab5f6 (patch)
tree3cc9745eb41a37c491e8e3d886d4f8cc47c547e0
parent4ff1a3460cce81c21e1a2be245663f1359570c9e (diff)
milkway: steal array implementation from glib
-rw-r--r--milkway/Makefile.am4
-rw-r--r--milkway/mw-array.c343
-rw-r--r--milkway/mw-array.h129
-rw-r--r--milkway/mw-ptr-array.c386
-rw-r--r--milkway/mw-ptr-array.h123
5 files changed, 985 insertions, 0 deletions
diff --git a/milkway/Makefile.am b/milkway/Makefile.am
index d869a23..c98febd 100644
--- a/milkway/Makefile.am
+++ b/milkway/Makefile.am
@@ -22,6 +22,8 @@ milkway_headers = \
mw-object.h \
mw-error.h \
mw-qsort.h \
+ mw-array.h \
+ mw-ptr-array.h \
mw-connection-mgr.h \
mw-list.h \
mw-slist.h \
@@ -57,6 +59,8 @@ libmilkway_la_SOURCES = \
mw-object.c \
mw-error.c \
mw-qsort.c \
+ mw-array.c \
+ mw-ptr-array.c \
mw-connection-mgr.c \
mw-list.c \
mw-slist.c \
diff --git a/milkway/mw-array.c b/milkway/mw-array.c
new file mode 100644
index 0000000..b2bb2ca
--- /dev/null
+++ b/milkway/mw-array.c
@@ -0,0 +1,343 @@
+/* GLIB - Library of useful routines for C programming
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "milkwayint.h"
+#include "milkway/mw-array.h"
+#include "milkway/mw-qsort.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define MIN_ARRAY_SIZE 16
+
+#define mw_array_elt_len(array, i) ((array)->elt_size * (i))
+#define mw_array_elt_pos(array,i) ((array)->data + mw_array_elt_len((array),(i)))
+#define mw_array_elt_zero(array, pos, len) \
+ (memset (mw_array_elt_pos ((array), pos), 0, mw_array_elt_len ((array), len)))
+#define mw_array_zero_terminate(array) \
+ do { \
+ if ((array)->zero_terminated) \
+ mw_array_elt_zero ((array), (array)->len, 1); \
+ } while (0)
+
+static int mw_nearest_pow (int num);
+static void mw_array_maybe_expand (mw_array_t *array,
+ int len);
+
+static mw_array_t*
+mw_array_init (mw_array_t *array,
+ mw_array_type_t *type,
+ mw_bool_t zero_terminated,
+ mw_bool_t clear,
+ mw_uint_t elt_size,
+ mw_uint_t reserved_size)
+{
+ if (!mw_object_init(&array->base, &type->base))
+ return NULL;
+
+ 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)
+ {
+ mw_array_maybe_expand (array, reserved_size);
+ mw_array_zero_terminate(array);
+ }
+
+ return array;
+}
+
+mw_array_t*
+mw_array_new (mw_bool_t zero_terminated,
+ mw_bool_t clear,
+ mw_uint_t elt_size)
+{
+ return mw_array_sized_new (zero_terminated, clear, elt_size, 0);
+}
+
+mw_array_t*
+mw_array_sized_new (mw_bool_t zero_terminated,
+ mw_bool_t clear,
+ mw_uint_t elt_size,
+ mw_uint_t reserved_size)
+{
+ mw_array_t *self = mw_object_alloc(MW_ARRAY_TYPE);
+
+ if (!self)
+ return NULL;
+ if (!mw_array_init(self, MW_ARRAY_TYPE, zero_terminated, clear, elt_size,
+ reserved_size))
+ return NULL;
+ return self;
+}
+
+/**
+ * mw_array_get_element_size:
+ * @array: A #mw_array_t.
+ *
+ * Gets the size of the elements in @array.
+ *
+ * Returns: Size of each element, in bytes.
+ *
+ * Since: 2.22
+ **/
+mw_uint_t
+mw_array_get_element_size (mw_array_t *array)
+{
+ return array->elt_size;
+}
+
+char*
+mw_array_take (mw_array_t *array)
+{
+ char* segment;
+
+ segment = (char*) array->data;
+
+ array->data = NULL;
+ array->len = 0;
+ array->alloc = 0;
+
+ return segment;
+}
+
+mw_array_t*
+mw_array_append_vals (mw_array_t *array,
+ const mw_pointer_t data,
+ mw_uint_t len)
+{
+ mw_array_maybe_expand (array, len);
+
+ memcpy (mw_array_elt_pos (array, array->len), data,
+ mw_array_elt_len (array, len));
+
+ array->len += len;
+
+ mw_array_zero_terminate (array);
+
+ return array;
+}
+
+mw_array_t*
+mw_array_prepend_vals (mw_array_t *array,
+ const mw_pointer_t data,
+ mw_uint_t len)
+{
+ mw_array_maybe_expand (array, len);
+
+ memmove (mw_array_elt_pos (array, len), mw_array_elt_pos (array, 0),
+ mw_array_elt_len (array, array->len));
+
+ memcpy (mw_array_elt_pos (array, 0), data, mw_array_elt_len (array, len));
+
+ array->len += len;
+
+ mw_array_zero_terminate (array);
+
+ return array;
+}
+
+mw_array_t*
+mw_array_insert_vals (mw_array_t *array,
+ mw_uint_t index_,
+ const mw_pointer_t data,
+ mw_uint_t len)
+{
+ mw_array_maybe_expand (array, len);
+
+ memmove (mw_array_elt_pos (array, len + index_),
+ mw_array_elt_pos (array, index_),
+ mw_array_elt_len (array, array->len - index_));
+
+ memcpy (mw_array_elt_pos (array, index_), data,
+ mw_array_elt_len (array, len));
+
+ array->len += len;
+
+ mw_array_zero_terminate (array);
+
+ return array;
+}
+
+mw_array_t*
+mw_array_set_size (mw_array_t *array,
+ mw_uint_t length)
+{
+ if (length > array->len)
+ {
+ mw_array_maybe_expand (array, length - array->len);
+
+ if (array->clear)
+ mw_array_elt_zero (array, array->len, length - array->len);
+ }
+ else if (length < array->len)
+ mw_array_elt_zero (array, length, array->len - length);
+
+ array->len = length;
+
+ mw_array_zero_terminate (array);
+
+ return array;
+}
+
+mw_array_t*
+mw_array_remove_index (mw_array_t *array,
+ mw_uint_t index_)
+{
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+
+ if (index_ != array->len - 1)
+ memmove (mw_array_elt_pos (array, index_),
+ mw_array_elt_pos (array, index_ + 1),
+ mw_array_elt_len (array, array->len - index_ - 1));
+
+ array->len -= 1;
+ mw_array_elt_zero (array, array->len, 1);
+
+ return array;
+}
+
+mw_array_t*
+mw_array_remove_index_fast (mw_array_t *array,
+ mw_uint_t index_)
+{
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+
+ if (index_ != array->len - 1)
+ memcpy (mw_array_elt_pos (array, index_),
+ mw_array_elt_pos (array, array->len - 1),
+ mw_array_elt_len (array, 1));
+
+ array->len -= 1;
+ mw_array_elt_zero (array, array->len, 1);
+ return array;
+}
+
+mw_array_t*
+mw_array_remove_range (mw_array_t *array,
+ mw_uint_t index_,
+ mw_uint_t length)
+{
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+ mw_assert (index_ + length <= array->len);
+
+ if (index_ + length != array->len)
+ memmove (mw_array_elt_pos (array, index_),
+ mw_array_elt_pos (array, index_ + length),
+ (array->len - (index_ + length)) * array->elt_size);
+
+ array->len -= length;
+ mw_array_elt_zero (array, array->len, length);
+
+ return array;
+}
+
+void
+mw_array_sort (mw_array_t *array,
+ mw_compare_func_t compare_func)
+{
+ mw_assert (array != NULL);
+
+ qsort (array->data,
+ array->len,
+ array->elt_size,
+ (int (*)(const void*, const void*))compare_func);
+}
+
+void
+mw_array_sort_with_data (mw_array_t *array,
+ mw_compare_data_func_t compare_func,
+ mw_pointer_t user_data)
+{
+ mw_assert (array != NULL);
+
+ mw_qsort_with_data (array->data,
+ array->len,
+ array->elt_size,
+ compare_func,
+ user_data);
+}
+
+
+static int
+mw_nearest_pow (int num)
+{
+ int n = 1;
+
+ while (n < num)
+ n <<= 1;
+
+ return n;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+static void
+mw_array_maybe_expand (mw_array_t *array,
+ int len)
+{
+ mw_uint_t want_alloc = mw_array_elt_len (array, array->len + len +
+ array->zero_terminated);
+
+ if (want_alloc > array->alloc)
+ {
+ want_alloc = mw_nearest_pow (want_alloc);
+ want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
+
+ array->data = realloc (array->data, want_alloc);
+
+ memset (array->data + array->alloc, 0, want_alloc - array->alloc);
+ array->alloc = want_alloc;
+ }
+}
+
+static void
+mw_array_finalize(mw_object_t *super)
+{
+ mw_array_t *self = (mw_array_t*)super;
+ mw_object_type_t *stype = MW_SUPER_TYPE_BASE(super, MW_ARRAY_TYPE);
+
+ free (self->data);
+ stype->finalize(super);
+}
+
+static void
+mw_array_type_init(mw_array_type_t *self)
+{
+ self->base.finalize = mw_array_finalize;
+}
+
+MW_DEFINE_GET_TYPE(mw_array, mw_array_type_t,
+ MW_OBJECT_TYPE, "MWArray", 0);
diff --git a/milkway/mw-array.h b/milkway/mw-array.h
new file mode 100644
index 0000000..f4cefc4
--- /dev/null
+++ b/milkway/mw-array.h
@@ -0,0 +1,129 @@
+/* GLIB - Library of useful routines for C programming
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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/.
+ */
+
+#ifndef __MW_ARRAY_H__
+#define __MW_ARRAY_H__
+
+MW_BEGIN_DECLS
+
+#include <milkway/mw-object.h>
+
+typedef struct _mw_array mw_array_t;
+typedef struct _mw_array_type mw_array_type_t;
+
+struct _mw_array
+{
+ mw_object_t base;
+
+ mw_char_t *data;
+ mw_uint_t len;
+ mw_uint_t alloc;
+ mw_uint_t elt_size;
+ mw_uint_t zero_terminated : 1;
+ mw_uint_t clear : 1;
+};
+
+struct _mw_array_type {
+ mw_object_type_t base;
+};
+
+/* Resizable arrays. remove fills any cleared spot and shortens the
+ * array, while preserving the order. remove_fast will distort the
+ * order by moving the last element to the position of the removed.
+ */
+
+#define mw_array_append_val(a,v) mw_array_append_vals (a, &(v), 1)
+#define mw_array_prepend_val(a,v) mw_array_prepend_vals (a, &(v), 1)
+#define mw_array_insert_val(a,i,v) mw_array_insert_vals (a, i, &(v), 1)
+#define mw_array_index(a,t,i) (((t*) (void *) (a)->data) [(i)])
+
+#define MW_ARRAY_TYPE mw_array_get_type()
+
+mw_public mw_array_type_t*
+mw_array_get_type(void);
+
+mw_public mw_array_t*
+mw_array_new (mw_bool_t zero_terminated,
+ mw_bool_t clear_,
+ mw_uint_t element_size);
+
+mw_public mw_array_t*
+mw_array_sized_new (mw_bool_t zero_terminated,
+ mw_bool_t clear_,
+ mw_uint_t element_size,
+ mw_uint_t reserved_size);
+
+mw_public char*
+mw_array_take (mw_array_t *array);
+
+mw_public mw_uint_t
+mw_array_get_element_size (mw_array_t *array);
+
+mw_public mw_array_t*
+mw_array_append_vals (mw_array_t *array,
+ const mw_pointer_t data,
+ mw_uint_t len);
+
+mw_public mw_array_t*
+mw_array_prepend_vals (mw_array_t *array,
+ const mw_pointer_t data,
+ mw_uint_t len);
+
+mw_public mw_array_t*
+mw_array_insert_vals (mw_array_t *array,
+ mw_uint_t index_,
+ const mw_pointer_t data,
+ mw_uint_t len);
+
+mw_public mw_array_t*
+mw_array_set_size (mw_array_t *array,
+ mw_uint_t length);
+
+mw_public mw_array_t*
+mw_array_remove_index (mw_array_t *array,
+ mw_uint_t index_);
+
+mw_public mw_array_t*
+mw_array_remove_index_fast (mw_array_t *array,
+ mw_uint_t index_);
+
+mw_public mw_array_t*
+mw_array_remove_range (mw_array_t *array,
+ mw_uint_t index_,
+ mw_uint_t length);
+
+mw_public void
+mw_array_sort (mw_array_t *array,
+ mw_compare_func_t compare_func);
+
+mw_public void
+mw_array_sort_with_data (mw_array_t *array,
+ mw_compare_data_func_t compare_func,
+ mw_pointer_t user_data);
+
+MW_END_DECLS
+
+#endif /* __MW_ARRAY_H__ */
diff --git a/milkway/mw-ptr-array.c b/milkway/mw-ptr-array.c
new file mode 100644
index 0000000..14d9958
--- /dev/null
+++ b/milkway/mw-ptr-array.c
@@ -0,0 +1,386 @@
+/* GLIB - Library of useful routines for C programming
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "milkwayint.h"
+#include "milkway/mw-ptr-array.h"
+#include "milkway/mw-qsort.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define MIN_ARRAY_SIZE 16
+
+#define mw_array_elt_len(array, i) ((array)->elt_size * (i))
+#define mw_array_elt_pos(array,i) ((array)->data + mw_array_elt_len((array),(i)))
+#define mw_array_elt_zero(array, pos, len) \
+ (memset (mw_array_elt_pos ((array), pos), 0, mw_array_elt_len ((array), len)))
+#define mw_array_zero_terminate(array) \
+ do { \
+ if ((array)->zero_terminated) \
+ mw_array_elt_zero ((array), (array)->len, 1); \
+ } while (0)
+
+static void mw_ptr_array_maybe_expand (mw_ptr_array_t *array,
+ int len);
+
+static mw_ptr_array_t*
+mw_ptr_array_init (mw_ptr_array_t *array,
+ mw_ptr_array_type_t *type,
+ mw_uint_t reserved_size)
+{
+ if (!mw_object_init(&array->base, &type->base))
+ return NULL;
+
+ array->pdata = NULL;
+ array->len = 0;
+ array->alloc = 0;
+ array->element_free_func = NULL;
+
+ if (reserved_size != 0)
+ mw_ptr_array_maybe_expand (array, reserved_size);
+
+ return array;
+}
+
+mw_ptr_array_t*
+mw_ptr_array_new (void)
+{
+ return mw_ptr_array_sized_new (0);
+}
+
+mw_ptr_array_t*
+mw_ptr_array_sized_new (mw_uint_t reserved_size)
+{
+ mw_ptr_array_t *self = mw_object_alloc(MW_PTR_ARRAY_TYPE);
+
+ if (!self)
+ return NULL;
+ if (!mw_ptr_array_init(self, MW_PTR_ARRAY_TYPE, reserved_size))
+ return NULL;
+ return self;
+}
+
+
+/**
+ * mw_ptr_array_new_with_free_func:
+ * @element_free_func: A function to free elements with destroy @array or %NULL.
+ *
+ * Creates a new #mw_ptr_array_t with a reference count of 1 and use @element_free_func
+ * for freeing each element when the array is destroyed either via
+ * mw_ptr_array_unref(), when mw_ptr_array_free() is called with @free_segment
+ * set to %TRUE or when removing elements.
+ *
+ * Returns: A new #mw_ptr_array_t.
+ *
+ * Since: 2.22
+ **/
+mw_ptr_array_t *
+mw_ptr_array_new_with_free_func (mw_destroy_func_t element_free_func)
+{
+ mw_ptr_array_t *array;
+
+ array = mw_ptr_array_new ();
+ mw_ptr_array_set_free_func (array, element_free_func);
+ return array;
+}
+
+/**
+ * mw_ptr_array_set_free_func:
+ * @array: A #mw_ptr_array_t.
+ * @element_free_func: A function to free elements with destroy @array or %NULL.
+ *
+ * Sets a function for freeing each element when @array is destroyed
+ * either via mw_ptr_array_unref(), when mw_ptr_array_free() is called
+ * with @free_segment set to %TRUE or when removing elements.
+ *
+ * Since: 2.22
+ **/
+void
+mw_ptr_array_set_free_func (mw_ptr_array_t *array,
+ mw_destroy_func_t element_free_func)
+{
+ array->element_free_func = element_free_func;
+}
+
+mw_pointer_t*
+mw_ptr_array_take (mw_ptr_array_t *array)
+{
+ mw_pointer_t *segment;
+
+ segment = array->pdata;
+ array->pdata = NULL;
+ array->len = 0;
+ array->alloc = 0;
+ return segment;
+}
+
+static int
+mw_nearest_pow (int num)
+{
+ int n = 1;
+
+ while (n < num)
+ n <<= 1;
+
+ return n;
+}
+
+#undef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+static void
+mw_ptr_array_maybe_expand (mw_ptr_array_t *array,
+ int len)
+{
+ if ((array->len + len) > array->alloc)
+ {
+ mw_uint_t old_alloc = array->alloc;
+
+ array->alloc = mw_nearest_pow (array->len + len);
+ array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE);
+ array->pdata = realloc (array->pdata, sizeof (mw_pointer_t) * array->alloc);
+
+ mw_unless(array->pdata);
+
+ for ( ; old_alloc < array->alloc; old_alloc++)
+ array->pdata [old_alloc] = NULL;
+ }
+}
+
+void
+mw_ptr_array_set_size (mw_ptr_array_t *array,
+ unsigned int length)
+{
+ if (length > array->len)
+ {
+ unsigned int i;
+
+ mw_ptr_array_maybe_expand (array, (length - array->len));
+ /* This is not
+ * memset (array->pdata + array->len, 0,
+ * sizeof (mw_pointer_t) * (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;
+ }
+ else if (length < array->len)
+ mw_ptr_array_remove_range (array, length, array->len - length);
+
+ array->len = length;
+}
+
+mw_pointer_t
+mw_ptr_array_remove_index (mw_ptr_array_t *array,
+ mw_uint_t index_)
+{
+ mw_pointer_t result;
+
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+
+ result = array->pdata[index_];
+
+ if (array->element_free_func != NULL)
+ array->element_free_func (array->pdata[index_]);
+
+ if (index_ != array->len - 1)
+ memmove (array->pdata + index_, array->pdata + index_ + 1,
+ sizeof (mw_pointer_t) * (array->len - index_ - 1));
+
+ array->len -= 1;
+ array->pdata[array->len] = NULL;
+
+ return result;
+}
+
+mw_pointer_t
+mw_ptr_array_remove_index_fast (mw_ptr_array_t *array,
+ mw_uint_t index_)
+{
+ mw_pointer_t result;
+
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+
+ result = array->pdata[index_];
+
+ if (index_ != array->len - 1)
+ {
+ if (array->element_free_func != NULL)
+ array->element_free_func (array->pdata[index_]);
+ array->pdata[index_] = array->pdata[array->len - 1];
+ }
+
+ array->len -= 1;
+ array->pdata[array->len] = NULL;
+
+ return result;
+}
+
+void
+mw_ptr_array_remove_range (mw_ptr_array_t *array,
+ mw_uint_t index_,
+ mw_uint_t length)
+{
+ mw_uint_t n, i;
+
+ mw_assert (array);
+ mw_assert (index_ < array->len);
+ mw_assert (index_ + length <= array->len);
+
+ if (array->element_free_func != NULL)
+ {
+ for (n = index_; n < index_ + length; n++)
+ array->element_free_func (array->pdata[n]);
+ }
+
+ if (index_ + length != array->len)
+ {
+ memmove (&array->pdata[index_],
+ &array->pdata[index_ + length],
+ (array->len - (index_ + length)) * sizeof (mw_pointer_t));
+ }
+
+ array->len -= length;
+
+ for (i = 0; i < length; i++)
+ array->pdata[array->len + i] = NULL;
+}
+
+mw_bool_t
+mw_ptr_array_remove (mw_ptr_array_t *array,
+ mw_pointer_t data)
+{
+ mw_uint_t i;
+
+ for (i = 0; i < array->len; i += 1)
+ {
+ if (array->pdata[i] == data)
+ {
+ mw_ptr_array_remove_index (array, i);
+ return MW_TRUE;
+ }
+ }
+
+ return MW_FALSE;
+}
+
+mw_bool_t
+mw_ptr_array_remove_fast (mw_ptr_array_t *array,
+ mw_pointer_t data)
+{
+ mw_uint_t i;
+
+ mw_assert (array);
+
+ for (i = 0; i < array->len; i += 1)
+ {
+ if (array->pdata[i] == data)
+ {
+ mw_ptr_array_remove_index_fast (array, i);
+ return MW_TRUE;
+ }
+ }
+
+ return MW_FALSE;
+}
+
+void
+mw_ptr_array_add (mw_ptr_array_t *array,
+ mw_pointer_t data)
+{
+ mw_ptr_array_maybe_expand (array, 1);
+ array->pdata[array->len++] = data;
+}
+
+void
+mw_ptr_array_sort (mw_ptr_array_t *array,
+ mw_compare_func_t compare_func)
+{
+ qsort (array->pdata,
+ array->len,
+ sizeof (mw_pointer_t),
+ (int (*)(const void*, const void*))compare_func);
+}
+
+void
+mw_ptr_array_sort_with_data (mw_ptr_array_t *array,
+ mw_compare_data_func_t compare_func,
+ mw_pointer_t user_data)
+{
+ mw_qsort_with_data (array->pdata,
+ array->len,
+ sizeof (mw_pointer_t),
+ compare_func,
+ user_data);
+}
+
+/**
+ * mw_ptr_array_foreach:
+ * @array: a #mw_ptr_array_t
+ * @func: the function to call for each array element
+ * @user_data: user data to pass to the function
+ *
+ * Calls a function for each element of a #mw_ptr_array_t.
+ *
+ * Since: 2.4
+ **/
+void
+mw_ptr_array_foreach (mw_ptr_array_t *array,
+ mw_func_t func,
+ mw_pointer_t user_data)
+{
+ mw_uint_t i;
+
+ for (i = 0; i < array->len; i++)
+ (*func) (array->pdata[i], user_data);
+}
+
+static void
+mw_ptr_array_finalize(mw_object_t *super)
+{
+ mw_ptr_array_t *self = (mw_ptr_array_t*)super;
+ mw_object_type_t *stype = MW_SUPER_TYPE_BASE(super, MW_PTR_ARRAY_TYPE);
+
+ if (self->pdata && self->element_free_func != NULL)
+ mw_ptr_array_foreach (self, (mw_func_t) self->element_free_func, NULL);
+
+ free (self->pdata);
+ stype->finalize(super);
+}
+
+static void
+mw_ptr_array_type_init(mw_ptr_array_type_t *self)
+{
+ self->base.finalize = mw_ptr_array_finalize;
+}
+
+MW_DEFINE_GET_TYPE(mw_ptr_array, mw_ptr_array_type_t,
+ MW_OBJECT_TYPE, "MWPtrArray", 0);
diff --git a/milkway/mw-ptr-array.h b/milkway/mw-ptr-array.h
new file mode 100644
index 0000000..da2e4e0
--- /dev/null
+++ b/milkway/mw-ptr-array.h
@@ -0,0 +1,123 @@
+/* GLIB - Library of useful routines for C programming
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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/.
+ */
+
+#ifndef __MW_PTR_ARRAY_H__
+#define __MW_PTR_ARRAY_H__
+
+MW_BEGIN_DECLS
+
+#include <milkway/mw-object.h>
+
+typedef struct _mw_ptr_array mw_ptr_array_t;
+typedef struct _mw_ptr_array_type mw_ptr_array_type_t;
+
+struct _mw_ptr_array
+{
+ mw_object_t base;
+
+ mw_pointer_t *pdata;
+ mw_uint_t len;
+ mw_uint_t alloc;
+ mw_destroy_func_t element_free_func;
+};
+
+struct _mw_ptr_array_type {
+ mw_object_type_t base;
+};
+
+#define MW_PTR_ARRAY_TYPE mw_ptr_array_get_type()
+
+/* Resizable pointer array. This interface is much less complicated
+ * than the above. Add appends a pointer. Remove fills any cleared
+ * spot and shortens the array. remove_fast will again distort order.
+ */
+#define mw_ptr_array_index(array,index_) ((array)->pdata)[index_]
+
+mw_public mw_ptr_array_type_t*
+mw_ptr_array_get_type(void);
+
+mw_public
+mw_ptr_array_t* mw_ptr_array_new (void);
+
+mw_public mw_ptr_array_t*
+mw_ptr_array_new_with_free_func (mw_destroy_func_t element_free_func);
+
+mw_public mw_ptr_array_t*
+mw_ptr_array_sized_new (mw_uint_t reserved_size);
+
+mw_public mw_pointer_t*
+mw_ptr_array_take (mw_ptr_array_t *array);
+
+mw_public void
+mw_ptr_array_set_free_func (mw_ptr_array_t *array,
+ mw_destroy_func_t element_free_func);
+
+mw_public void
+mw_ptr_array_set_size (mw_ptr_array_t *array,
+ unsigned int length);
+
+mw_public mw_pointer_t
+mw_ptr_array_remove_index (mw_ptr_array_t *array,
+ mw_uint_t index_);
+
+mw_public mw_pointer_t
+mw_ptr_array_remove_index_fast (mw_ptr_array_t *array,
+ mw_uint_t index_);
+
+mw_public mw_bool_t
+mw_ptr_array_remove (mw_ptr_array_t *array,
+ mw_pointer_t data);
+
+mw_public mw_bool_t
+mw_ptr_array_remove_fast (mw_ptr_array_t *array,
+ mw_pointer_t data);
+
+mw_public void
+mw_ptr_array_remove_range (mw_ptr_array_t *array,
+ mw_uint_t index_,
+ mw_uint_t length);
+
+mw_public void
+mw_ptr_array_add (mw_ptr_array_t *array,
+ mw_pointer_t data);
+
+mw_public void
+mw_ptr_array_sort (mw_ptr_array_t *array,
+ mw_compare_func_t compare_func);
+
+mw_public void
+mw_ptr_array_sort_with_data (mw_ptr_array_t *array,
+ mw_compare_data_func_t compare_func,
+ mw_pointer_t user_data);
+
+mw_public void
+mw_ptr_array_foreach (mw_ptr_array_t *array,
+ mw_func_t func,
+ mw_pointer_t user_data);
+
+MW_END_DECLS
+
+#endif /* __MW_ARRAY_H__ */