apfl/src/alloc.h

103 lines
4.7 KiB
C

#ifndef APFL_ALLOC_H
#define APFL_ALLOC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.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_LIST(a, ptr, old, new) REALLOC_BYTES(a, ptr, sizeof(*ptr) * (old), sizeof(*ptr) * (new))
#define ALLOC_LIST(a, T, len) (T *)ALLOC_BYTES(a, sizeof(T) * (len))
#define FREE_LIST(a, ptr, len) FREE_BYTES(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)
#ifdef __cplusplus
}
#endif
#endif