Thanks to visit codestin.com
Credit goes to code.neomutt.org

NeoMutt  2025-12-11-189-gceedb6
Teaching an old dog new tricks
DOXYGEN
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 management wrappers.