// vim:fileencoding=utf-8:foldmethod=marker

#include "mem_allocator.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <stdlib.h>

void *wpMemAllocatorAlloc(const WpAllocator *allocator, u64 size) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_ALLOC)) {
		return NULL;
	}

	return allocator->alloc(size, allocator->obj);
}

void *wpMemAllocatorAllocAligned(const WpAllocator *allocator, u64 size, u64 alignment) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_ALLOC_ALIGNED)) {
		return NULL;
	}

	return allocator->alloc_aligned(size, alignment, allocator->obj);
}

void *wpMemAllocatorRealloc(const WpAllocator *allocator, void *ptr, u64 old_size, u64 new_size) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_REALLOC)) {
		return NULL;
	}

	return allocator->realloc(ptr, old_size, new_size, allocator->obj);
}

void *wpMemAllocatorReallocAligned(const WpAllocator *allocator, void *ptr, u64 old_size,
                                         u64 new_size, u64 alignment) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_REALLOC_ALIGNED)) {
		return NULL;
	}

	return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
}

void wpMemAllocatorFree(const WpAllocator *allocator, void **ptr, u64 size) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_FREE)) {
		return;
	}

	allocator->free(ptr, size, allocator->obj);
}

b8 wpMemAllocatorOpSupported(const WpAllocator *allocator, WpMemOp op) {
	wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");

	switch (op) {
		case WP_MEM_OP_ALLOC:
			return allocator->alloc != NULL;
		case WP_MEM_OP_ALLOC_ALIGNED:
			return allocator->alloc_aligned != NULL;
		case WP_MEM_OP_REALLOC:
			return allocator->realloc != NULL;
		case WP_MEM_OP_REALLOC_ALIGNED:
			return allocator->realloc_aligned != NULL;
		case WP_MEM_OP_FREE:
			return allocator->free != NULL;
		default:
			break;
	}

	return false;
}
