changeset 3190:ba17b6e45193 HEAD

Added dynamic array implementation. When compiling with gcc and DEBUG enabled, gcc checks type safety at compile time.
author Timo Sirainen <tss@iki.fi>
date Sat, 12 Mar 2005 20:15:48 +0200
parents f80be7e73f71
children 0df3f5d71958
files src/lib/Makefile.am src/lib/array.h src/lib/lib.h
diffstat 3 files changed, 261 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/Makefile.am	Sat Mar 12 14:24:28 2005 +0200
+++ b/src/lib/Makefile.am	Sat Mar 12 20:15:48 2005 +0200
@@ -71,6 +71,7 @@
 	write-full.c
 
 noinst_HEADERS = \
+	array.h \
 	base64.h \
 	buffer.h \
 	compat.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/array.h	Sat Mar 12 20:15:48 2005 +0200
@@ -0,0 +1,256 @@
+#ifndef __ARRAY_H
+#define __ARRAY_H
+
+#include "buffer.h"
+
+/* Array is a buffer accessible using fixed size elements. If DEBUG is
+   enabled, it also provides compile time type safety:
+
+   If DEBUG is enabled, an extra variable is defined along with the array
+   itself. This is used to cast ARRAY_IDX() return value correctly, so
+   compiler gives a warning if it's assigned into variable with a different
+   type.
+
+   Example usage:
+
+   struct foo {
+   	array_t ARRAY_DEFINE(bars, struct bar);
+	...
+   };
+
+   ARRAY_CREATE(foo->bars, default_pool, struct bar, 10);
+   ARRAY_CREATE(foo->bars, default_pool, struct baz, 10); // compiler error
+
+   struct bar *bar = ARRAY_IDX(foo->bars, 5);
+   struct baz *baz = ARRAY_IDX(foo->bars, 5); // compiler warning
+*/
+#if defined (DEBUG) && defined (__GNUC__)
+#  define ARRAY_DEFINE(name, array_type) name; array_type *name ## __ ## type
+#  define ARRAY_CREATE(array, pool, array_type, init_count) STMT_START { \
+	array_type *_array_tmp = *(array ## __ ## type); _array_tmp = NULL; \
+	array_create(array, pool, sizeof(array_type), init_count); \
+	} STMT_END
+#  define ARRAY_ARG_SET_TYPE(array, array_type) \
+	array_type **array ## __ ## type = NULL
+#else
+#  define ARRAY_DEFINE(name, array_type) name
+#  define ARRAY_CREATE(array, pool, array_type, init_count) \
+	array_create(array, pool, sizeof(array_type), init_count);
+#  define ARRAY_ARG_SET_TYPE(array, array_type)
+#endif
+
+struct array {
+	buffer_t *buffer;
+	size_t element_size;
+};
+
+static inline void
+array_create_from_buffer(array_t *array, buffer_t *buffer, size_t element_size)
+{
+	array->buffer = buffer;
+	array->element_size = element_size;
+}
+
+static inline void
+array_create(array_t *array, pool_t pool,
+	     size_t element_size, unsigned int init_count)
+{
+	buffer_t *buffer;
+
+        buffer = buffer_create_dynamic(pool, init_count * element_size);
+	array_create_from_buffer(array, buffer, element_size);
+}
+
+static inline void
+array_free(array_t *array)
+{
+	buffer_free(array->buffer);
+	array->buffer = NULL;
+}
+
+static inline int
+array_is_created(const array_t *array)
+{
+	return array->buffer != NULL;
+}
+
+static inline void
+array_clear(array_t *array)
+{
+	buffer_set_used_size(array->buffer, 0);
+}
+
+static inline void
+_array_append(array_t *array, const void *data, unsigned int count)
+{
+	buffer_append(array->buffer, data, count * array->element_size);
+}
+#ifndef DEBUG
+#  define array_append _array_append
+#else
+#  define array_append(array, data, count) STMT_START { \
+	typeof(*(array ## __ ## type)) _array_tmp = data; \
+	_array_append(array, _array_tmp, count); \
+	} STMT_END
+#endif
+
+static inline void
+array_append_array(array_t *dest_array, const array_t *src_array)
+{
+	i_assert(dest_array->element_size == src_array->element_size);
+	buffer_append_buf(dest_array->buffer, src_array->buffer, 0, (size_t)-1);
+}
+
+static inline void
+_array_insert(array_t *array, unsigned int idx,
+	      const void *data, unsigned int count)
+{
+	buffer_insert(array->buffer, idx * array->element_size,
+		      data, count * array->element_size);
+}
+#ifndef DEBUG
+#  define array_insert _array_insert
+#else
+#  define array_insert(array, idx, data, count) STMT_START { \
+	typeof(*(array ## __ ## type)) _array_tmp = data; \
+	_array_insert(array, idx, _array_tmp, count); \
+	} STMT_END
+#endif
+
+static inline void
+array_delete(array_t *array, unsigned int idx, unsigned int count)
+{
+	buffer_delete(array->buffer, idx * array->element_size,
+		      count * array->element_size);
+}
+
+static inline const void *
+_array_get(const array_t *array, unsigned int *count_r)
+{
+	if (count_r != NULL)
+		*count_r = array->buffer->used / array->element_size;
+	return array->buffer->data;
+}
+#ifndef DEBUG
+#  define array_get _array_get
+#else
+#  define array_get(array, count) \
+	(const typeof(*(array ## __ ## type)))_array_get(array, count)
+#endif
+
+static inline const void *
+_array_idx(const array_t *array, unsigned int idx)
+{
+	i_assert(idx * array->element_size < array->buffer->used);
+	return CONST_PTR_OFFSET(array->buffer->data, idx * array->element_size);
+}
+#ifndef DEBUG
+#  define array_idx _array_idx
+#else
+#  define array_idx(array, idx) \
+	(const typeof(*(array ## __ ## type)))_array_idx(array, idx)
+#endif
+
+static inline void *
+_array_get_modifyable(array_t *array, unsigned int *count_r)
+{
+	if (count_r != NULL)
+		*count_r = array->buffer->used / array->element_size;
+	return buffer_get_modifyable_data(array->buffer, NULL);
+}
+#ifndef DEBUG
+#  define array_get_modifyable _array_get_modifyable
+#else
+#  define array_get_modifyable(array, count) \
+	(typeof(*(array ## __ ## type))) \
+		_array_get_modifyable(array, count)
+#endif
+
+static inline void *
+_array_modifyable_idx(array_t *array, unsigned int idx)
+{
+	size_t pos;
+
+	pos = idx * array->element_size;
+	if (pos >= array->buffer->used) {
+		/* index doesn't exist yet, initialize with zero */
+		buffer_append_zero(array->buffer, pos + array->element_size -
+				   array->buffer->used);
+	}
+	return buffer_get_space_unsafe(array->buffer, pos, array->element_size);
+}
+#ifndef DEBUG
+#  define array_modifyable_idx _array_modifyable_idx
+#else
+#  define array_modifyable_idx(array, count) \
+	(typeof(*(array ## __ ## type))) \
+		_array_modifyable_idx(array, count)
+#endif
+
+static inline void
+_array_idx_set(array_t *array, unsigned int idx, const void *data)
+{
+	size_t pos;
+
+	pos = idx * array->element_size;
+	if (pos > array->buffer->used) {
+		/* index doesn't exist yet, initialize with zero */
+		buffer_append_zero(array->buffer, pos - array->buffer->used);
+	}
+	buffer_write(array->buffer, pos, data, array->element_size);
+}
+#ifndef DEBUG
+#  define array_idx_set _array_idx_set
+#else
+#  define array_idx_set(array, idx, data) STMT_START { \
+	typeof(*(array ## __ ## type)) _array_tmp = data; \
+	_array_idx_set(array, idx, _array_tmp); \
+	} STMT_END
+#endif
+
+static inline void *
+_array_modifyable_append(array_t *array)
+{
+	void *data;
+
+	data = buffer_append_space_unsafe(array->buffer, array->element_size);
+	memset(data, 0, array->element_size);
+	return data;
+}
+#ifndef DEBUG
+#  define array_modifyable_append _array_modifyable_append
+#else
+#  define array_modifyable_append(array) \
+	(typeof(*(array ## __ ## type))) \
+		_array_modifyable_append(array)
+#endif
+
+static inline void *
+_array_modifyable_insert(array_t *array, unsigned int idx)
+{
+	void *data;
+	size_t pos;
+
+	pos = idx * array->element_size;
+	buffer_copy(array->buffer, pos + array->element_size,
+		    array->buffer, pos, (size_t)-1);
+
+	data = buffer_get_space_unsafe(array->buffer, pos, array->element_size);
+	memset(data, 0, array->element_size);
+	return data;
+}
+#ifndef DEBUG
+#  define array_modifyable_insert _array_modifyable_insert
+#else
+#  define array_modifyable_insert(array, idx) \
+	(typeof(*(array ## __ ## type))) \
+		_array_modifyable_insert(array, idx)
+#endif
+
+static inline unsigned int
+array_count(const array_t *array)
+{
+	return array->buffer->used / array->element_size;
+}
+
+#endif
--- a/src/lib/lib.h	Sat Mar 12 14:24:28 2005 +0200
+++ b/src/lib/lib.h	Sat Mar 12 20:15:48 2005 +0200
@@ -28,14 +28,16 @@
 #include "mempool.h"
 #include "imem.h"
 
-#include "strfuncs.h"
-
 typedef struct buffer buffer_t;
+typedef struct array array_t;
 typedef struct buffer string_t;
 
 struct istream;
 struct ostream;
 
+#include "array.h" /* ARRAY_DEFINE()s may exist in any header */
+#include "strfuncs.h"
+
 extern unsigned char null4[4]; /* 4 zeros - useful for padding */
 
 size_t nearest_power(size_t num);