array.h revision 489a4b34972902602320f910fc0c6014ea072c50
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#ifndef __ARRAY_H
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define __ARRAY_H
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce/* Array is a buffer accessible using fixed size elements. As long as the
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce compiler provides typeof() function, the array provides type safety. If
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce a wrong type is tried to be added to the array, or if the array's contents
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce are tried to be used using a wrong type, the compiler will give a warning.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Example usage:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct foo {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_DEFINE(bars, struct bar);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ...
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce };
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_CREATE(&foo->bars, default_pool, struct bar, 10);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_CREATE(&foo->bars, default_pool, struct baz, 10); // compiler warning
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct bar *bar = array_idx(&foo->bars, 5);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct baz *baz = array_idx(&foo->bars, 5); // compiler warning
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce If you want to pass an array as a parameter to a function, you'll need to
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce create a type for the array using ARRAY_DEFINE_TYPE() and use the type in
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce the parameter using ARRAY_TYPE().
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Example:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_DEFINE_TYPE(foo, struct foo);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce void do_foo(ARRAY_TYPE(foo) *bars) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct foo *foo = array_idx(bars, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce*/
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include "array-decl.h"
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include "buffer.h"
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define ARRAY_CREATE(array, pool, array_type, init_count) STMT_START { \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array_type const *_array_tmp = (array)->v; _array_tmp = NULL; \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array_create(array, pool, sizeof(array_type), init_count); \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } STMT_END
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#ifdef __GNUC__
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CAST_CONST(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (typeof((array)->v))
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CAST_MODIFIABLE(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (typeof((array)->v_modifiable))
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CHECK(array, data) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce typeof((array)->v_modifiable) __tmp_array_data2 __attr_unused__ = \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (typeof(const typeof(typeof(*(data)) *)))NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#else
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CAST_CONST(array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CAST_MODIFIABLE(array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce# define ARRAY_TYPE_CHECK(array, data)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#endif
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_create_from_buffer(struct array *array, buffer_t *buffer,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t element_size)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array->buffer = buffer;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array->element_size = element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_create_from_buffer(array, buffer, element_size) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_create_from_buffer(&(array)->arr, buffer, element_size)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_create(struct array *array, pool_t pool,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t element_size, unsigned int init_count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_t *buffer;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer = buffer_create_dynamic(pool, init_count * element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_create_from_buffer(array, buffer, element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_create(array, pool, element_size, init_count) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_create(&(array)->arr, pool, element_size, init_count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_free(struct array *array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_free(array->buffer);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array->buffer = NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_free(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_free(&(array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline bool
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_is_created(const struct array *array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return array->buffer != NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_is_created(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_is_created(&(array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_clear(struct array *array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_set_used_size(array->buffer, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_clear(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_clear(&(array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_append(struct array *array, const void *data, unsigned int count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_append(array->buffer, data, count * array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_append(array, data, count) STMT_START { \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CHECK(array, data) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_append(&(array)->arr, data, count); \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce} STMT_END
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_append_array(struct array *dest_array, const struct array *src_array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_assert(dest_array->element_size == src_array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_append_buf(dest_array->buffer, src_array->buffer, 0, (size_t)-1);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_append_array(dest_array, src_array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_append_array(&(dest_array)->arr, &(src_array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_insert(struct array *array, unsigned int idx,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const void *data, unsigned int count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_insert(array->buffer, idx * array->element_size,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce data, count * array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_insert(array, idx, data, count) STMT_START { \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CHECK(array, data) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_insert(&(array)->arr, idx, data, count); \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } STMT_END
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_delete(struct array *array, unsigned int idx, unsigned int count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_delete(array->buffer, idx * array->element_size,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce count * array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_delete(array, idx, count) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_delete(&(array)->arr, idx, count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline const void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_get(const struct array *array, unsigned int *count_r)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (count_r != NULL)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce *count_r = array->buffer->used / array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return array->buffer->data;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_get(array, count) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_CONST(array)_array_get(&(array)->arr, count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline const void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_idx(const struct array *array, unsigned int idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce i_assert(idx * array->element_size < array->buffer->used);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return CONST_PTR_OFFSET(array->buffer->data, idx * array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_idx(array, idx) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_CONST(array)_array_idx(&(array)->arr, idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_get_modifiable(struct array *array, unsigned int *count_r)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (count_r != NULL)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce *count_r = array->buffer->used / array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return buffer_get_modifiable_data(array->buffer, NULL);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_get_modifiable(array, count) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_MODIFIABLE(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_get_modifiable(&(array)->arr, count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_idx_modifiable(struct array *array, unsigned int idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t pos;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pos = idx * array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (pos >= array->buffer->used) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* index doesn't exist yet, initialize with zero */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_append_zero(array->buffer, pos + array->element_size -
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array->buffer->used);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return buffer_get_space_unsafe(array->buffer, pos, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_idx_modifiable(array, count) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_MODIFIABLE(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_idx_modifiable(&(array)->arr, count)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_idx_set(struct array *array, unsigned int idx, const void *data)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t pos;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pos = idx * array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (pos > array->buffer->used) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* index doesn't exist yet, initialize with zero */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_append_zero(array->buffer, pos - array->buffer->used);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_write(array->buffer, pos, data, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_idx_set(array, idx, data) STMT_START { \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CHECK(array, data) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_idx_set(&(array)->arr, idx, data); \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } STMT_END
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_idx_clear(struct array *array, unsigned int idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t pos;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pos = idx * array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (pos > array->buffer->used) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* index doesn't exist yet, initialize with zero */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_append_zero(array->buffer, pos - array->buffer->used);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_write_zero(array->buffer, pos, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_idx_clear(array, idx) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_idx_clear(&(array)->arr, idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_append_space(struct array *array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce void *data;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce data = buffer_append_space_unsafe(array->buffer, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce memset(data, 0, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return data;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_append_space(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_MODIFIABLE(array)_array_append_space(&(array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline void *
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_insert_space(struct array *array, unsigned int idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce void *data;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce size_t pos;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce pos = idx * array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce buffer_copy(array->buffer, pos + array->element_size,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce array->buffer, pos, (size_t)-1);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce data = buffer_get_space_unsafe(array->buffer, pos, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce memset(data, 0, array->element_size);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return data;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_insert_space(array, idx) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ARRAY_TYPE_CAST_MODIFIABLE(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_insert_space(&(array)->arr, idx)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline unsigned int
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_count(const struct array *array)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return array->buffer->used / array->element_size;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_count(array) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_count(&(array)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic inline bool
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce_array_cmp(const struct array *array1, const struct array *array2)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (!_array_is_created(array1) || array1->buffer->used == 0)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return !_array_is_created(array2) || array2->buffer->used == 0;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (!_array_is_created(array2))
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return FALSE;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return buffer_cmp(array1->buffer, array2->buffer);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#define array_cmp(array1, array2) \
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce _array_cmp(&(array1)->arr, &(array2)->arr)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#endif
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce