#include "malunal/allocators/linear.h" typedef struct { allocator_t allocator; malunal_size_t size; malunal_size_t used; malunal_uint8_t* buffer; } impl_t; typedef impl_t* impl_mptr_t; typedef const impl_t* impl_iptr_t; _Static_assert( sizeof(linear_allocator_t) == sizeof(impl_t), "Linear allocator must be the size of its implementation" ); static const allocator_vtable_t linear_allocator_vtable = { .acquire = (allocator_acquire_pfn_t)&linear_allocator_acquire, .dispose = (allocator_dispose_pfn_t)&linear_allocator_dispose }; error_t linear_allocator_size( linear_allocator_iptr_t allocator, malunal_uint32_t* out ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; *out = self->size; return NO_ERROR; } error_t linear_allocator_used( linear_allocator_iptr_t allocator, malunal_uint32_t* out ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; *out = self->used; return NO_ERROR; } error_t linear_allocator_init( malunal_size_t size, malunal_mptr_t buffer, linear_allocator_mptr_t allocator ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; self->allocator.vtable = &linear_allocator_vtable; self->buffer = buffer; self->size = size; self->used = 0; return NO_ERROR; } error_t linear_allocator_acquire( linear_allocator_mptr_t allocator, malunal_size_t size, malunal_mptr_t* out ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; if (self->used + size > self->size) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_OUT_OF_MEMORY }; *out = self->buffer + self->used; self->used += size; return NO_ERROR; } error_t linear_allocator_dispose( linear_allocator_mptr_t allocator, malunal_mptr_t address, malunal_size_t size ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; malunal_uint8_t* addr = address; malunal_uint8_t* beg = self->buffer; malunal_uint8_t* end = self->buffer + self->size; if (addr < beg || addr > end) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NOT_MY_ADDRESS }; return NO_ERROR; } error_t linear_allocator_reset( linear_allocator_mptr_t allocator ) { if (allocator == null) return (error_t) { .domain = &ERROR_DOMAIN_ALLOCATOR_T, .code = ALLOCATOR_ERROR_NULL_ALLOCATOR }; impl_mptr_t self = (impl_mptr_t)allocator; self->used = 0; return NO_ERROR; }