#ifndef COSMOPOLITAN_LIBC_ALG_ARRAYLIST2_H_ #define COSMOPOLITAN_LIBC_ALG_ARRAYLIST2_H_ #include "libc/mem/mem.h" #include "libc/str/str.h" #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ /* TODO(jart): Fully develop these better macros. */ #define APPEND(LIST_P, LIST_I, LIST_N, ITEM) \ CONCAT(LIST_P, LIST_I, LIST_N, ITEM, 1) #define CONCAT(LIST_P, LIST_I, LIST_N, ITEM, COUNT) \ ({ \ autotype(LIST_P) ListP = (LIST_P); \ autotype(LIST_I) ListI = (LIST_I); \ autotype(LIST_N) ListN = (LIST_N); \ typeof(&(*ListP)[0]) Item = (ITEM); \ size_t SizE = sizeof(*Item); \ size_t Count = (COUNT); \ ssize_t Entry = -1; \ /* NOTE: We use `<` to guarantee one additional slot */ \ /* grow() will memset(0) extended memory, thus */ \ /* you get a nul-terminator for free sometimes */ \ /* the exception is if you list.i=0 and re-use */ \ /* so you need concat(...); list.p[list.i++]=0 */ \ if (*ListI + Count < *ListN || grow(ListP, ListN, SizE, Count)) { \ memcpy(&(*ListP)[*ListI], Item, (SizE) * (Count)); \ Entry = *ListI; \ *ListI += Count; /* happens after copy in case signal */ \ } \ Entry; \ }) COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_ALG_ARRAYLIST2_H_ */