use core::{ffi::{CStr, VaList, c_char, c_int, c_long, c_longlong, c_size_t, c_uchar, c_void}, ptr::null_mut}; use core::alloc::GlobalAlloc; use enumset::EnumSet; use esp_alloc::EspHeap; // Here we select the allocator to use for libxkbcommon. static XKBC_ALLOCATOR: &EspHeap = &crate::PSRAM_ALLOCATOR; // Implementation based on esp-alloc's `compat` feature. #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_malloc(size: c_size_t) -> *mut c_void { unsafe { malloc_with_caps(size, EnumSet::empty()) as *mut _ } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_calloc( number: c_size_t, size: c_size_t, ) -> *mut c_void { let total_size = number as usize * size; unsafe { let ptr = __xkbc_malloc(total_size) as *mut u8; if !ptr.is_null() { for i in 0..total_size as isize { ptr.offset(i).write_volatile(0); } } ptr as *mut _ } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_realloc( ptr: *mut c_void, new_size: c_size_t, ) -> *mut c_void { unsafe { realloc_with_caps(ptr as *mut _, new_size, EnumSet::empty()) as *mut _ } } #[unsafe(no_mangle)] pub unsafe extern "C" fn __xkbc_free(ptr: *mut c_void) { if ptr.is_null() { return; } unsafe { let ptr = ptr.offset(-4); let total_size = *(ptr as *const usize); XKBC_ALLOCATOR.dealloc( ptr as *mut u8, core::alloc::Layout::from_size_align_unchecked(total_size, 4), ) } } unsafe fn malloc_with_caps( size: usize, caps: EnumSet, ) -> *mut u8 { let total_size = size + 4; unsafe { let ptr = XKBC_ALLOCATOR.alloc_caps( caps, core::alloc::Layout::from_size_align_unchecked(total_size, 4), ); if ptr.is_null() { return ptr; } *(ptr as *mut usize) = total_size; ptr.offset(4) } } unsafe fn realloc_with_caps( ptr: *mut u8, new_size: usize, caps: enumset::EnumSet, ) -> *mut u8 { unsafe extern "C" { fn memcpy(d: *mut u8, s: *const u8, l: usize); } unsafe { let p = malloc_with_caps(new_size, caps); if !p.is_null() && !ptr.is_null() { let len = usize::min( (ptr as *const u32).sub(1).read_volatile() as usize, new_size, ); memcpy(p, ptr, len); __xkbc_free(ptr as *mut _); } p } }