#ifndef APFL_ALLOC_H #define APFL_ALLOC_H #ifdef __cplusplus extern "C" { #endif #include #include "apfl.h" #define ALLOCATOR_CALL(a, oldptr, oldsize, newsize) \ ((a).alloc((a).opaque, (oldptr), (oldsize), (newsize))) #define ALLOC_BYTES(a, n) (((n) == 0) ? NULL : ALLOCATOR_CALL(a, NULL, 0, (n))) #define REALLOC_BYTES(a, ptr, old, new) ALLOCATOR_CALL(a, ptr, old, new) #define FREE_BYTES(a, ptr, n) ALLOCATOR_CALL(a, ptr, n, 0) #define REALLOC_UNTYPED_ARRAY(a, ptr, elemsize, old, new) apfl_alloc_realloc_array(a, (ptr), (elemsize), (old), (new)) #define ALLOC_UNTYPED_ARRAY(a, elemsize, len) REALLOC_UNTYPED_ARRAY((a), NULL, (elemsize), 0, (len)) #define FREE_UNTYPED_ARRAY(a, ptr, elemsize, len) REALLOC_UNTYPED_ARRAY((a), (ptr), (elemsize), (len), 0) #define REALLOC_LIST(a, ptr, old, new) REALLOC_UNTYPED_ARRAY((a), (ptr), sizeof(*(ptr)), (old), (new)) #define ALLOC_LIST(a, T, len) (T *)ALLOC_UNTYPED_ARRAY((a), sizeof(T), (len)) #define FREE_LIST(a, ptr, len) FREE_UNTYPED_ARRAY((a), (ptr), sizeof(*ptr), (len)) #define ALLOC_OBJ(a, T) ALLOC_LIST(a, T, 1) #define FREE_OBJ(a, ptr) FREE_LIST(a, ptr, 1) #define DEINIT_CAP_LIST(allocator, items, len, cap, item_deinit) \ do { \ if ((items) == NULL) { \ break; \ } \ for (size_t i = 0; i < (len); i++) { \ item_deinit(allocator, &((items)[i])); \ } \ FREE_LIST(allocator, items, cap); \ len = 0; \ cap = 0; \ (items) = NULL; \ } while(0) #define DEINIT_LIST(allocator, items, len, item_deinit) \ do { \ if ((items) == NULL) { \ break; \ } \ for (size_t i = 0; i < (len); i++) { \ item_deinit(allocator, &((items)[i])); \ } \ FREE_LIST(allocator, items, len); \ len = 0; \ (items) = NULL; \ } while(0) #define DEINIT_LIST_WITH_ARGS(allocator, items, len, item_deinit, ...) \ do { \ if ((items) == NULL) { \ break; \ } \ for (size_t i = 0; i < (len); i++) { \ item_deinit(__VA_ARGS__, &((items)[i])); \ } \ FREE_LIST(allocator, items, len); \ len = 0; \ (items) = NULL; \ } while(0) #define DEINIT_CAP_LIST_WITH_ARGS(allocator, items, len, cap, item_deinit, ...) \ do { \ if ((items) == NULL) { \ break; \ } \ for (size_t i = 0; i < (len); i++) { \ item_deinit(__VA_ARGS__, &((items)[i])); \ } \ FREE_LIST(allocator, items, cap); \ len = 0; \ cap = 0; \ (items) = NULL; \ } while(0) #define MOVEPTR(out, in) \ do { \ out = in; \ in = NULL; \ } while(0) // DESTROY destroys a dynamically allocated value. // It will first deinit the value using deiniter, // free the memory and then set the variable to NULL. // It is always allowed to destroy an already destroyed // or deinited value. #define DESTROY(allocator, var, deiniter) \ do { \ if ((var) == NULL) { \ break; \ } \ deiniter(allocator, var); \ FREE_OBJ(allocator, var); \ (var) = NULL; \ } while(0) void *apfl_alloc_realloc_array(struct apfl_allocator, void *oldptr, size_t elem_size, size_t oldlen, size_t newlen); #ifdef __cplusplus } #endif #endif