#ifndef DYN_ARRAY_H_ #define DYN_ARRAY_H_ #include #include #include #include "DynString.h" #ifdef BOUNDS_CHECK #include "log.h" #endif // BOUNDS_CHECK #define DYN_ARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, DynArray_##type_name, DynArray_##type_name##_##func_name); #define DYN_ARRAY_IMPL(type, type_name) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_ALLOC, type, type_name, alloc) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_IS_NULL, type, type_name, is_null) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_PUSH_BACK, type, type_name, push_back) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_AT, type, type_name, at) #define DYN_ARRAY_HEADER(type, type_name) \ DYN_ARRAY_STRUCT(type, type_name) \ DYN_ARRAY_SIGS(type, type_name) #define DYN_ARRAY_SIGS(type, type_name) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_ALLOC_SIG, type, type_name, alloc) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_IS_NULL_SIG, type, type_name, is_null) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_PUSH_BACK_SIG, type, type_name, push_back) \ DYN_ARRAY_EXPANDER(DYN_ARRAY_AT_SIG, type, type_name, at) // DYN_ARRAY_ALLOC_SIG(type, DynArray_##type_name, DynArray_##type_name##_alloc); \ // DYN_ARRAY_PUSH_BACK_SIG(type, DynArray_##type_name, DynArray_##type_name##_push_back); #define DYN_ARRAY_STRUCT(type, type_name) \ typedef struct { \ type* data; \ size_t len; \ size_t capacity; \ } DynArray_##type_name; // DYN_ARRAY_STRUCT(int); #define DYN_ARRAY_ALLOC_SIG(type, type_name, func_name) int func_name(type_name* darr) #define DYN_ARRAY_ALLOC(type, type_name, func_name) \ DYN_ARRAY_ALLOC_SIG(type, type_name, func_name) { \ darr->data = (type*) calloc(1, sizeof(type)); \ if (darr->data == NULL) { \ return -1; \ } \ darr->len = 0; \ darr->capacity = 1; \ return 1; \ } #define DYN_ARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name* darr) #define DYN_ARRAY_IS_NULL(type, type_name, func_name) \ DYN_ARRAY_IS_NULL_SIG(type, type_name, func_name) { \ return darr->data == NULL; \ } // DYN_ARRAY_ALLOC(int, DynArray_int, DynArray_int_alloc); #define DYN_ARRAY_PUSH_BACK_SIG(type, type_name, func_name) int func_name(type_name* darr, const type* new_elem) #define DYN_ARRAY_PUSH_BACK(type, type_name, func_name) \ DYN_ARRAY_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(type)); \ if (darr->data == NULL) { \ return -1; \ } \ } \ memcpy(darr->data + darr->len, new_elem, sizeof(type)); \ darr->len++; \ return 1; \ } #define DYN_ARRAY_AT_SIG(type, type_name, func_name) type* func_name(type_name* darr, const size_t i) #ifdef BOUNDS_CHECK #define DYN_ARRAY_AT(type, type_name, func_name) \ DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ if (i < 0 || i > darr->len) { \ LOG_FATALF(#func_name " exceeded bounds! i: %zu, len: %zu", i, darr->len); \ } \ \ return &darr->data[i]; \ } #else #define DYN_ARRAY_AT(type, type_name, func_name) \ DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ return darr->data[i]; \ } #endif // BOUNDS_CHECK // DYN_ARRAY_PUSH_BACK(int, DynArray_int, DynArray_int_push_back); DYN_ARRAY_HEADER(DynString, DynString); DYN_ARRAY_HEADER(char*, charp); #endif // DYN_ARRAY_H_