use crate::{DEFAULT_REGEX_CONF, Regex, RegexConf, RegexMatcher};
use core::ffi::{CStr, c_char, c_ulong};
use core::ptr;
extern crate alloc;
use alloc::boxed::Box;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_compile(src: *const c_char) -> *mut Regex {
let src = unsafe { CStr::from_ptr(src) };
let Ok(src) = src.to_str() else {
return ptr::null_mut();
};
let Ok(regex) = Regex::compile(src) else {
return ptr::null_mut();
};
Box::into_raw(Box::new(regex))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_test(regex: *const Regex, src: *const c_char) -> bool {
unsafe { regex_test_with_conf(regex, src, DEFAULT_REGEX_CONF) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_test_with_conf(
regex: *const Regex,
src: *const c_char,
conf: RegexConf,
) -> bool {
let src = unsafe { CStr::from_ptr(src) };
let Ok(src) = src.to_str() else { return false };
unsafe { &*regex }.test_with_conf(src, conf)
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_find_matches<'a>(
regex: *const Regex,
src: *const c_char,
) -> *mut RegexMatcher<'a> {
unsafe { regex_find_matches_with_conf(regex, src, DEFAULT_REGEX_CONF) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_find_matches_with_conf<'a>(
regex: *const Regex,
src: *const c_char,
conf: RegexConf,
) -> *mut RegexMatcher<'a> {
let src = unsafe { CStr::from_ptr(src) };
let Ok(src) = src.to_str() else {
return ptr::null_mut();
};
let matcher = unsafe { &*regex }.find_matches_with_conf(src, conf);
let matcher = Box::new(matcher);
Box::into_raw(matcher)
}
#[repr(C)]
pub struct Span {
offset: c_ulong,
len: c_ulong,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_matcher_next(
matcher: *mut RegexMatcher<'_>,
span: *mut Span,
) -> bool {
match unsafe { &mut *matcher }.next() {
Some(m) => {
unsafe {
*span = Span {
offset: m.span().0 as c_ulong,
len: m.slice().len() as c_ulong,
}
};
true
}
None => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_matcher_free(matcher: *mut RegexMatcher<'_>) {
unsafe {
drop(Box::from_raw(matcher));
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn regex_free(regex: *mut Regex) {
let r = unsafe { Box::from_raw(regex) };
drop(r);
}