1use cfg_if::cfg_if;
5
6use crate::ffi::{_efree, _emalloc, _estrdup};
7use std::{
8 alloc::Layout,
9 ffi::{c_char, c_void, CString},
10};
11
12#[must_use]
22pub fn emalloc(layout: Layout) -> *mut u8 {
23 let size = layout.size();
25
26 (unsafe {
27 cfg_if! {
28 if #[cfg(php_debug)] {
29 #[allow(clippy::used_underscore_items)]
30 _emalloc(size as _, std::ptr::null_mut(), 0, std::ptr::null_mut(), 0)
31 } else {
32 #[allow(clippy::used_underscore_items)]
33 _emalloc(size as _)
34 }
35 }
36 })
37 .cast::<u8>()
38}
39
40pub unsafe fn efree(ptr: *mut u8) {
52 cfg_if! {
53 if #[cfg(php_debug)] {
54 #[allow(clippy::used_underscore_items)]
55 _efree(
56 ptr.cast::<c_void>(),
57 std::ptr::null_mut(),
58 0,
59 std::ptr::null_mut(),
60 0,
61 );
62 } else {
63 #[allow(clippy::used_underscore_items)]
64 _efree(ptr.cast::<c_void>());
65 }
66 }
67}
68
69pub fn estrdup(string: impl Into<Vec<u8>>) -> *mut c_char {
80 let string = unsafe { CString::from_vec_unchecked(string.into()) }.into_raw();
81
82 let result = unsafe {
83 cfg_if! {
84 if #[cfg(php_debug)] {
85 #[allow(clippy::used_underscore_items)]
86 _estrdup(string, std::ptr::null_mut(), 0, std::ptr::null_mut(), 0)
87 } else {
88 #[allow(clippy::used_underscore_items)]
89 _estrdup(string)
90 }
91 }
92 };
93
94 drop(unsafe { CString::from_raw(string) });
95 result
96}
97
98#[cfg(test)]
99#[cfg(feature = "embed")]
100mod test {
101 use super::*;
102 use crate::embed::Embed;
103 use std::ffi::CStr;
104
105 #[test]
106 fn test_emalloc() {
107 Embed::run(|| {
108 let layout = Layout::from_size_align(16, 8).expect("should create layout");
109 let ptr = emalloc(layout);
110 assert!(!ptr.is_null());
111 unsafe { efree(ptr) };
112 });
113 }
114
115 #[test]
116 fn test_estrdup() {
117 Embed::run(|| {
118 let original = "Hello, world!";
119 let duplicated = estrdup(original);
120 assert!(!duplicated.is_null());
121
122 let duplicated_str = unsafe { CStr::from_ptr(duplicated) };
123 assert_eq!(
124 duplicated_str.to_str().expect("should convert to str"),
125 original
126 );
127
128 unsafe { efree(duplicated.cast::<u8>()) }
129 });
130 }
131}