array.h revision 1df7543b209cabc208515c6bfc3b123f6ea184c2
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen/* Array is a buffer accessible using fixed size elements. As long as the
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen compiler provides typeof() function, the array provides type safety. If
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen a wrong type is tried to be added to the array, or if the array's contents
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen are tried to be used using a wrong type, the compiler will give a warning.
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen Example usage:
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_DEFINE(bars, struct bar);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i_array_init(&foo->bars, 10);
bd3714d623d67f7dc8bd70ba39b467762ae409e8Timo Sirainen struct bar *bar = array_idx(&foo->bars, 5);
bd3714d623d67f7dc8bd70ba39b467762ae409e8Timo Sirainen struct baz *baz = array_idx(&foo->bars, 5); // compiler warning
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen If you want to pass an array as a parameter to a function, you'll need to
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen create a type for the array using ARRAY_DEFINE_TYPE() and use the type in
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen the parameter using ARRAY_TYPE().
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen ARRAY_DEFINE_TYPE(foo, struct foo);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen void do_foo(ARRAY_TYPE(foo) *bars) {
3bc4e3b9f4ce6c3e771fa5ba284daa42828a9ce6Timo Sirainen struct foo *foo = array_idx(bars, 0);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen#define p_array_init(array, pool, init_count) \
11a29a16c8b41ad7c057420e53963a4595adc33dTimo Sirainen array_create(array, pool, sizeof(**(array)->v), init_count)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen p_array_init(array, pool_datastack_create(), init_count)
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen/* usage: struct foo *foo; array_foreach(foo_arr, foo) { .. } */
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L)
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen (const char *)(elem = *(array)->v) + (array)->arr.buffer->used; \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen# define array_foreach_modifiable(array, elem) \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen (const char *)(elem = ARRAY_TYPE_CAST_MODIFIABLE(array) \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen buffer_get_modifiable_data((array)->arr.buffer, NULL)) + \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen elem != CONST_PTR_OFFSET(*(array)->v, (array)->arr.buffer->used); \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen# define array_foreach_modifiable(array, elem) \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen for (elem = ARRAY_TYPE_CAST_MODIFIABLE(array) \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen buffer_get_modifiable_data((array)->arr.buffer, NULL)) + \
1df7543b209cabc208515c6bfc3b123f6ea184c2Timo Sirainen elem != CONST_PTR_OFFSET(*(array)->v, (array)->arr.buffer->used); \
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_create_from_buffer_i(struct array *array, buffer_t *buffer,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen#define array_create_from_buffer(array, buffer, element_size) \
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_create_from_buffer_i(&(array)->arr, buffer, element_size)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_create_i(struct array *array, pool_t pool,
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen buffer = buffer_create_dynamic(pool, init_count * element_size);
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_create_from_buffer_i(array, buffer, element_size);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen#define array_create(array, pool, element_size, init_count) \
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_create_i(&(array)->arr, pool, element_size, init_count)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic inline bool
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_append_i(struct array *array, const void *data, unsigned int count)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen buffer_append(array->buffer, data, count * array->element_size);
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_append_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_append_array_i(struct array *dest_array, const struct array *src_array)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen i_assert(dest_array->element_size == src_array->element_size);
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen buffer_append_buf(dest_array->buffer, src_array->buffer, 0, (size_t)-1);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen#define array_append_array(dest_array, src_array) \
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_append_array_i(&(dest_array)->arr, &(src_array)->arr)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_insert_i(struct array *array, unsigned int idx,
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen buffer_insert(array->buffer, idx * array->element_size,
b046ca519fc1092495691df7256de32a18dc7a17Timo Sirainen#define array_insert(array, idx, data, count) \
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_insert_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_delete_i(struct array *array, unsigned int idx, unsigned int count)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen buffer_delete(array->buffer, idx * array->element_size,
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline const void *
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_get_i(const struct array *array, unsigned int *count_r)
c6eca51b54586c1f37cfe39e38c844da3f937a4dTimo Sirainen *count_r = array->buffer->used / array->element_size;
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen ARRAY_TYPE_CAST_CONST(array)array_get_i(&(array)->arr, count)
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstatic inline const void * ATTR_PURE
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_idx_i(const struct array *array, unsigned int idx)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen i_assert(idx * array->element_size < array->buffer->used);
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen return CONST_PTR_OFFSET(array->buffer->data, idx * array->element_size);
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen ARRAY_TYPE_CAST_CONST(array)array_idx_i(&(array)->arr, idx)
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void *
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainenarray_get_modifiable_i(struct array *array, unsigned int *count_r)
c6eca51b54586c1f37cfe39e38c844da3f937a4dTimo Sirainen *count_r = array->buffer->used / array->element_size;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return buffer_get_modifiable_data(array->buffer, NULL);
aa181b6e3751d4e76da6f135729032660b14406cTimo Sirainenvoid *array_idx_modifiable_i(struct array *array, unsigned int idx);
aa181b6e3751d4e76da6f135729032660b14406cTimo Sirainenvoid array_idx_set_i(struct array *array, unsigned int idx, const void *data);
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen array_idx_set_i(&(array)->arr + ARRAY_TYPE_CHECK(array, data), \
aa181b6e3751d4e76da6f135729032660b14406cTimo Sirainenvoid array_idx_clear_i(struct array *array, unsigned int idx);
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainenstatic inline void *
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen data = buffer_append_space_unsafe(array->buffer, array->element_size);
684844265f01abd1da5864647a6dd69cc1bbbc71Timo Sirainen ARRAY_TYPE_CAST_MODIFIABLE(array)array_append_space_i(&(array)->arr)
aa181b6e3751d4e76da6f135729032660b14406cTimo Sirainenvoid *array_insert_space_i(struct array *array, unsigned int idx);
f59e2b09deeb94317342016949592577ef150c1bTimo Sirainenstatic inline void
f59e2b09deeb94317342016949592577ef150c1bTimo Sirainenarray_copy(struct array *dest, unsigned int dest_idx,
f59e2b09deeb94317342016949592577ef150c1bTimo Sirainen const struct array *src, unsigned int src_idx, unsigned int count)
f59e2b09deeb94317342016949592577ef150c1bTimo Sirainen i_assert(dest->element_size == src->element_size);
f59e2b09deeb94317342016949592577ef150c1bTimo Sirainen buffer_copy(dest->buffer, dest_idx * dest->element_size,
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstatic inline unsigned int ATTR_PURE
30972f343b285b6214ea053e1939b92cfe79040cTimo Sirainen return array->buffer->used / array->element_size;
304cda7b78964aeacda7cd5388c7eb2a0be3e31aTimo Sirainenvoid array_sort_i(struct array *array, int (*cmp)(const void *, const void *));
304cda7b78964aeacda7cd5388c7eb2a0be3e31aTimo Sirainen ({(void)(1 ? 0 : cmp(ARRAY_TYPE_CAST_CONST(array)NULL, \
304cda7b78964aeacda7cd5388c7eb2a0be3e31aTimo Sirainen (int (*)(const void *, const void *))cmp); })
304cda7b78964aeacda7cd5388c7eb2a0be3e31aTimo Sirainen array_sort_i(&(array)->arr, (int (*)(const void *, const void *))cmp)
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainenvoid *array_bsearch_i(struct array *array, const void *key,
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen int (*cmp)(const void *, const void *));
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen ({(void)(1 ? 0 : cmp(key, ARRAY_TYPE_CAST_CONST(array)NULL)); \
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen array_bsearch_i(&(array)->arr, (const void *)key, \
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen (int (*)(const void *, const void *))cmp); })
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen array_bsearch_i(&(array)->arr, (const void *)key, \
40252a7eb6030f51dc6436e5b844c8a65890a736Timo Sirainen (int (*)(const void *, const void *))cmp)