NeoMutt
2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Toggle main menu visibility
Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1
23
29
30
#ifndef MUTT_MUTT_ARRAY_H
31
#define MUTT_MUTT_ARRAY_H
32
33
#include <stdbool.h>
34
#include <string.h>
35
#include "
memory.h
"
36
40
#define ARRAY_HEADROOM 25
41
47
#define ARRAY_HEAD(name, T) \
48
struct name \
49
{ \
50
int size;
\
51
int capacity;
\
52
T *entries;
\
53
}
54
58
#define ARRAY_HEAD_INITIALIZER \
59
{ 0, 0, NULL }
60
65
#define ARRAY_INIT(head) \
66
memset((head), 0, sizeof(*(head)))
67
74
#define ARRAY_EMPTY(head) \
75
((head)->size == 0)
76
87
#define ARRAY_SIZE(head) \
88
((head)->size)
89
95
#define ARRAY_CAPACITY(head) \
96
((head)->capacity)
97
109
#define ARRAY_GET(head, idx) \
110
(((idx) >= 0) && ((head)->size > (idx)) ? &(head)->entries[(idx)] : NULL)
111
123
#define ARRAY_SET(head, idx, elem) \
124
({ \
125
if ((head)->capacity <= (idx)) \
126
ARRAY_RESERVE(head, (idx) + 1); \
127
ARRAY_SET_NORESERVE(head, idx, elem); \
128
})
129
136
#define ARRAY_FIRST(head) \
137
ARRAY_GET(head, 0)
138
145
#define ARRAY_LAST(head) \
146
(ARRAY_EMPTY(head) \
147
? NULL \
148
: ARRAY_GET(head, ARRAY_SIZE(head) - 1))
149
157
#define ARRAY_ADD(head, elem) \
158
({ \
159
if ((head)->capacity <= (head)->size) \
160
ARRAY_RESERVE(head, (head)->size + 1); \
161
ARRAY_ADD_NORESERVE(head, elem); \
162
})
163
174
#define ARRAY_SHRINK(head, n) \
175
((head)->size -= MIN(n, (head)->size))
176
182
#define ARRAY_ELEM_SIZE(head) \
183
(sizeof(*(head)->entries))
184
191
#define ARRAY_RESERVE(head, n) \
192
({ \
193
if ((head)->capacity < (n)) \
194
{ \
195
mutt_mem_reallocarray(&(head)->entries, \
196
(n) + ARRAY_HEADROOM, \
197
ARRAY_ELEM_SIZE(head)); \
198
memset((head)->entries + (head)->capacity, 0, \
199
((n) + ARRAY_HEADROOM - (head)->capacity) * ARRAY_ELEM_SIZE(head)); \
200
(head)->capacity = (n) + ARRAY_HEADROOM; \
201
} \
202
(head)->capacity; \
203
})
204
209
#define ARRAY_FREE(head) \
210
do \
211
{ \
212
FREE(&(head)->entries); \
213
(head)->size = (head)->capacity = 0; \
214
} while (0)
215
223
#define ARRAY_FOREACH(elem, head) \
224
ARRAY_FOREACH_FROM_TO(elem, head, 0, (head)->size)
225
235
#define ARRAY_FOREACH_FROM(elem, head, from) \
236
ARRAY_FOREACH_FROM_TO(elem, head, from, (head)->size)
237
247
#define ARRAY_FOREACH_TO(elem, head, to) \
248
ARRAY_FOREACH_FROM_TO(elem, head, 0, to)
249
261
#define ARRAY_FOREACH_FROM_TO(elem, head, from, to) \
262
for (int ARRAY_FOREACH_IDX_##elem = (from); \
263
(ARRAY_FOREACH_IDX_##elem < (to)) && \
264
((elem) = ARRAY_GET(head, ARRAY_FOREACH_IDX_##elem)); \
265
ARRAY_FOREACH_IDX_##elem++)
266
274
#define ARRAY_FOREACH_REVERSE(elem, head) \
275
ARRAY_FOREACH_REVERSE_FROM_TO(elem, head, (head)->size, 0)
276
286
#define ARRAY_FOREACH_REVERSE_FROM(elem, head, from) \
287
ARRAY_FOREACH_REVERSE_FROM_TO(elem, head, from, 0)
288
298
#define ARRAY_FOREACH_REVERSE_TO(elem, head, to) \
299
ARRAY_FOREACH_REVERSE_FROM_TO(elem, head, (head)->size, to)
300
312
#define ARRAY_FOREACH_REVERSE_FROM_TO(elem, head, from, to) \
313
for (int ARRAY_FOREACH_IDX_##elem = (from) - 1; \
314
(ARRAY_FOREACH_IDX_##elem >= (to)) && \
315
((elem) = ARRAY_GET(head, ARRAY_FOREACH_IDX_##elem)); \
316
ARRAY_FOREACH_IDX_##elem--)
317
324
#define ARRAY_IDX(head, elem) \
325
((elem) - (head)->entries)
326
338
#define ARRAY_INSERT(head, idx, elem) \
339
(((head)->capacity > (head)->size \
340
? true \
341
: ARRAY_RESERVE((head), (head)->size + 1)), \
342
((idx) <= (head)->size \
343
? (memmove(&(head)->entries[(idx) + 1], &(head)->entries[(idx)], \
344
ARRAY_ELEM_SIZE((head)) * ((head)->size - (idx))), \
345
(head)->entries[(idx)] = (elem), \
346
(head)->size++, \
347
true) \
348
: false))
349
355
#define ARRAY_REMOVE(head, elem) \
356
do \
357
{ \
358
if (ARRAY_SIZE(head) > ARRAY_IDX(head, elem) + 1) \
359
{ \
360
memmove(elem, (elem) + 1, \
361
ARRAY_ELEM_SIZE(head) * \
362
(ARRAY_SIZE(head) - ARRAY_IDX(head, elem) - 1)); \
363
} \
364
ARRAY_SHRINK(head, 1); \
365
} while (0)
366
373
#define ARRAY_SORT(head, fn, sdata) \
374
({ \
375
if ((head)->entries != NULL) \
376
mutt_qsort_r((head)->entries, ARRAY_SIZE(head), ARRAY_ELEM_SIZE(head), fn, sdata);\
377
!!(head)->entries; \
378
})
379
380
/******************************************************************************
381
* Internal APIs
382
*****************************************************************************/
383
#define ARRAY_SET_NORESERVE(head, idx, elem) \
384
({ \
385
if ((head)->capacity > (idx)) \
386
{ \
387
(head)->size = MAX((head)->size, (idx) + 1); \
388
(head)->entries[(idx)] = (elem); \
389
} \
390
(head)->capacity > (idx); \
391
})
392
393
#ifndef __COVERITY__
394
#define __coverity_escape__(x) 0
395
#endif
396
#define ARRAY_ADD_NORESERVE(head, elem) \
397
((head)->capacity > (head)->size \
398
? (((head)->entries[(head)->size++] = (elem)), \
399
((void)__coverity_escape__(elem), true)) \
400
: ((void)__coverity_escape__(elem), false))
401
402
#endif
/* MUTT_MUTT_ARRAY_H */
memory.h
Memory management wrappers.