1 // Copyright © Tavian Barnes <tavianator@tavianator.com>
2 // SPDX-License-Identifier: 0BSD
12 /** The current capacity of the array, as a count of elements. */
14 /** The current length of the array. */
17 // The array elements are stored after this header in memory. Not using
18 // a flexible array member to avoid worrying about strict aliasing. We
19 // assume that 2*sizeof(size_t) keeps any memory allocation suitably
20 // aligned for the element type.
23 /** Get the header for a darray. */
24 static struct darray *darray_header(const void *da) {
25 return (struct darray *)da - 1;
28 /** Get the array from a darray header. */
29 static char *darray_data(struct darray *header) {
30 return (char *)(header + 1);
33 size_t darray_length(const void *da) {
35 return darray_header(da)->length;
41 void *darray_push(void *da, const void *item, size_t size) {
42 struct darray *header;
44 header = darray_header(da);
46 header = malloc(sizeof(*header) + size);
54 size_t capacity = header->capacity;
55 size_t i = header->length++;
58 header = realloc(header, sizeof(*header) + capacity * size);
60 // This failure will be detected by darray_check()
63 header->capacity = capacity;
66 char *data = darray_data(header);
67 memcpy(data + i * size, item, size);
71 int darray_check(void *da) {
76 struct darray *header = darray_header(da);
77 if (header->length <= header->capacity) {
80 // realloc() failed in darray_push(), so reset the length and report the failure
81 header->length = header->capacity;
86 void darray_free(void *da) {
88 free(darray_header(da));