Files

140 lines
3.1 KiB
C

#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;
}