NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
array.h
Go to the documentation of this file.
1 
29 #include <stdbool.h>
30 #include <string.h>
31 #include "memory.h"
32 
36 #define ARRAY_HEADROOM 25
37 
43 #define ARRAY_HEAD(name, type) \
44  struct name \
45  { \
46  size_t size; \
47  size_t capacity; \
48  type *entries; \
49  }
50 
54 #define ARRAY_HEAD_INITIALIZER \
55  { 0, 0, NULL }
56 
61 #define ARRAY_INIT(head) \
62  memset((head), 0, sizeof(*(head)))
63 
70 #define ARRAY_EMPTY(head) \
71  ((head)->size == 0)
72 
83 #define ARRAY_SIZE(head) \
84  ((head)->size)
85 
91 #define ARRAY_CAPACITY(head) \
92  ((head)->capacity)
93 
105 #define ARRAY_GET(head, idx) \
106  ((head)->size > (idx) ? &(head)->entries[(idx)] : NULL)
107 
119 #define ARRAY_SET(head, idx, elem) \
120  (((head)->capacity > (idx) \
121  ? true \
122  : ARRAY_RESERVE((head), (idx) + 1)), \
123  ARRAY_SET_NORESERVE((head), (idx), (elem)))
124 
131 #define ARRAY_FIRST(head) \
132  ARRAY_GET((head), 0)
133 
140 #define ARRAY_LAST(head) \
141  (ARRAY_EMPTY((head)) \
142  ? NULL \
143  : ARRAY_GET((head), ARRAY_SIZE((head)) - 1))
144 
152 #define ARRAY_ADD(head, elem) \
153  (((head)->capacity > (head)->size \
154  ? true \
155  : ARRAY_RESERVE((head), (head)->size + 1)), \
156  ARRAY_ADD_NORESERVE((head), (elem)))
157 
168 #define ARRAY_SHRINK(head, num) \
169  ((head)->size -= MIN((num), (head)->size))
170 
176 #define ARRAY_ELEM_SIZE(head) \
177  (sizeof(*(head)->entries))
178 
185 #define ARRAY_RESERVE(head, num) \
186  (((head)->capacity > (num)) ? \
187  (head)->capacity : \
188  ((mutt_mem_realloc(&(head)->entries, ((num) + ARRAY_HEADROOM) * ARRAY_ELEM_SIZE(head))), \
189  (memset((head)->entries + (head)->capacity, 0, \
190  ((num) + ARRAY_HEADROOM - (head)->capacity) * ARRAY_ELEM_SIZE(head))), \
191  ((head)->capacity = (num) + ARRAY_HEADROOM)))
192 
198 #define ARRAY_FREE(head) \
199  (FREE(&(head)->entries), (head)->size = (head)->capacity = 0)
200 
206 #define ARRAY_FOREACH(elem, head) \
207  ARRAY_FOREACH_FROM_TO((elem), (head), 0, (head)->size)
208 
217 #define ARRAY_FOREACH_FROM(elem, head, from) \
218  ARRAY_FOREACH_FROM_TO((elem), (head), (from), (head)->size)
219 
228 #define ARRAY_FOREACH_TO(elem, head, to) \
229  ARRAY_FOREACH_FROM_TO((elem), (head), 0, (to))
230 
241 #define ARRAY_FOREACH_FROM_TO(elem, head, from, to) \
242  for (size_t ARRAY_FOREACH_IDX = (from); \
243  (ARRAY_FOREACH_IDX < (to)) && \
244  ((elem) = ARRAY_GET((head), ARRAY_FOREACH_IDX)); \
245  ARRAY_FOREACH_IDX++)
246 
253 #define ARRAY_IDX(head, elem) \
254  (elem - (head)->entries)
255 
261 #define ARRAY_REMOVE(head, elem) \
262  (memmove((elem), (elem) + 1, \
263  ARRAY_ELEM_SIZE((head)) * (ARRAY_SIZE((head)) - ARRAY_IDX((head), (elem)))), \
264  ARRAY_SHRINK((head), 1))
265 
271 #define ARRAY_SORT(head, fn) \
272  qsort((head)->entries, ARRAY_SIZE(head), ARRAY_ELEM_SIZE(head), (fn))
273 
274 /******************************************************************************
275  * Internal APIs
276  *****************************************************************************/
277 #define ARRAY_SET_NORESERVE(head, idx, elem) \
278  ((head)->capacity > (idx) \
279  ? (((head)->size = MAX((head)->size, ((idx) + 1))), \
280  ((head)->entries[(idx)] = (elem)), \
281  true) \
282  : false)
283 
284 #define ARRAY_ADD_NORESERVE(head, elem) \
285  ((head)->capacity > (head)->size \
286  ? (((head)->entries[(head)->size++] = (elem)), \
287  true) \
288  : false)
289 
Memory management wrappers.