1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6
7#[cfg(test)]
8mod tests {
9 use super::*;
10 use std::ffi::c_int;
11 use std::mem;
12
13 #[cfg(feature = "approx")]
14 #[test]
15 fn reganexec() {
16 let mut preg = mem::MaybeUninit::<regex_t>::uninit();
17 if unsafe {
18 tre_regcomp(
19 preg.as_mut_ptr(),
20 b"Hello!\0".as_ptr() as *const _,
21 REG_ICASE as c_int,
22 )
23 } != 0
24 {
25 panic!("tre_regcomp");
26 }
27 let preg = unsafe { preg.assume_init() };
28
29 let params = regaparams_t {
30 cost_ins: 1,
31 cost_del: 1,
32 cost_subst: 1,
33 max_cost: 2,
34 max_del: 2,
35 max_ins: 2,
36 max_subst: 2,
37 max_err: 2,
38 };
39
40 let mut pmatch: Vec<regmatch_t> = vec![Default::default(); 1];
41 let mut amatch = regamatch_t {
42 nmatch: 1,
43 pmatch: pmatch.as_mut_ptr(),
44 ..Default::default()
45 };
46
47 if unsafe {
48 tre_reganexec(
49 &preg,
50 b"Hullo!".as_ptr() as *const _,
51 6,
52 &mut amatch,
53 params,
54 0,
55 )
56 } != 0
57 {
58 panic!("tre_regaexec");
59 }
60
61 assert_eq!(amatch.cost, 1);
62 assert_eq!(pmatch[0].rm_so, 0);
63 assert_eq!(pmatch[0].rm_eo, 6);
64 }
65
66 #[test]
67 fn regexec() {
68 let mut preg = mem::MaybeUninit::<regex_t>::uninit();
69 if unsafe {
70 tre_regcomp(
71 preg.as_mut_ptr(),
72 b"Hello(, [[:alpha:]]+)?!\0".as_ptr() as *const _,
73 (REG_EXTENDED | REG_ICASE) as c_int,
74 )
75 } != 0
76 {
77 panic!("tre_regcomp");
78 }
79
80 let preg = unsafe { preg.assume_init() };
81
82 let nmatch = 1;
83 let mut pmatch: Vec<regmatch_t> = vec![regmatch_t { rm_so: 0, rm_eo: 0 }; 1];
84 if unsafe {
85 tre_regexec(
86 &preg,
87 b"Hello!".as_ptr() as *const _,
88 nmatch,
89 pmatch.as_mut_ptr(),
90 0,
91 )
92 } != 0
93 {
94 panic!("tre_regexec");
95 }
96
97 assert!(pmatch[0].rm_so == 0, "Bad starting offset");
98 assert!(pmatch[0].rm_eo == 6, "Bad ending offset");
99
100 pmatch[0].rm_eo = 0;
101
102 let nmatch = 2;
103 pmatch.push(regmatch_t { rm_so: 0, rm_eo: 0 });
104 if unsafe {
105 tre_regexec(
106 &preg,
107 b"Hello, world!\0".as_ptr() as *const _,
108 nmatch,
109 pmatch.as_mut_ptr(),
110 0,
111 )
112 } != 0
113 {
114 panic!("tre_regexec");
115 }
116
117 assert!(pmatch[0].rm_so == 0, "Bad starting offset");
118 assert!(pmatch[0].rm_eo == 13, "Bad ending offset");
119 assert!(pmatch[1].rm_so == 5, "Bad starting offset for match group");
120 assert!(pmatch[1].rm_eo == 12, "Bad ending offset for match group");
121 }
122
123 #[test]
124 fn reguexec() {
125 use std::ffi::{c_int, c_uint, c_void};
126 #[repr(C)]
127 struct Data<'a>(pub &'a [u8], pub usize);
128
129 #[inline(never)]
130 #[no_mangle]
131 unsafe extern "C" fn get_next_char(
132 c: *mut tre_char_t,
133 pos_add: *mut c_uint,
134 context: *mut c_void,
135 ) -> c_int {
136 let data = context as *mut Data;
137 let string = (*data).0;
138 let i = (*data).1;
139
140 if i >= string.len() {
141 *c = b'\0';
142 return -1;
143 }
144
145 *c = string[i];
146 *pos_add = 1;
147 (*data).1 += 1;
148 0
149 }
150
151 #[inline(never)]
152 #[no_mangle]
153 unsafe extern "C" fn rewind(pos: usize, context: *mut c_void) {
154 let data = context as *mut Data;
155 (*data).1 = pos;
156 }
157
158 #[inline(never)]
159 #[no_mangle]
160 unsafe extern "C" fn compare(
161 pos1: usize,
162 pos2: usize,
163 len: usize,
164 context: *mut c_void,
165 ) -> c_int {
166 let data = context as *mut Data;
167 let string = (*data).0;
168 let slen = string.len();
169
170 if pos1 > slen || pos2 > slen {
171 return -1;
172 }
173
174 let mut i1_s = pos1;
175 let mut i1_e = if i1_s + len > string.len() {
176 slen - 1
177 } else {
178 i1_s + len
179 };
180
181 let mut i2_s = pos2;
182 let mut i2_e = if i2_s + len > string.len() {
183 slen - 1
184 } else {
185 i2_s + len
186 };
187
188 if (i1_s > i1_e || i2_s > i2_e) || ((i1_e - i1_s) != (i2_e - i2_s)) {
189 return -1;
191 }
192
193 if i1_s > i2_s {
194 std::mem::swap(&mut i1_s, &mut i2_s);
196 std::mem::swap(&mut i1_e, &mut i2_e);
197 }
198
199 if string[i1_s..i1_e] == string[i2_s..i2_e] {
200 return 0;
201 }
202
203 -1
204 }
205
206 let mut preg = mem::MaybeUninit::<regex_t>::uninit();
207 if unsafe {
208 tre_regcomp(
209 preg.as_mut_ptr(),
210 b"(abracadabra)(\\1)*\0".as_ptr() as *const _,
211 (REG_ICASE | REG_EXTENDED) as c_int,
212 )
213 } != 0
214 {
215 panic!("tre_regcomp");
216 }
217 let preg = unsafe { preg.assume_init() };
218
219 let string = b"abracadabraabracadabra";
220 let mut data = Data(string, 0);
221 let source = tre_str_source {
222 get_next_char: Some(get_next_char),
223 rewind: Some(rewind),
224 compare: Some(compare),
225 context: &mut data as *mut _ as *mut c_void,
226 };
227
228 let mut matches = vec![regmatch_t::default(); 1];
229 if unsafe { tre_reguexec(&preg, &source, 1, matches.as_mut_ptr(), 0) } != 0 {
230 panic!("tre_reguexec");
231 }
232
233 assert_eq!(matches[0].rm_so, 0);
234 assert_eq!(matches[0].rm_eo, 22);
235 }
236}