use crate::alloc::Layout;
#[cfg(not(windows))]
use libc::posix_memalign;
#[cfg(windows)]
unsafe fn posix_memalign(this: &mut *mut core::ffi::c_void, size: usize, align: usize) -> i32 {
let ptr = unsafe { libc::aligned_malloc(size, align) };
if ptr.is_null() {
return libc::ENOMEM;
}
*this = ptr;
0
}
#[cfg(windows)]
use libc::aligned_free;
#[cfg(not(windows))]
use libc::free as aligned_free;
use libc::realloc;
#[crate::stabby]
#[derive(Clone, Copy, Default)]
pub struct LibcAlloc {
inner: [u8; 0],
}
impl core::fmt::Debug for LibcAlloc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("LibcAlloc")
}
}
impl LibcAlloc {
pub const fn new() -> Self {
Self { inner: [] }
}
}
impl crate::alloc::IAlloc for LibcAlloc {
fn alloc(&mut self, layout: Layout) -> *mut () {
if layout.size == 0 {
return core::ptr::null_mut();
}
let mut ptr = core::ptr::null_mut();
let err = unsafe { posix_memalign(&mut ptr, layout.align, layout.size) };
if err != 0 && ((ptr as usize).rem_euclid(layout.align) != 0) {
ptr = core::ptr::null_mut();
}
ptr.cast()
}
unsafe fn free(&mut self, ptr: *mut ()) {
unsafe { aligned_free(ptr.cast()) }
}
unsafe fn realloc(&mut self, ptr: *mut (), prev: Layout, new_size: usize) -> *mut () {
if new_size == 0 {
return core::ptr::null_mut();
}
let mut new_ptr = core::ptr::null_mut::<core::ffi::c_void>();
if prev.align <= 8 {
new_ptr = unsafe { realloc(ptr.cast(), new_size) };
};
if new_ptr.is_null() {
let err = unsafe { posix_memalign(&mut new_ptr, prev.align, new_size) };
if err == 0 {
unsafe {
core::ptr::copy_nonoverlapping(
ptr.cast::<u8>(),
new_ptr.cast::<u8>(),
prev.size,
)
}
self.free(ptr.cast());
}
}
new_ptr.cast()
}
}