1use crate::{
8 ffi, translate::*, GStr, GStringPtr, MatchInfo, PtrSlice, Regex, RegexCompileFlags,
9 RegexMatchFlags,
10};
11use std::{mem, ptr};
12
13impl Regex {
14 #[doc(alias = "g_regex_get_string_number")]
15 #[doc(alias = "get_string_number")]
16 pub fn string_number(&self, name: impl IntoGStr) -> i32 {
17 name.run_with_gstr(|name| unsafe {
18 ffi::g_regex_get_string_number(self.to_glib_none().0, name.to_glib_none().0)
19 })
20 }
21
22 #[doc(alias = "g_regex_escape_nul")]
23 pub fn escape_nul(string: impl IntoGStr) -> crate::GString {
24 unsafe {
25 string.run_with_gstr(|string| {
26 from_glib_full(ffi::g_regex_escape_nul(
27 string.to_glib_none().0,
28 string.len() as _,
29 ))
30 })
31 }
32 }
33
34 #[doc(alias = "g_regex_escape_string")]
35 pub fn escape_string(string: impl IntoGStr) -> crate::GString {
36 unsafe {
37 string.run_with_gstr(|string| {
38 from_glib_full(ffi::g_regex_escape_string(
39 string.to_glib_none().0,
40 string.len() as _,
41 ))
42 })
43 }
44 }
45
46 #[doc(alias = "g_regex_check_replacement")]
47 pub fn check_replacement(replacement: impl IntoGStr) -> Result<bool, crate::Error> {
48 replacement.run_with_gstr(|replacement| unsafe {
49 let mut has_references = mem::MaybeUninit::uninit();
50 let mut error = ptr::null_mut();
51 let is_ok = ffi::g_regex_check_replacement(
52 replacement.to_glib_none().0,
53 has_references.as_mut_ptr(),
54 &mut error,
55 );
56 debug_assert_eq!(is_ok == crate::ffi::GFALSE, !error.is_null());
57 if error.is_null() {
58 Ok(from_glib(has_references.assume_init()))
59 } else {
60 Err(from_glib_full(error))
61 }
62 })
63 }
64
65 #[doc(alias = "g_regex_match_simple")]
66 pub fn match_simple(
67 pattern: impl IntoGStr,
68 string: impl IntoGStr,
69 compile_options: RegexCompileFlags,
70 match_options: RegexMatchFlags,
71 ) -> bool {
72 pattern.run_with_gstr(|pattern| {
73 string.run_with_gstr(|string| unsafe {
74 from_glib(ffi::g_regex_match_simple(
75 pattern.to_glib_none().0,
76 string.to_glib_none().0,
77 compile_options.into_glib(),
78 match_options.into_glib(),
79 ))
80 })
81 })
82 }
83
84 #[doc(alias = "g_regex_replace")]
85 pub fn replace(
86 &self,
87 string: impl IntoGStr,
88 start_position: i32,
89 replacement: impl IntoGStr,
90 match_options: RegexMatchFlags,
91 ) -> Result<crate::GString, crate::Error> {
92 unsafe {
93 string.run_with_gstr(|string| {
94 replacement.run_with_gstr(|replacement| {
95 let mut error = ptr::null_mut();
96 let ret = ffi::g_regex_replace(
97 self.to_glib_none().0,
98 string.as_ptr() as *const _,
99 string.len() as _,
100 start_position,
101 replacement.to_glib_none().0,
102 match_options.into_glib(),
103 &mut error,
104 );
105 debug_assert_eq!(ret.is_null(), !error.is_null());
106 if error.is_null() {
107 Ok(from_glib_full(ret))
108 } else {
109 Err(from_glib_full(error))
110 }
111 })
112 })
113 }
114 }
115
116 #[doc(alias = "g_regex_match_all")]
117 pub fn match_all<'input>(
118 &self,
119 string: &'input GStr,
120 match_options: RegexMatchFlags,
121 ) -> Result<MatchInfo<'input>, crate::Error> {
122 self.match_all_full(string, 0, match_options)
123 }
124
125 #[doc(alias = "g_regex_match_all_full")]
126 pub fn match_all_full<'input>(
127 &self,
128 string: &'input GStr,
129 start_position: i32,
130 match_options: RegexMatchFlags,
131 ) -> Result<MatchInfo<'input>, crate::Error> {
132 unsafe {
133 let mut match_info = ptr::null_mut();
134 let mut error = ptr::null_mut();
135 let res = ffi::g_regex_match_all_full(
136 self.to_glib_none().0,
137 string.to_glib_none().0,
138 string.len() as _,
139 start_position,
140 match_options.into_glib(),
141 &mut match_info,
142 &mut error,
143 );
144 if error.is_null() {
145 let match_info = MatchInfo::from_glib_full(match_info);
146 debug_assert_eq!(match_info.matches(), from_glib(res));
147 Ok(match_info)
148 } else {
149 debug_assert!(match_info.is_null());
150 Err(from_glib_full(error))
151 }
152 }
153 }
154
155 #[doc(alias = "g_regex_match")]
156 pub fn match_<'input>(
157 &self,
158 string: &'input GStr,
159 match_options: RegexMatchFlags,
160 ) -> Result<MatchInfo<'input>, crate::Error> {
161 self.match_full(string, 0, match_options)
162 }
163
164 #[doc(alias = "g_regex_match_full")]
165 pub fn match_full<'input>(
166 &self,
167 string: &'input GStr,
168 start_position: i32,
169 match_options: RegexMatchFlags,
170 ) -> Result<MatchInfo<'input>, crate::Error> {
171 unsafe {
172 let mut match_info = ptr::null_mut();
173 let mut error = ptr::null_mut();
174 let res = ffi::g_regex_match_full(
175 self.to_glib_none().0,
176 string.to_glib_none().0,
177 string.len() as _,
178 start_position,
179 match_options.into_glib(),
180 &mut match_info,
181 &mut error,
182 );
183 if error.is_null() {
184 let match_info = MatchInfo::from_glib_full(match_info);
185 debug_assert_eq!(match_info.matches(), from_glib(res));
186 Ok(match_info)
187 } else {
188 debug_assert!(match_info.is_null());
189 Err(from_glib_full(error))
190 }
191 }
192 }
193
194 #[doc(alias = "g_regex_replace_literal")]
195 pub fn replace_literal(
196 &self,
197 string: impl IntoGStr,
198 start_position: i32,
199 replacement: impl IntoGStr,
200 match_options: RegexMatchFlags,
201 ) -> Result<crate::GString, crate::Error> {
202 unsafe {
203 string.run_with_gstr(|string| {
204 replacement.run_with_gstr(|replacement| {
205 let mut error = ptr::null_mut();
206 let ret = ffi::g_regex_replace_literal(
207 self.to_glib_none().0,
208 string.to_glib_none().0,
209 string.len() as _,
210 start_position,
211 replacement.to_glib_none().0,
212 match_options.into_glib(),
213 &mut error,
214 );
215 debug_assert_eq!(ret.is_null(), !error.is_null());
216 if error.is_null() {
217 Ok(from_glib_full(ret))
218 } else {
219 Err(from_glib_full(error))
220 }
221 })
222 })
223 }
224 }
225
226 #[doc(alias = "g_regex_split")]
227 pub fn split(
228 &self,
229 string: impl IntoGStr,
230 match_options: RegexMatchFlags,
231 ) -> PtrSlice<GStringPtr> {
232 self.split_full(string, 0, match_options, 0)
233 .unwrap_or_default()
234 }
235
236 #[doc(alias = "g_regex_split_full")]
237 pub fn split_full(
238 &self,
239 string: impl IntoGStr,
240 start_position: i32,
241 match_options: RegexMatchFlags,
242 max_tokens: i32,
243 ) -> Result<PtrSlice<GStringPtr>, crate::Error> {
244 unsafe {
245 let mut error = ptr::null_mut();
246 string.run_with_gstr(|string| {
247 let ret = ffi::g_regex_split_full(
248 self.to_glib_none().0,
249 string.to_glib_none().0,
250 string.len() as _,
251 start_position,
252 match_options.into_glib(),
253 max_tokens,
254 &mut error,
255 );
256 debug_assert_eq!(ret.is_null(), !error.is_null());
257 if error.is_null() {
258 Ok(FromGlibPtrContainer::from_glib_full(ret))
259 } else {
260 Err(from_glib_full(error))
261 }
262 })
263 }
264 }
265
266 #[doc(alias = "g_regex_split_simple")]
267 pub fn split_simple(
268 pattern: impl IntoGStr,
269 string: impl IntoGStr,
270 compile_options: RegexCompileFlags,
271 match_options: RegexMatchFlags,
272 ) -> PtrSlice<GStringPtr> {
273 pattern.run_with_gstr(|pattern| {
274 string.run_with_gstr(|string| unsafe {
275 FromGlibPtrContainer::from_glib_full(ffi::g_regex_split_simple(
276 pattern.to_glib_none().0,
277 string.to_glib_none().0,
278 compile_options.into_glib(),
279 match_options.into_glib(),
280 ))
281 })
282 })
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289
290 #[test]
291 fn test_replace_literal() {
292 let regex = Regex::new(
293 "s[ai]mple",
294 RegexCompileFlags::OPTIMIZE,
295 RegexMatchFlags::DEFAULT,
296 )
297 .expect("Regex new")
298 .expect("Null regex");
299
300 let quote = "This is a simple sample.";
301 let result = regex
302 .replace_literal(quote, 0, "XXX", RegexMatchFlags::DEFAULT)
303 .expect("regex replace");
304
305 assert_eq!(result, "This is a XXX XXX.");
306 }
307
308 #[test]
309 fn test_split() {
310 let regex = Regex::new(
311 "s[ai]mple",
312 RegexCompileFlags::OPTIMIZE,
313 RegexMatchFlags::DEFAULT,
314 )
315 .expect("Regex new")
316 .expect("Null regex");
317
318 let quote = "This is a simple sample.";
319 let result = regex.split(quote, RegexMatchFlags::DEFAULT);
320
321 assert_eq!(result.len(), 3);
322 assert_eq!(result[0], "This is a ");
323 assert_eq!(result[1], " ");
324 assert_eq!(result[2], ".");
325 }
326
327 #[test]
328 fn test_match() {
329 let regex = Regex::new(r"\d", RegexCompileFlags::DEFAULT, RegexMatchFlags::DEFAULT)
330 .expect("Regex new")
331 .expect("Null regex");
332
333 let input = crate::GString::from("87");
334 let m = regex.match_(input.as_gstr(), RegexMatchFlags::DEFAULT);
335 let m = m.unwrap();
336 assert!(m.matches());
337 assert_eq!(m.match_count(), 1);
338 assert_eq!(m.fetch(0).as_deref(), Some("8"));
339 assert!(m.next().unwrap());
340 assert_eq!(m.fetch(0).as_deref(), Some("7"));
341 assert!(!m.next().unwrap());
342 assert!(m.fetch(0).is_none());
343
344 let input = crate::GString::from("a");
345 let m = regex.match_(input.as_gstr(), RegexMatchFlags::DEFAULT);
346 let m = m.unwrap();
347 assert!(!m.matches());
348 assert_eq!(m.match_count(), 0);
349 assert!(m.fetch(0).is_none());
350 }
351}