array.h revision 2d729323913a672708dc600242e1cc3085985dcc
#ifndef ARRAY_H
#define ARRAY_H
/* Array is a buffer accessible using fixed size elements. As long as the
compiler provides a typeof() operator, the array provides type safety. If
a wrong type is tried to be added to the array, or if the array's contents
are tried to be used using a wrong type, the compiler will give a warning.
Example usage:
struct foo {
ARRAY(struct bar) bars;
...
};
i_array_init(&foo->bars, 10);
struct bar *bar = array_idx(&foo->bars, 5);
struct baz *baz = array_idx(&foo->bars, 5); // compiler warning
If you want to pass an array as a parameter to a function, you'll need to
create a type for the array using ARRAY_DEFINE_TYPE() and use the type in
the parameter using ARRAY_TYPE(). Any arrays that you want to be passing
around, such as structure members as in the above example, must also be
defined using ARRAY_TYPE() too, rather than ARRAY().
Example:
ARRAY_DEFINE_TYPE(foo, struct foo);
void do_foo(ARRAY_TYPE(foo) *foos) {
struct foo *foo = array_idx(foos, 0);
}
struct foo_manager {
ARRAY_TYPE(foo) foos; // pedantically, ARRAY(struct foo) is a different type
};
// ...
do_foo(&my_foo_manager->foos); // No compiler warning about mismatched types
*/
#include "array-decl.h"
#include "buffer.h"
#ifdef HAVE_TYPEOF
# define ARRAY_TYPE_CAST_CONST(array) \
# define ARRAY_TYPE_CAST_MODIFIABLE(array) \
#else
# define ARRAY_TYPE_CAST_CONST(array)
# define ARRAY_TYPE_CAST_MODIFIABLE(array)
#endif
/* usage: struct foo *foo; array_foreach(foo_arr, foo) { .. } */
for (const void *elem ## __foreach_end = \
/* Bikeshed: which is better
array_foreach_elem(array, myvar) { ... use myvar ... } // not clear myvar is modified
array_foreach_elem(array, &myvar) { ... use myvar ... } // clearer, as more pass-by-referencey
Latter is impossible if we want to use the variable name as the base for the other variable names
*/
; \
; \
_foreach_offset += sizeof(elem) \
)
#else
(elem)++)
(elem)++)
#endif
static inline void
{
}
static inline void
{
}
static inline void
{
}
#define array_free(array) \
static inline bool
{
}
#define array_is_created(array) \
{
}
#define array_get_pool(array) \
static inline void
{
}
#define array_clear(array) \
static inline unsigned int ATTR_PURE
{
}
#define array_count(array) \
/* No need for the real count if all we're doing is comparing againts 0 */
#define array_is_empty(array) \
#define array_not_empty(array) \
static inline void
{
}
static inline void
{
}
static inline void
{
}
static inline void
{
}
static inline const void *
{
}
/* Re: i_assert() vs. pure: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51971#c1 */
static inline const void * ATTR_PURE
{
}
static inline void *
{
}
static inline void *
{
void *data;
return data;
}
#define array_append_space(array) \
#define array_append_zero(array) \
static inline void
{
}
/* Exchange ownership of two arrays, which should have been allocated
replacement. Can also do it with uninitialised arrays (which will
have .element_size == 0). */
static inline void
{
}
/* Test equality via a comparator */
(int (*)(const void *, const void *))cmp)
int (*cmp)(const void*, const void *, const void *),
/* Same, but with a context pointer.
context can't be void* as ``const typeof(context)'' won't compile,
so ``const typeof(*context)*'' is required instead, and that requires a
complete type. */
(int (*)(const void *, const void *, const void *))cmp, \
ctx)
#define array_reverse(array) \
(int (*)(const void *, const void *))cmp)
int (*cmp)(const void *, const void *));
/* Returns pointer to first element for which cmp(key,elem)==0, or NULL */
int (*cmp)(const void *, const void *));
int (*cmp)(const void *, const void *))
{
}
array_lsearch##modifiable##i( \
(const void *)key, \
(int (*)(const void *, const void *))cmp)
#endif