summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2008-11-08 07:54:26 -0500
committerSøren Sandmann <sandmann@redhat.com>2008-11-08 07:54:26 -0500
commit6cfabb95cf52aa0c34ed201106a799eb6474ae8b (patch)
tree732958f3023066b4ab10f5c7fa380087c13650ae /array.c
parentbeea00c337ceb360739aa2bd435bea88b286c0dc (diff)
Implement parr's in terms of a general array type
Diffstat (limited to 'array.c')
-rw-r--r--array.c153
1 files changed, 101 insertions, 52 deletions
diff --git a/array.c b/array.c
index 127c302..87db36e 100644
--- a/array.c
+++ b/array.c
@@ -15,8 +15,96 @@
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <string.h>
#include "libnul.h"
+/* General array implementation */
+
+#define INITIAL_SIZE 30
+
+typedef struct array_t array_t;
+
+typedef union
+{
+ double d;
+ int i;
+ void *p;
+ long l;
+} align_t;
+
+struct array_t
+{
+ const int *magic;
+ int element_size;
+ gssize n_bytes; /* Number of bytes allocated in total */
+ gssize n_elements; /* Number of elements in use, not including
+ * the nul terminator
+ */
+ align_t data[1];
+};
+
+static inline array_t *
+get_array (void *data, const int *magic)
+{
+ array_t *array;
+
+ array = (array_t *)((uint8_t *)data - NUL_STRUCT_OFFSET (array_t, data));
+
+ g_return_val_if_fail (array->magic == magic, NULL);
+
+ return array;
+}
+
+static void
+array_free (array_t *array, const int *magic)
+{
+ g_return_if_fail (array->magic == magic);
+
+ g_free (array);
+}
+
+static array_t *
+realloc_array (array_t *array, int n_elements)
+{
+ gssize n_bytes;
+
+ /* FIXME: overflow? */
+ n_bytes = NUL_STRUCT_OFFSET (array_t, data);
+ if (!array)
+ n_bytes += 128;
+ else
+ n_bytes += (n_elements + 1) * array->element_size;
+
+ if (!array || n_bytes > array->n_bytes)
+ {
+ gssize pot;
+
+ pot = 1;
+ while (pot < n_bytes)
+ pot *= 2;
+
+ array = g_realloc (array, pot);
+ array->n_bytes = pot;
+ }
+
+ return array;
+}
+
+static void *
+array_new (int element_size, const int *magic)
+{
+ array_t *array = realloc_array (NULL, -1);
+
+ array->element_size = element_size;
+ array->magic = magic;
+ array->n_elements = 0;
+ memset (array->data, 0, element_size);
+
+ return array->data;
+}
+
+
+
/* Pointer arrays. The idiomatic way to iterate through such an array is:
*
* void **p;
@@ -58,78 +146,39 @@ struct parr_t
#define INITIAL_SIZE 30
-static parr_t *
-realloc_parr (parr_t *parr, int n_pointers)
-{
- gssize n_bytes;
-
- /* FIXME: overflow? */
- n_bytes = NUL_STRUCT_OFFSET (parr_t, data) + n_pointers * sizeof (void *) + 1;
-
- if (!parr || n_bytes > parr->n_bytes)
- {
- gssize pot;
-
- pot = 1;
- while (pot < n_bytes)
- pot *= 2;
-
- parr = g_realloc (parr, pot);
- parr->magic = &parr_t_magic;
- parr->n_bytes = pot;
- }
-
- return parr;
-}
+static const int parr_t_magic;
void **
nul_parr_new (void)
{
- parr_t *parr = realloc_parr (NULL, INITIAL_SIZE);
-
- parr->data[0] = NULL;
- parr->n_used = 0;
-
- return parr->data;
-}
-
-static inline parr_t *
-get_parr (void **data)
-{
- parr_t *parr;
-
- parr = (parr_t *)((uint8_t *)data - NUL_STRUCT_OFFSET (parr_t, data));
-
- g_return_val_if_fail (parr->magic == &parr_t_magic, NULL);
-
- return parr;
+ return array_new (sizeof (void *), &parr_t_magic);
}
void **
nul_parr_append (void **arr, gpointer data)
{
- parr_t *parr = get_parr (arr);
+ array_t *array = get_array (arr, &parr_t_magic);
- realloc_parr (parr, parr->n_used + 1);
+ array = realloc_array (array, array->n_elements + 1);
- parr->data[parr->n_used++] = data;
- parr->data[parr->n_used] = NULL;
+ arr = (void **)array->data;
- return parr->data;
+ arr[array->n_elements++] = data;
+ arr[array->n_elements] = NULL;
+
+ return arr;
}
void
nul_parr_free (void **arr)
{
- parr_t *parr = get_parr (arr);
-
- g_free (parr);
+ array_free (get_array (arr, &parr_t_magic), &parr_t_magic);
}
gsize
-nul_parr_len (void **arr)
+nul_parr_len (void **arr)
{
- parr_t *parr = get_parr (arr);
+ array_t *array = get_array (arr, &parr_t_magic);
- return parr->n_used;
+ return array->n_elements;
}