#ifndef JNR_DARRAY_H
#define JNR_DARRAY_H

/*
 * Simple type-safe dynamic array using macros.
 *
 * Usage:
 *   DArray(int) nums = {0};
 *   da_push(&nums, 42);
 *   da_push(&nums, 99);
 *   for (int i = 0; i < nums.count; i++) printf("%d\n", nums.items[i]);
 *   da_free(&nums);
 */

#include <stdlib.h>
#include <string.h>

#define DArray(T) struct { T *items; int count; int capacity; }

#define da_push(arr, val) do {                                          \
    if ((arr)->count >= (arr)->capacity) {                              \
        (arr)->capacity = (arr)->capacity ? (arr)->capacity * 2 : 8;   \
        (arr)->items = realloc((arr)->items,                            \
            (arr)->capacity * sizeof(*(arr)->items));                   \
    }                                                                   \
    (arr)->items[(arr)->count++] = (val);                               \
} while (0)

#define da_pop(arr) ((arr)->items[--(arr)->count])

#define da_clear(arr) ((arr)->count = 0)

#define da_free(arr) do {      \
    free((arr)->items);        \
    (arr)->items = NULL;       \
    (arr)->count = 0;          \
    (arr)->capacity = 0;       \
} while (0)

#define da_remove(arr, idx) do {                                        \
    if ((idx) < (arr)->count - 1) {                                    \
        memmove(&(arr)->items[(idx)], &(arr)->items[(idx) + 1],        \
            ((arr)->count - (idx) - 1) * sizeof(*(arr)->items));       \
    }                                                                   \
    (arr)->count--;                                                     \
} while (0)

/* Swap-remove: O(1) but doesn't preserve order */
#define da_remove_fast(arr, idx) do {                                   \
    (arr)->items[(idx)] = (arr)->items[--(arr)->count];                 \
} while (0)

#endif /* JNR_DARRAY_H */
