140 lines
3.1 KiB
C
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;
|
|
}
|