O2 2.0
A communication protocol for interactive music and media applications.
dynarray.h
1/* dynarray.h -- generic dynamic arrays */
2#ifndef dynarray_h
3#define dynarray_h
4
5typedef struct dyn_array {
6 int32_t allocated;
7 int32_t length;
8 char *array;
10
11/* initialize a dynamic array. typ is the type of each element,
12 siz is the initial space allocated (number of elements). The
13 initial length is 0 */
14#define DA_INIT(a, typ, siz) { \
15 (a).allocated = (siz); \
16 (a).length = 0; \
17 (a).array = ((siz) > 0 ? (char *) O2_MALLOCNT((siz), typ) : NULL); }
18
19#define DA_ZERO(a, typ) \
20 memset((a).array, 0, sizeof(typ) * (a).allocated)
21
22
23#define DA_INIT_ZERO(a, typ, siz) { \
24 DA_INIT(a, typ, siz); \
25 o2_mem_check((a).array); \
26 DA_ZERO(a, typ); }
27
28/* get a pointer to the first item of array. The type of
29 each element is typ. */
30#define DA(a, typ) (o2_mem_check((a).array), (typ *) ((a).array))
31
32/* get an element from a dynamic array */
33#define DA_GET(a, typ, index) \
34 (assert(DA_CHECK(a, index)), DA(a, typ)[index])
35
36/* get address of element in a dynamic array
37 * I would like to write &DA_GET(...), but with bounds checking,
38 * DA_GET() does not return an rvalue, i.e. you cannot take the
39 * address of (assert(in_bounds), DA(...)[index]), so we have
40 * this variant of the macro that takes the address directly:
41 */
42#define DA_GET_ADDR(a, typ, index) \
43 (assert(DA_CHECK(a, index)), &DA(a, typ)[index])
44
45/* get the last element. Assumes length > 0. */
46#define DA_LAST(a, typ) DA_GET(a, typ, (a).length - 1)
47
48/* get the address of the last element */
49#define DA_LAST_ADDR(a, typ) DA_GET_ADDR(a, typ, (a).length - 1)
50
51/* set an array element at index to data. typ is the type of
52 each element in array. */
53#define DA_SET(a, typ, index, data) \
54 (*DA_GET_ADDR(a, typ, index) = (data))
55
56/* return if index of a dynamic array is in bounds */
57#define DA_CHECK(a, index) \
58 ((index) >= 0 && (index) < (a).length)
59
60/* make sure there is room for at least one more element, and increase
61 the length by one. Caller should immediately assign a value to the
62 last element */
63#define DA_EXPAND(a, typ) \
64 ((((a).length + 1 > (a).allocated) ? \
65 o2_da_expand(&(a), sizeof(typ)) : NULL), \
66 &DA(a, typ)[(a).length++]) // return new element address
67
68/* append data (of type typ) to the dynamic array */
69#define DA_APPEND(a, typ, data) { \
70 *(DA_EXPAND(a, typ)) = (data); }
71
72/* remove an element at index i, replacing with last */
73#define DA_REMOVE(a, typ, i) { \
74 DA_SET(a, typ, i, DA_LAST(a, typ)); \
75 (a).length--; }
76
77
78#define DA_FINISH(a) { (a).length = (a).allocated = 0; \
79 if ((a).array) O2_FREE((a).array); (a).array = NULL; }
80
81void *o2_da_expand(dyn_array_ptr array, int siz);
82
83#endif /* dynarray_h */
Definition: dynarray.h:5