#include "../include/al/lib.h" #include "../include/al/macros.h" #include "../include/al/array_sort.h" // Initially based on XV by Kang Seonghoon. // https://github.com/lifthrasiir/angolmois/blob/master/angolmois.c#L79 // https://gist.github.com/lifthrasiir/4422136 #define array(type) \ struct { \ u32 count; \ u32 alloc; \ type *__sized_by(alloc) data; \ } #define AL_ARRAY_NO_INDEX ((u32)-1) #define al_array_init(array) ((array).count = 0, (array).alloc = 0, (array).data = NULL) #define al_array_at(array, i) ((array).data[i]) #define al_array_last(array) al_array_at(array, (array).count - 1) #define al_array_offset(array, n) ((array).data + (n)) #define al_array_item_size(array) sizeof(*(array).data) // NOLINT(bugprone-sizeof-expression) #define al_array_reserve(array, count) \ ((array).alloc = _al_array_reserve((void **)&(array).data, (array).alloc, ((count) * al_array_item_size(array)))) #define al_array_copy(dest, src) \ do { \ al_array_reserve(dest, (src).count); \ (dest).count = (src).count; \ al_memcpy(al_array_offset(dest, 0), al_array_offset(src, 0), \ al_array_item_size(dest) * (dest).count); \ } while (0) #define al_array_push(array, item) \ do { \ al_array_reserve(array, (array).count + 1); \ al_array_at(array, (array).count++) = item; \ } while (0) #define al_array_insert(array, i, item) \ do { \ al_array_reserve(array, (array).count + 1); \ if (i != (array).count - 1) { \ al_memmove(al_array_offset(array, i + 1), al_array_offset(array, i), \ al_array_item_size(array) * ((array).count - i)); \ } \ (array).count++; \ al_array_at(array, i) = item; \ } while (0) #define al_array_pop(array) al_array_at(array, --(array).count) #define al_array_pop_at(array, i, r) \ do { \ r = al_array_at(array, i); \ al_array_remove_at(array, i); \ } while (0) #define al_array_remove_at(array, i) \ do { \ if (i == (array).count - 1) { \ (array).count--; \ } else { \ al_memmove(al_array_offset(array, i), al_array_offset(array, i + 1), \ al_array_item_size(array) * (--(array).count - i)); \ } \ } while (0) #define al_array_remove_range(array, start, end) \ do { \ if (end != (array).count) { \ al_memmove(al_array_offset(array, start), al_array_offset(array, end), \ al_array_item_size(array) * ((array).count - end)); \ } \ (array).count -= end - start; \ } while (0) #ifdef AL_HAVE_GNU_EXTENSIONS #define al_array_contains(array, needle) \ ({ \ bool was_contained = false; \ for (u32 ic = 0; ic < (array).count; ic++) { \ if (al_array_at(array, ic) == needle) { \ was_contained = true; \ break; \ } \ } \ was_contained; \ }) #define al_array_remove(array, elem) \ ({ \ bool did_remove = false; \ for (u32 ir = 0; ir < (array).count; ir++) { \ if (al_array_at(array, ir) == elem) { \ al_array_remove_at(array, ir); \ did_remove = true; \ break; \ } \ } \ did_remove; \ }) #define al_array_remove_all(array, elem) \ ({ \ bool did_remove = false; \ for (u32 ir = (array).count; ir-- > 0;) { \ if (al_array_at(array, ir) == elem) { \ al_array_remove_at(array, ir); \ did_remove = true; \ } \ } \ did_remove; \ }) #endif #ifdef AL_USE_STDLIB #define al_array_sort(array, type, cmp) AL_STDLIB_QSORT((array).data, type, (array).count, cmp) #else #define al_array_sort(array, type, cmp) AL_INSERSION_SORT((array).data, type, (array).count, cmp) #endif #define al_array_free(array) \ if ((array).alloc) AL_ARRAY_FREE((array).data) #define al_array_foreach(array, i, item) \ for (u32 i = 0; (i < (array).count && (item = al_array_at(array, i), 1)); i++) #define al_array_foreach_rev(array, i, item) \ for (u32 i = (array).count; (i-- > 0 && (item = al_array_at(array, i), 1));) #define al_array_foreach_ptr(array, i, item) \ for (u32 i = 0; (i < (array).count && (item = al_array_offset(array, i), 1)); i++) #define al_array_foreach_ptr_rev(array, i, item) \ for (u32 i = (array).count; (i-- > 0 && (item = al_array_offset(array, i), 1));) #define al_array_remove_at_iter(array, i) \ do { \ al_array_remove_at(array, i); \ i--; \ } while (0) static inline u32 _al_array_reserve(void **ptr, u32 prev_size, u32 size) { return al_growing_allocation(ptr, prev_size, size, AL_ARRAY_REALLOC); }