|
3 | 3 |
|
4 | 4 | use cfg_if::cfg_if;
|
5 | 5 |
|
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 | +}; |
8 | 11 |
|
9 | 12 | /// Uses the PHP memory allocator to allocate request-bound memory.
|
10 | 13 | ///
|
@@ -62,3 +65,67 @@ pub unsafe fn efree(ptr: *mut u8) {
|
62 | 65 | }
|
63 | 66 | }
|
64 | 67 | }
|
| 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_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")] |
| 100 | +mod 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 | +} |
0 commit comments