NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
array.h
Go to the documentation of this file.
1
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, type) \
48 struct name \
49 { \
50 size_t size; \
51 size_t capacity; \
52 type *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 ((head)->size > (idx) ? &(head)->entries[(idx)] : NULL)
111
123#define ARRAY_SET(head, idx, elem) \
124 (((head)->capacity > (idx) \
125 ? true \
126 : ARRAY_RESERVE((head), (idx) + 1)), \
127 ARRAY_SET_NORESERVE((head), (idx), (elem)))
128
135#define ARRAY_FIRST(head) \
136 ARRAY_GET((head), 0)
137
144#define ARRAY_LAST(head) \
145 (ARRAY_EMPTY((head)) \
146 ? NULL \
147 : ARRAY_GET((head), ARRAY_SIZE((head)) - 1))
148
156#define ARRAY_ADD(head, elem) \
157 (((head)->capacity > (head)->size \
158 ? true \
159 : ARRAY_RESERVE((head), (head)->size + 1)), \
160 ARRAY_ADD_NORESERVE((head), (elem)))
161
172#define ARRAY_SHRINK(head, num) \
173 ((head)->size -= MIN((num), (head)->size))
174
180#define ARRAY_ELEM_SIZE(head) \
181 (sizeof(*(head)->entries))
182
189#define ARRAY_RESERVE(head, num) \
190 (((head)->capacity > (num)) ? \
191 (head)->capacity : \
192 ((mutt_mem_realloc( \
193 &(head)->entries, ((num) + ARRAY_HEADROOM) * ARRAY_ELEM_SIZE(head))), \
194 (memset((head)->entries + (head)->capacity, 0, \
195 ((num) + ARRAY_HEADROOM - (head)->capacity) * \
196 ARRAY_ELEM_SIZE(head))), \
197 ((head)->capacity = (num) + ARRAY_HEADROOM)))
198
204#define ARRAY_FREE(head) \
205 (FREE(&(head)->entries), (head)->size = (head)->capacity = 0)
206
212#define ARRAY_FOREACH(elem, head) \
213 ARRAY_FOREACH_FROM_TO((elem), (head), 0, (head)->size)
214
223#define ARRAY_FOREACH_FROM(elem, head, from) \
224 ARRAY_FOREACH_FROM_TO((elem), (head), (from), (head)->size)
225
234#define ARRAY_FOREACH_TO(elem, head, to) \
235 ARRAY_FOREACH_FROM_TO((elem), (head), 0, (to))
236
247#define ARRAY_FOREACH_FROM_TO(elem, head, from, to) \
248 for (size_t ARRAY_FOREACH_IDX = (from); \
249 (ARRAY_FOREACH_IDX < (to)) && \
250 ((elem) = ARRAY_GET((head), ARRAY_FOREACH_IDX)); \
251 ARRAY_FOREACH_IDX++)
252
259#define ARRAY_IDX(head, elem) \
260 (elem - (head)->entries)
261
267#define ARRAY_REMOVE(head, elem) \
268 (memmove((elem), (elem) + 1, \
269 ARRAY_ELEM_SIZE((head)) * \
270 MAX(0, (ARRAY_SIZE((head)) - ARRAY_IDX((head), (elem)) - 1))), \
271 ARRAY_SHRINK((head), 1))
272
279#define ARRAY_SORT(head, fn, sdata) \
280 ((head)->entries && \
281 (mutt_qsort_r((head)->entries, ARRAY_SIZE(head), ARRAY_ELEM_SIZE(head), (fn), (sdata)), true))
282
283/******************************************************************************
284 * Internal APIs
285 *****************************************************************************/
286#define ARRAY_SET_NORESERVE(head, idx, elem) \
287 ((head)->capacity > (idx) \
288 ? (((head)->size = MAX((head)->size, ((idx) + 1))), \
289 ((head)->entries[(idx)] = (elem)), \
290 true) \
291 : false)
292
293#ifndef __COVERITY__
294#define __coverity_escape__(x) 0
295#endif
296#define ARRAY_ADD_NORESERVE(head, elem) \
297 ((head)->capacity > (head)->size \
298 ? (((head)->entries[(head)->size++] = (elem)), \
299 ((void)__coverity_escape__(elem), true)) \
300 : ((void)__coverity_escape__(elem), false))
301
302#endif /* MUTT_MUTT_ARRAY_H */
Memory management wrappers.