Graphviz 16.1.1~dev.20260926.2046
Loading...
Searching...
No Matches
list.h
Go to the documentation of this file.
1
34
35#pragma once
36
37#include <assert.h>
38#include <stdint.h>
39#include <string.h>
40#include <util/list-private.h>
41#include <util/typeof.h>
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
47static_assert(
48 offsetof(list_t_, base) == 0,
49 "LIST(<type>).base and LIST(<type>).impl.base will not alias each other");
50
56#ifdef TYPEOF
57#define LIST(type) \
58 struct { \
59 union { \
60 type *base; \
61 list_t_ impl; \
62 }; \
63 void (*dtor)(type); \
64 }
65#else
66#define LIST(type) \
67 struct { \
68 union { \
69 type *base; \
70 list_t_ impl; \
71 }; \
72 void (*dtor)(type); \
73 type scratch; \
74 }
75#endif
76
82#define LIST_DTOR_FREE ((void *)1)
83
92#define LIST_SIZE(list) gv_list_size_((list)->impl)
93
102#define LIST_IS_EMPTY(list) (LIST_SIZE(list) == 0)
103
113#ifdef TYPEOF
114#define LIST_TRY_APPEND(list, item) \
115 gv_list_try_append_(&(list)->impl, (TYPEOF((list)->base[0])[1]){item}, \
116 sizeof((list)->base[0]))
117#else
118#define LIST_TRY_APPEND(list, item) \
119 gv_list_try_append_(&(list)->impl, \
120 ((list)->scratch = (item), &(list)->scratch), \
121 sizeof((list)->base[0]))
122#endif
123
142#ifdef TYPEOF
143#define LIST_APPEND(list, ...) \
144 do { \
145 TYPEOF((list)->base[0]) scratch_ = (__VA_ARGS__); \
146 const size_t slot_ = \
147 gv_list_append_slot_(&(list)->impl, sizeof((list)->base[0])); \
148 (list)->base[slot_] = scratch_; \
149 } while (0)
150#else
151#define LIST_APPEND(list, ...) \
152 do { \
153 (list)->scratch = (__VA_ARGS__); \
154 const size_t slot_ = \
155 gv_list_append_slot_(&(list)->impl, sizeof((list)->base[0])); \
156 (list)->base[slot_] = (list)->scratch; \
157 } while (0)
158#endif
159
170#ifdef TYPEOF
171#define LIST_PREPEND(list, item) \
172 do { \
173 TYPEOF((list)->base[0]) scratch_ = (item); \
174 const size_t slot_ = \
175 gv_list_prepend_slot_(&(list)->impl, sizeof((list)->base[0])); \
176 (list)->base[slot_] = scratch_; \
177 } while (0)
178#else
179#define LIST_PREPEND(list, item) \
180 do { \
181 (list)->scratch = (item); \
182 const size_t slot_ = \
183 gv_list_prepend_slot_(&(list)->impl, sizeof((list)->base[0])); \
184 (list)->base[slot_] = (list)->scratch; \
185 } while (0)
186#endif
187
197#define LIST_GET(list, index) \
198 ((list)->base[gv_list_get_((list)->impl, (index))])
199
210#define LIST_AT(list, index) \
211 (&(list)->base[gv_list_get_((list)->impl, (index))])
212
222#define LIST_FRONT(list) LIST_AT((list), 0)
223
233#define LIST_BACK(list) LIST_AT((list), LIST_SIZE(list) - 1)
234
244#ifdef TYPEOF
245#define LIST_SET(list, index, item) \
246 do { \
247 TYPEOF((list)->base[0]) scratch_ = (item); \
248 const size_t slot_ = gv_list_get_((list)->impl, (index)); \
249 LIST_DTOR_((list), slot_); \
250 (list)->base[slot_] = scratch_; \
251 } while (0)
252#else
253#define LIST_SET(list, index, item) \
254 do { \
255 (list)->scratch = (item); \
256 const size_t slot_ = gv_list_get_((list)->impl, (index)); \
257 LIST_DTOR_((list), slot_); \
258 (list)->base[slot_] = (list)->scratch; \
259 } while (0)
260#endif
261
270#ifdef TYPEOF
271#define LIST_REMOVE(list, item) \
272 do { \
273 const size_t found_ = \
274 gv_list_find_((list)->impl, (TYPEOF((list)->base[0])[1]){item}, \
275 sizeof((list)->base[0])); \
276 if (found_ == SIZE_MAX) { /* not found */ \
277 break; \
278 } \
279 \
280 LIST_DTOR_((list), found_); \
281 gv_list_remove_(&(list)->impl, found_, sizeof((list)->base[0])); \
282 } while (0)
283#else
284#define LIST_REMOVE(list, item) \
285 do { \
286 /* get something we can take the address of */ \
287 (list)->scratch = (item); \
288 \
289 const size_t found_ = gv_list_find_((list)->impl, &(list)->scratch, \
290 sizeof((list)->base[0])); \
291 if (found_ == SIZE_MAX) { /* not found */ \
292 break; \
293 } \
294 \
295 LIST_DTOR_((list), found_); \
296 gv_list_remove_(&(list)->impl, found_, sizeof((list)->base[0])); \
297 } while (0)
298#endif
299
307#define LIST_CLEAR(list) \
308 do { \
309 for (size_t i_ = 0; i_ < LIST_SIZE(list); ++i_) { \
310 const size_t slot_ = gv_list_get_((list)->impl, i_); \
311 LIST_DTOR_((list), slot_); \
312 } \
313 gv_list_clear_(&(list)->impl, sizeof((list)->base[0])); \
314 } while (0)
315
324#define LIST_RESERVE(list, capacity) \
325 gv_list_reserve_(&(list)->impl, capacity, sizeof((list)->base[0]))
326
340#define LIST_CONTAINS(list, needle) \
341 gv_list_contains_((list)->impl, \
342 ((void)((list)->base == &(needle)), &(needle)), \
343 sizeof((list)->base[0]))
344
356#define LIST_COPY(list_type, src) \
357 ((list_type){.impl = gv_list_copy_((src)->impl, sizeof((src)->base[0])), \
358 .dtor = (src)->dtor})
359
370#define LIST_SYNC(list) gv_list_sync_(&(list)->impl, sizeof((list)->base[0]))
371
381#define LIST_SORT(list, cmp) \
382 gv_list_sort_(&(list)->impl, (cmp), sizeof((list)->base[0]))
383
391#define LIST_REVERSE(list) \
392 gv_list_reverse_(&(list)->impl, sizeof((list)->base[0]))
393
401#define LIST_SHRINK_TO_FIT(list) \
402 gv_list_shrink_to_fit_(&(list)->impl, sizeof((list)->base[0]))
403
413#define LIST_FREE(list) \
414 do { \
415 LIST_CLEAR(list); \
416 gv_list_free_(&(list)->impl); \
417 } while (0)
418
431#define LIST_PUSH_BACK(list, ...) LIST_APPEND((list), (__VA_ARGS__))
432
441#ifdef TYPEOF
442#define LIST_POP_FRONT(list) \
443 (*(TYPEOF((list)->base))gv_list_pop_front_(&(list)->impl, \
444 (TYPEOF((list)->base[0])[1]){0}, \
445 sizeof((list)->base[0])))
446#else
447#define LIST_POP_FRONT(list) \
448 ((void)gv_list_pop_front_(&(list)->impl, &(list)->scratch, \
449 sizeof((list)->base[0])), \
450 (list)->scratch)
451#endif
452
461#ifdef TYPEOF
462#define LIST_POP_BACK(list) \
463 (*(TYPEOF((list)->base))gv_list_pop_back_(&(list)->impl, \
464 (TYPEOF((list)->base[0])[1]){0}, \
465 sizeof((list)->base[0])))
466#else
467#define LIST_POP_BACK(list) \
468 ((void)gv_list_pop_back_(&(list)->impl, &(list)->scratch, \
469 sizeof((list)->base[0])), \
470 (list)->scratch)
471#endif
472
483#define LIST_DROP_BACK(list) \
484 do { \
485 const size_t slot_ = gv_list_get_((list)->impl, LIST_SIZE(list) - 1); \
486 LIST_DTOR_((list), slot_); \
487 (void)gv_list_pop_back_(&(list)->impl, (char[sizeof((list)->base[0])]){0}, \
488 sizeof((list)->base[0])); \
489 } while (0)
490
504#define LIST_DETACH(list, datap, sizep) \
505 gv_list_detach_(&(list)->impl, ((void)(&(list)->base == (datap)), (datap)), \
506 (sizep), sizeof((list)->base[0]))
507
508#ifdef __cplusplus
509}
510#endif
internal implementation details of list.h
pre-C23 typeof support