libxml_rs/xslt/extensions/
mod.rs1use crate::abi::allocator::xmlFree;
18use crate::abi::structs::*;
19use crate::abi::types::*;
20use std::os::raw::c_int;
21use std::ptr;
22
23#[repr(C)]
25pub struct _xsltExtFunction {
26 pub next: *mut _xsltExtFunction,
27 pub name: *mut xmlChar,
28 pub ns: *mut xmlChar,
29 pub func: *mut c_void,
30}
31
32#[repr(C)]
34pub struct _xsltExtElement {
35 pub next: *mut _xsltExtElement,
36 pub name: *mut xmlChar,
37 pub ns: *mut xmlChar,
38 pub func: *mut c_void,
39}
40
41#[no_mangle]
49pub unsafe extern "C" fn xsltRegisterExtFunction(
50 ctxt: *mut _xsltTransformContext,
51 name: *const xmlChar,
52 NS_uri: *const xmlChar,
53 f: Option<unsafe extern "C" fn(*mut c_void, c_int)>,
54) -> c_int {
55 if ctxt.is_null() || name.is_null() || NS_uri.is_null() {
56 return -1;
57 }
58 let entry = libc::calloc(1, core::mem::size_of::<_xsltExtFunction>()) as *mut _xsltExtFunction;
59 if entry.is_null() {
60 return -1;
61 }
62 (*entry).name = dup_str(name);
63 (*entry).ns = dup_str(NS_uri);
64 if (*entry).name.is_null() || (*entry).ns.is_null() {
65 if !(*entry).name.is_null() {
66 libc::free((*entry).name as *mut libc::c_void);
67 }
68 if !(*entry).ns.is_null() {
69 libc::free((*entry).ns as *mut libc::c_void);
70 }
71 libc::free(entry as *mut libc::c_void);
72 return -1;
73 }
74 (*entry).func = f.map(|fp| fp as *mut c_void).unwrap_or(ptr::null_mut());
75 (*entry).next = (*ctxt).extFunctionsTab as *mut _xsltExtFunction;
78 (*ctxt).extFunctionsTab = entry as *mut c_void;
79 (*ctxt).extFunctionsNr += 1;
80 0
81}
82
83#[no_mangle]
91pub unsafe extern "C" fn xsltRegisterExtElement(
92 ctxt: *mut _xsltTransformContext,
93 name: *const xmlChar,
94 NS_uri: *const xmlChar,
95 f: Option<
96 unsafe extern "C" fn(*mut c_void, *mut c_void, *mut _xmlNode, *mut c_void, *mut _xmlNode),
97 >,
98) -> c_int {
99 if ctxt.is_null() || name.is_null() || NS_uri.is_null() {
100 return -1;
101 }
102 let entry = libc::calloc(1, core::mem::size_of::<_xsltExtElement>()) as *mut _xsltExtElement;
103 if entry.is_null() {
104 return -1;
105 }
106 (*entry).name = dup_str(name);
107 (*entry).ns = dup_str(NS_uri);
108 if (*entry).name.is_null() || (*entry).ns.is_null() {
109 if !(*entry).name.is_null() {
110 libc::free((*entry).name as *mut libc::c_void);
111 }
112 if !(*entry).ns.is_null() {
113 libc::free((*entry).ns as *mut libc::c_void);
114 }
115 libc::free(entry as *mut libc::c_void);
116 return -1;
117 }
118 (*entry).func = f.map(|fp| fp as *mut c_void).unwrap_or(ptr::null_mut());
119 (*entry).next = (*ctxt).extInfos as *mut _xsltExtElement;
120 (*ctxt).extInfos = entry as *mut c_void;
121 0
122}
123
124pub unsafe fn xsltFindExtFunction(
131 ctxt: *mut _xsltTransformContext,
132 name: *const xmlChar,
133 ns: *const xmlChar,
134) -> *mut c_void {
135 if ctxt.is_null() || name.is_null() || ns.is_null() {
136 return ptr::null_mut();
137 }
138 let mut cur = (*ctxt).extFunctionsTab as *mut _xsltExtFunction;
139 while !cur.is_null() {
140 if !(*cur).name.is_null()
141 && !(*cur).ns.is_null()
142 && libc::strcmp(
143 (*cur).name as *const libc::c_char,
144 name as *const libc::c_char,
145 ) == 0
146 && libc::strcmp((*cur).ns as *const libc::c_char, ns as *const libc::c_char) == 0
147 {
148 return (*cur).func;
149 }
150 cur = (*cur).next;
151 }
152 ptr::null_mut()
153}
154
155pub unsafe fn xsltFindExtElement(
162 ctxt: *mut _xsltTransformContext,
163 name: *const xmlChar,
164 ns: *const xmlChar,
165) -> *mut c_void {
166 if ctxt.is_null() || name.is_null() || ns.is_null() {
167 return ptr::null_mut();
168 }
169 let mut cur = (*ctxt).extInfos as *mut _xsltExtElement;
170 while !cur.is_null() {
171 if !(*cur).name.is_null()
172 && !(*cur).ns.is_null()
173 && libc::strcmp(
174 (*cur).name as *const libc::c_char,
175 name as *const libc::c_char,
176 ) == 0
177 && libc::strcmp((*cur).ns as *const libc::c_char, ns as *const libc::c_char) == 0
178 {
179 return (*cur).func;
180 }
181 cur = (*cur).next;
182 }
183 ptr::null_mut()
184}
185
186pub unsafe fn xsltFreeExts(ctxt: *mut _xsltTransformContext) {
192 if ctxt.is_null() {
193 return;
194 }
195 let mut cur = (*ctxt).extFunctionsTab as *mut _xsltExtFunction;
197 (*ctxt).extFunctionsTab = ptr::null_mut();
198 (*ctxt).extFunctionsNr = 0;
199 while !cur.is_null() {
200 let next = (*cur).next;
201 if !(*cur).name.is_null() {
202 libc::free((*cur).name as *mut libc::c_void);
203 }
204 if !(*cur).ns.is_null() {
205 libc::free((*cur).ns as *mut libc::c_void);
206 }
207 libc::free(cur as *mut libc::c_void);
208 cur = next;
209 }
210 let mut cur = (*ctxt).extInfos as *mut _xsltExtElement;
212 (*ctxt).extInfos = ptr::null_mut();
213 while !cur.is_null() {
214 let next = (*cur).next;
215 if !(*cur).name.is_null() {
216 libc::free((*cur).name as *mut libc::c_void);
217 }
218 if !(*cur).ns.is_null() {
219 libc::free((*cur).ns as *mut libc::c_void);
220 }
221 libc::free(cur as *mut libc::c_void);
222 cur = next;
223 }
224}
225
226unsafe fn dup_str(s: *const xmlChar) -> *mut xmlChar {
228 let len = libc::strlen(s as *const libc::c_char);
229 let copy = libc::malloc(len + 1) as *mut xmlChar;
230 if copy.is_null() {
231 return ptr::null_mut();
232 }
233 libc::memcpy(copy as *mut libc::c_void, s as *const libc::c_void, len);
234 *copy.add(len) = 0;
235 copy
236}
237
238use std::ffi::c_void;
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243 use core::ptr;
244
245 fn make_ctxt() -> *mut _xsltTransformContext {
246 unsafe {
247 libc::calloc(1, core::mem::size_of::<_xsltTransformContext>())
248 as *mut _xsltTransformContext
249 }
250 }
251
252 #[test]
253 fn test_register_and_find_function() {
254 unsafe {
255 let ctxt = make_ctxt();
256 extern "C" fn dummy(_ctx: *mut c_void, _n: c_int) {}
257 assert_eq!(
258 xsltRegisterExtFunction(
259 ctxt,
260 b"myfunc\0".as_ptr() as *const xmlChar,
261 b"http://example.com/ext\0".as_ptr() as *const xmlChar,
262 Some(dummy),
263 ),
264 0
265 );
266 let found = xsltFindExtFunction(
267 ctxt,
268 b"myfunc\0".as_ptr() as *const xmlChar,
269 b"http://example.com/ext\0".as_ptr() as *const xmlChar,
270 );
271 assert_eq!(found, dummy as *mut c_void);
272 let not_found = xsltFindExtFunction(
273 ctxt,
274 b"other\0".as_ptr() as *const xmlChar,
275 b"http://example.com/ext\0".as_ptr() as *const xmlChar,
276 );
277 assert!(not_found.is_null());
278 xsltFreeExts(ctxt);
279 libc::free(ctxt as *mut libc::c_void);
280 }
281 }
282
283 #[test]
284 fn test_register_null() {
285 unsafe {
286 assert_eq!(
287 xsltRegisterExtFunction(ptr::null_mut(), ptr::null(), ptr::null(), None),
288 -1
289 );
290 assert_eq!(
291 xsltRegisterExtElement(ptr::null_mut(), ptr::null(), ptr::null(), None),
292 -1
293 );
294 }
295 }
296}