38 lines
1.9 KiB
C
38 lines
1.9 KiB
C
#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_ */
|