#include "allocator.h" #include #include #include #include #define DEFAULT_ALIGNMENT ((size_t)_Alignof(max_align_t)) void *sand_allocate_aligned(SandAllocator *a, size_t size, size_t alignment) { assert(a != NULL); assert(size > 0); assert(alignment > 0); void *ptr = a->allocate(size, alignment, a->user_data); assert(ptr == NULL || sand_pointer_is_aligned(ptr, alignment)); return ptr; } void *sand_allocate(SandAllocator *a, size_t size) { return sand_allocate_aligned(a, size, DEFAULT_ALIGNMENT); } void *sand_reallocate_aligned(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size, size_t alignment) { assert(a != NULL); assert(old_ptr != NULL); assert(old_size > 0); assert(new_size > 0); assert(alignment > 0); if (a->reallocate != NULL) { void *new_ptr = a->reallocate(old_ptr, old_size, new_size, alignment, a->user_data); assert(sand_pointer_is_aligned(new_ptr, alignment)); return new_ptr; } else { void *new_ptr = a->allocate(new_size, alignment, a->user_data); if (new_ptr == NULL) { return NULL; // Note that we HAVEN'T freed `old_ptr`! } assert(sand_pointer_is_aligned(new_ptr, alignment)); memmove(new_ptr, old_ptr, old_size); // Can't know if they overlap. a->deallocate(old_ptr, old_size, a->user_data); return new_ptr; } } void *sand_reallocate(SandAllocator *a, void *old_ptr, size_t old_size, size_t new_size) { return sand_reallocate_aligned(a, old_ptr, old_size, new_size, DEFAULT_ALIGNMENT); } void sand_deallocate(SandAllocator *a, void *old_ptr, size_t old_size) { assert(a != NULL); assert(old_ptr != NULL); assert(old_size > 0); if (old_ptr == NULL) { return; } a->deallocate(old_ptr, old_size, a->user_data); } bool sand_is_valid_alignment(size_t alignment) { // Only powers of two are allowed as alignments for simplicity. return alignment % 2 == 0; } void *sand_align_pointer_forward(void *ptr, size_t alignment) { intptr_t p = (intptr_t)ptr; intptr_t a = alignment; intptr_t ap = ((p + a - 1) & ~(a - 1)); void *result = (void *)ap; assert(sand_pointer_is_aligned(result, alignment)); return result; } size_t sand_align_size_forward(size_t n, size_t alignment) { size_t result = ((n + alignment - 1) & ~(alignment - 1)); assert(sand_size_is_aligned(result, alignment)); return result; } bool sand_pointer_is_aligned(void *pointer, size_t alignment) { return ((uintptr_t)pointer & (alignment - 1)) == 0; } bool sand_size_is_aligned(size_t n, size_t alignment) { return (n & (alignment - 1)) == 0; }