#ifndef SCUFCONT_DARRAY_H_ #define SCUFCONT_DARRAY_H_ #include #include #include // IWYU pragma: keep #include #include "scufcont.h" // IWYU pragma: keep // #define SCUFCONT_BOUNDS_CHECK #ifdef SCUFCONT_BOUNDS_CHECK #include #endif // SCUFCONT_BOUNDS_CHECK #define SCDARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, SCDArray_##type_name, SCDArray_##type_name##_##func_name) #define SCDARRAY_IMPL(type, type_name) \ SCDARRAY_EXPANDER(SCDARRAY_ALLOC, type, type_name, alloc) \ SCDARRAY_EXPANDER(SCDARRAY_FREE, type, type_name, free) \ SCDARRAY_EXPANDER(SCDARRAY_IS_NULL, type, type_name, is_null) \ SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK, type, type_name, push_back) \ SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE, type, type_name, push_back_multiple) \ SCDARRAY_EXPANDER(SCDARRAY_AT, type, type_name, at) \ SCDARRAY_EXPANDER(SCDARRAY_RESIZE, type, type_name, resize) \ SCDARRAY_EXPANDER(SCDARRAY_REMOVE_NO_RESIZE, type, type_name, remove_no_resize) \ SCDARRAY_EXPANDER(SCDARRAY_REMOVE, type, type_name, remove) \ SCDARRAY_EXPANDER(SCDARRAY_CLEAR_NO_RESIZE, type, type_name, clear_no_resize) \ SCDARRAY_EXPANDER(SCDARRAY_CLEAR, type, type_name, clear) #define SCDARRAY_HEADER(type, type_name) \ SCDARRAY_STRUCT(type, type_name) \ SCDARRAY_SIGS(type, type_name) #define SCDARRAY_SIGS(type, type_name) \ SCDARRAY_EXPANDER(SCDARRAY_ALLOC_SIG, type, type_name, alloc); \ SCDARRAY_EXPANDER(SCDARRAY_FREE_SIG, type, type_name, free); \ SCDARRAY_EXPANDER(SCDARRAY_IS_NULL_SIG, type, type_name, is_null); \ SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_SIG, type, type_name, push_back); \ SCDARRAY_EXPANDER(SCDARRAY_PUSH_BACK_MULTIPLE_SIG, type, type_name, push_back_multiple); \ SCDARRAY_EXPANDER(SCDARRAY_AT_SIG, type, type_name, at); \ SCDARRAY_EXPANDER(SCDARRAY_RESIZE_SIG, type, type_name, resize); \ SCDARRAY_EXPANDER(SCDARRAY_REMOVE_SIG, type, type_name, remove); \ SCDARRAY_EXPANDER(SCDARRAY_CLEAR_NO_RESIZE_SIG, type, type_name, clear_no_resize); \ SCDARRAY_EXPANDER(SCDARRAY_CLEAR_SIG, type, type_name, clear); // SCDARRAY_ALLOC_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_alloc); // SCDARRAY_PUSH_BACK_SIG(type, SCDArray_##type_name, SCDArray_##type_name##_push_back); #define SCDARRAY_STRUCT(type, type_name) \ typedef struct { \ type *data; \ size_t len; \ size_t capacity; \ } SCDArray_##type_name; // SCDARRAY_STRUCT(int); #define SCDARRAY_ALLOC_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr) #define SCDARRAY_ALLOC(type, type_name, func_name) \ SCDARRAY_ALLOC_SIG(type, type_name, func_name) { \ darr->data = (type *) calloc(1, sizeof(type)); \ if (darr->data == NULL) { \ return SCUFCONT_OUT_OF_MEMORY; \ } \ darr->len = 0; \ darr->capacity = 1; \ return SCUFCONT_SUCCESS; \ } #define SCDARRAY_FREE_SIG(type, type_name, func_name) void func_name(type_name *const darr) #define SCDARRAY_FREE(type, type_name, func_name) \ SCDARRAY_FREE_SIG(type, type_name, func_name) { \ free(darr->data); \ } #define SCDARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name *const darr) #define SCDARRAY_IS_NULL(type, type_name, func_name) \ SCDARRAY_IS_NULL_SIG(type, type_name, func_name) { \ return darr->data == NULL; \ } // SCDARRAY_ALLOC(int, SCDArray_int, SCDArray_int_alloc); #define SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elem) #define SCDARRAY_PUSH_BACK(type, type_name, func_name) \ SCDARRAY_PUSH_BACK_SIG(type, type_name, func_name) { \ if (darr->len + 1 > darr->capacity) { \ darr->capacity *= 2; \ darr->data = (type *) realloc(darr->data, darr->capacity * sizeof(*new_elem)); \ if (darr->data == NULL) { \ return SCUFCONT_OUT_OF_MEMORY; \ } \ } \ memcpy(darr->data + darr->len, new_elem, sizeof(*new_elem)); \ darr->len++; \ return SCUFCONT_SUCCESS; \ } #define SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) ScufContResult func_name(type_name *const darr, const type *const new_elems, const size_t new_elems_n) #define SCDARRAY_PUSH_BACK_MULTIPLE(type, type_name, func_name) \ SCDARRAY_PUSH_BACK_MULTIPLE_SIG(type, type_name, func_name) { \ if (darr->len + new_elems_n > darr->capacity) { \ darr->data = (type *) realloc(darr->data, (darr->capacity + new_elems_n) * sizeof(type)); \ if (darr->data == NULL) { \ return SCUFCONT_OUT_OF_MEMORY; \ } \ darr->capacity += new_elems_n; \ } \ memcpy(darr->data + darr->len, new_elems, sizeof(type) * new_elems_n); \ darr->len += new_elems_n; \ return SCUFCONT_SUCCESS; \ } // SCDARRAY_PUSH_BACK_MULTIPLE(int, SCDArray_int, SCDArray_int_push_back_multiple) #define SCDARRAY_AT_SIG(type, type_name, func_name) type *func_name(const type_name *const darr, const size_t i) // SCDARRAY_PUSH_BACK(int, SCDArray_int, SCDArray_int_push_back); #ifdef SCUFCONT_BOUNDS_CHECK #define SCDARRAY_AT(type, type_name, func_name) \ SCDARRAY_AT_SIG(type, type_name, func_name) { \ if (i < 0 || i > darr->len) { \ fprintf(stderr, #func_name " out-of-bounds. i: %zu, len: %zu", i, darr->len); \ exit(1); \ } \ \ return darr->data + i; \ } #else #define SCDARRAY_AT(type, type_name, func_name) \ SCDARRAY_AT_SIG(type, type_name, func_name) { \ return darr->data + i; \ } #endif // SCUFCONT_BOUNDS_CHECK // SCDARRAY_AT(char*, SCDArray_charp, SCDArray_charp_at) #define SCDARRAY_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr) #define SCDARRAY_RESIZE(type, type_name, func_name) \ SCDARRAY_RESIZE_SIG(type, type_name, func_name) { \ if (darr->len == 0) { \ darr->data = realloc(darr->data, sizeof(type)); \ } else { \ darr->data = realloc(darr->data, sizeof(type) * darr->len); \ } \ } #define SCDARRAY_REMOVE_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i) #define SCDARRAY_REMOVE_NO_RESIZE(type, type_name, func_name) \ SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \ if (i != darr->len - 1) { \ memmove(darr->data + i, darr->data + i + 1, (darr->len - (i + 1)) * sizeof(type)); \ } \ darr->len--; \ } // SCDARRAY_EXPANDER(SCDARRAY_REMOVE_NO_RESIZE, char*, charp, remove_no_resize) #define SCDARRAY_REMOVE_SIG(type, type_name, func_name) void func_name(type_name *const darr, const size_t i) #define SCDARRAY_REMOVE(type, type_name, func_name) \ SCDARRAY_REMOVE_SIG(type, type_name, func_name) { \ type_name##_remove_no_resize(darr, i); \ type_name##_resize(darr); \ } // SCDARRAY_EXPANDER(SCDARRAY_REMOVE, char*, charp, remove) #define SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) void func_name(type_name *const darr) #define SCDARRAY_CLEAR_NO_RESIZE(type, type_name, func_name) \ SCDARRAY_CLEAR_NO_RESIZE_SIG(type, type_name, func_name) { \ darr->len = 0; \ } // SCDARRAY_CLEAR_NO_RESIZE(char*, SCDArray_charp, SCDArray_charp_clear_no_resize) #define SCDARRAY_CLEAR_SIG(type, type_name, func_name) void func_name(type_name *const darr) #define SCDARRAY_CLEAR(type, type_name, func_name) \ SCDARRAY_CLEAR_SIG(type, type_name, func_name) { \ type_name##_clear_no_resize(darr); \ type_name##_resize(darr); \ } // SCDARRAY_EXPANDER(SCDARRAY_CLEAR, char*, charp, clear) #endif // SCUFCONT_DARRAY_H_