use ::core::alloc::{GlobalAlloc, Layout};
use ::core::ffi::c_void;
#[cfg(not(feature = "ctor"))]
use ::core::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "ctor")]
#[global_allocator]
static ALLOCATOR: LvglAllocUnsafe = LvglAllocUnsafe;
pub struct LvglAllocUnsafe;
unsafe impl GlobalAlloc for LvglAllocUnsafe {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
unsafe {
const USIZE_BYTES: usize = (usize::BITS / u8::BITS) as usize;
let extra_bytes = USIZE_BYTES + (layout.align() - 1);
let raw = lightvgl_sys::lv_malloc(layout.size() + extra_bytes).cast::<u8>();
let raw_shifted = raw.add(USIZE_BYTES);
let offset = raw_shifted.align_offset(layout.align());
let aligned = raw_shifted.wrapping_add(offset);
*((aligned.cast::<usize>()).sub(1)) = offset + USIZE_BYTES;
aligned
}
}
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
unsafe {
let offset = *(ptr.cast::<usize>()).sub(1);
let raw = ptr.sub(offset);
lightvgl_sys::lv_free(raw.cast::<c_void>());
}
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
unsafe {
const USIZE_BYTES: usize = (usize::BITS / u8::BITS) as usize;
let extra_bytes = USIZE_BYTES + (layout.align() - 1);
let raw = lightvgl_sys::lv_calloc(layout.size() + extra_bytes, 1).cast::<u8>();
let raw_shifted = raw.add(USIZE_BYTES);
let offset = raw_shifted.align_offset(layout.align());
let aligned = raw_shifted.wrapping_add(offset);
*((aligned.cast::<usize>()).sub(1)) = offset + USIZE_BYTES;
aligned
}
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
unsafe {
let offset = *(ptr.cast::<usize>()).sub(1);
let old = ptr.sub(offset).cast::<c_void>();
const USIZE_BYTES: usize = (usize::BITS / u8::BITS) as usize;
let extra_bytes = USIZE_BYTES + (layout.align() - 1);
let raw = lightvgl_sys::lv_realloc(old, new_size + extra_bytes).cast::<u8>();
let raw_shifted = raw.add(USIZE_BYTES);
let offset = raw_shifted.align_offset(layout.align());
let aligned = raw_shifted.add(offset);
*((aligned.cast::<usize>()).sub(1)) = offset + USIZE_BYTES;
aligned
}
}
}
#[cfg(not(feature = "ctor"))]
#[global_allocator]
static ALLOCATOR: LvglAllocSafe = LvglAllocSafe(LvglAllocUnsafe);
#[cfg(not(feature = "ctor"))]
static INITIALIZED: AtomicBool = AtomicBool::new(false);
#[cfg(not(feature = "ctor"))]
pub struct LvglAllocSafe(LvglAllocUnsafe);
#[cfg(not(feature = "ctor"))]
unsafe impl GlobalAlloc for LvglAllocSafe {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
if !INITIALIZED.load(Ordering::Acquire) {
crate::functions::lv_init();
INITIALIZED.store(true, Ordering::Release);
}
unsafe { self.0.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { self.0.dealloc(ptr, layout) }
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
if !INITIALIZED.load(Ordering::Acquire) {
crate::functions::lv_init();
INITIALIZED.store(true, Ordering::Release);
}
unsafe { self.0.alloc_zeroed(layout) }
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
unsafe { self.0.realloc(ptr, layout, new_size) }
}
}