#pragma once #include #include "scoped.h" #define ARRAY_LIST_EMPTY ((struct array_list) { NULL, 0, 0 }) struct array_list { void *buf; size_t len; size_t cap; }; int array_list_raw_alloc(struct array_list *al, size_t cap, size_t elem_size); void array_list_raw_cleanup(struct array_list *al); #define DEF_ARRAY_LIST_TYPE(NAME, TYPE, UNOCCUPIED, CLEANUP_FN) \ static inline TYPE *array_list_##NAME##_get(struct array_list *al, size_t i) { \ if (i >= al->len) \ return NULL; \ return &((TYPE *)al->buf)[i]; \ } \ static inline const TYPE *array_list_##NAME##_cget(const struct array_list *al, size_t i) { \ if (i >= al->len) \ return NULL; \ return &((const TYPE *)al->buf)[i]; \ } \ static inline void array_list_##NAME##_cleanup(struct array_list *al) { \ size_t i; \ for (i = 0; i < al->len; i++) \ CLEANUP_FN(array_list_##NAME##_get(al, i)); \ array_list_raw_cleanup(al); \ } \ static inline int array_list_##NAME##_alloc(struct array_list *al, size_t cap) { \ size_t i; \ if (cap < al->len) { \ for (i = cap; i < al->len; i++) \ CLEANUP_FN(array_list_##NAME##_get(al, i)); \ al->len = cap; \ } \ return array_list_raw_alloc(al, cap, sizeof(TYPE)); \ } \ static inline int array_list_##NAME##_push_noalloc_byval(struct array_list *al, TYPE elem) { \ if (al->len >= al->cap) \ return -1; \ ((TYPE *)al->buf)[al->len++] = elem; \ return 0; \ } \ DEF_SCOPED_TYPE( \ array_list_##NAME, \ struct array_list, \ ARRAY_LIST_EMPTY, \ array_list_##NAME##_cleanup)