Skip to content

Commit b3a46cd

Browse files
committed
feat(alloc): add estrdup
1 parent 96555c4 commit b3a46cd

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

allowed_bindings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ bind! {
2525
_call_user_function_impl,
2626
_efree,
2727
_emalloc,
28+
_estrdup,
2829
_zend_executor_globals,
2930
_sapi_globals_struct,
3031
_sapi_module_struct,

src/alloc.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
44
use cfg_if::cfg_if;
55

6-
use crate::ffi::{_efree, _emalloc};
7-
use std::{alloc::Layout, ffi::c_void};
6+
use crate::ffi::{_efree, _emalloc, _estrdup};
7+
use std::{
8+
alloc::Layout,
9+
ffi::{c_char, c_void, CString},
10+
};
811

912
/// Uses the PHP memory allocator to allocate request-bound memory.
1013
///
@@ -62,3 +65,66 @@ pub unsafe fn efree(ptr: *mut u8) {
6265
}
6366
}
6467
}
68+
69+
/// Duplicates a string using the PHP memory manager.
70+
///
71+
/// # Parameters
72+
///
73+
/// * `string` - The string to duplicate, which can be any type that can be
74+
/// converted into a `Vec<u8>`.
75+
///
76+
/// # Returns
77+
///
78+
/// A pointer to the duplicated string in the PHP memory manager.
79+
pub 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(php_debug)]
84+
{
85+
_estrdup(string, std::ptr::null_mut(), 0, std::ptr::null_mut(), 0)
86+
}
87+
#[cfg(not(php_debug))]
88+
{
89+
_estrdup(string)
90+
}
91+
};
92+
93+
drop(unsafe { CString::from_raw(string) });
94+
result
95+
}
96+
97+
#[cfg(test)]
98+
#[cfg(feature = "embed")]
99+
mod test {
100+
use super::*;
101+
use crate::embed::Embed;
102+
use std::ffi::CStr;
103+
104+
#[test]
105+
fn test_emalloc() {
106+
Embed::run(|| {
107+
let layout = Layout::from_size_align(16, 8).expect("should create layout");
108+
let ptr = emalloc(layout);
109+
assert!(!ptr.is_null());
110+
unsafe { efree(ptr) };
111+
});
112+
}
113+
114+
#[test]
115+
fn test_estrdup() {
116+
Embed::run(|| {
117+
let original = "Hello, world!";
118+
let duplicated = estrdup(original);
119+
assert!(!duplicated.is_null());
120+
121+
let duplicated_str = unsafe { CStr::from_ptr(duplicated) };
122+
assert_eq!(
123+
duplicated_str.to_str().expect("should convert to str"),
124+
original
125+
);
126+
127+
unsafe { efree(duplicated.cast::<u8>()) }
128+
});
129+
}
130+
}

src/exception.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ mod tests {
342342
});
343343
}
344344

345+
#[cfg(feature = "anyhow")]
345346
#[test]
346347
fn test_from_anyhow() {
347348
Embed::run(|| {

0 commit comments

Comments
 (0)