diff options
author | Søren Sandmann <sandmann@redhat.com> | 2008-11-08 07:54:26 -0500 |
---|---|---|
committer | Søren Sandmann <sandmann@redhat.com> | 2008-11-08 07:54:26 -0500 |
commit | 6cfabb95cf52aa0c34ed201106a799eb6474ae8b (patch) | |
tree | 732958f3023066b4ab10f5c7fa380087c13650ae /array.c | |
parent | beea00c337ceb360739aa2bd435bea88b286c0dc (diff) |
Implement parr's in terms of a general array type
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 153 |
1 files changed, 101 insertions, 52 deletions
@@ -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; } |