1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
#include "../include/al/lib.h"
#include "../include/al/macros.h"
#include "../include/al/array_sort.h"
// Initially based on XV by Kang Seonghoon.
// https://github.com/lifthrasiir/angolmois/blob/master/angolmois.c#L79
// https://gist.github.com/lifthrasiir/4422136
#define array(type) \
struct { \
u32 count; \
u32 alloc; \
type *__sized_by(alloc) data; \
}
#define AL_ARRAY_NO_INDEX ((u32)-1)
#define al_array_init(array) ((array).count = 0, (array).alloc = 0, (array).data = NULL)
#define al_array_at(array, i) ((array).data[i])
#define al_array_last(array) al_array_at(array, (array).count - 1)
#define al_array_offset(array, n) ((array).data + (n))
#define al_array_item_size(array) sizeof(*(array).data) // NOLINT(bugprone-sizeof-expression)
#define al_array_reserve(array, count) \
((array).alloc = _al_array_reserve((void **)&(array).data, (array).alloc, ((count) * al_array_item_size(array))))
#define al_array_copy(dest, src) \
do { \
al_array_reserve(dest, (src).count); \
(dest).count = (src).count; \
al_memcpy(al_array_offset(dest, 0), al_array_offset(src, 0), \
al_array_item_size(dest) * (dest).count); \
} while (0)
#define al_array_push(array, item) \
do { \
al_array_reserve(array, (array).count + 1); \
al_array_at(array, (array).count++) = item; \
} while (0)
#define al_array_insert(array, i, item) \
do { \
al_array_reserve(array, (array).count + 1); \
if (i != (array).count - 1) { \
al_memmove(al_array_offset(array, i + 1), al_array_offset(array, i), \
al_array_item_size(array) * ((array).count - i)); \
} \
(array).count++; \
al_array_at(array, i) = item; \
} while (0)
#define al_array_pop(array) al_array_at(array, --(array).count)
#define al_array_pop_at(array, i, r) \
do { \
r = al_array_at(array, i); \
al_array_remove_at(array, i); \
} while (0)
#define al_array_remove_at(array, i) \
do { \
if (i == (array).count - 1) { \
(array).count--; \
} else { \
al_memmove(al_array_offset(array, i), al_array_offset(array, i + 1), \
al_array_item_size(array) * (--(array).count - i)); \
} \
} while (0)
#define al_array_remove_range(array, start, end) \
do { \
if (end != (array).count) { \
al_memmove(al_array_offset(array, start), al_array_offset(array, end), \
al_array_item_size(array) * ((array).count - end)); \
} \
(array).count -= end - start; \
} while (0)
#ifdef AL_HAVE_GNU_EXTENSIONS
#define al_array_contains(array, needle) \
({ \
bool was_contained = false; \
for (u32 ic = 0; ic < (array).count; ic++) { \
if (al_array_at(array, ic) == needle) { \
was_contained = true; \
break; \
} \
} \
was_contained; \
})
#define al_array_remove(array, elem) \
({ \
bool did_remove = false; \
for (u32 ir = 0; ir < (array).count; ir++) { \
if (al_array_at(array, ir) == elem) { \
al_array_remove_at(array, ir); \
did_remove = true; \
break; \
} \
} \
did_remove; \
})
#define al_array_remove_all(array, elem) \
({ \
bool did_remove = false; \
for (u32 ir = (array).count; ir-- > 0;) { \
if (al_array_at(array, ir) == elem) { \
al_array_remove_at(array, ir); \
did_remove = true; \
} \
} \
did_remove; \
})
#endif
#ifdef AL_USE_STDLIB
#define al_array_sort(array, type, cmp) AL_STDLIB_QSORT((array).data, type, (array).count, cmp)
#else
#define al_array_sort(array, type, cmp) AL_INSERSION_SORT((array).data, type, (array).count, cmp)
#endif
#define al_array_free(array) \
if ((array).alloc) AL_ARRAY_FREE((array).data)
#define al_array_foreach(array, i, item) \
for (u32 i = 0; (i < (array).count && (item = al_array_at(array, i), 1)); i++)
#define al_array_foreach_rev(array, i, item) \
for (u32 i = (array).count; (i-- > 0 && (item = al_array_at(array, i), 1));)
#define al_array_foreach_ptr(array, i, item) \
for (u32 i = 0; (i < (array).count && (item = al_array_offset(array, i), 1)); i++)
#define al_array_foreach_ptr_rev(array, i, item) \
for (u32 i = (array).count; (i-- > 0 && (item = al_array_offset(array, i), 1));)
#define al_array_remove_at_iter(array, i) \
do { \
al_array_remove_at(array, i); \
i--; \
} while (0)
static inline u32 _al_array_reserve(void **ptr, u32 prev_size, u32 size)
{
return al_growing_allocation(ptr, prev_size, size, AL_ARRAY_REALLOC);
}
|