Branch data Line data Source code
1 : : /* GRegex -- regular expression API wrapper around PCRE.
2 : : *
3 : : * Copyright (C) 1999, 2000 Scott Wimer
4 : : * Copyright (C) 2004, Matthias Clasen <mclasen@redhat.com>
5 : : * Copyright (C) 2005 - 2007, Marco Barisione <marco@barisione.org>
6 : : * Copyright (C) 2022, Marco Trevisan <marco.trevisan@canonical.com>
7 : : *
8 : : * SPDX-License-Identifier: LGPL-2.1-or-later
9 : : *
10 : : * This library is free software; you can redistribute it and/or
11 : : * modify it under the terms of the GNU Lesser General Public
12 : : * License as published by the Free Software Foundation; either
13 : : * version 2.1 of the License, or (at your option) any later version.
14 : : *
15 : : * This library is distributed in the hope that it will be useful,
16 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : : * Lesser General Public License for more details.
19 : : *
20 : : * You should have received a copy of the GNU Lesser General Public License
21 : : * along with this library; if not, see <http://www.gnu.org/licenses/>.
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : #include <stdint.h>
27 : : #include <string.h>
28 : :
29 : : #define PCRE2_CODE_UNIT_WIDTH 8
30 : : #include <pcre2.h>
31 : :
32 : : #include "gtypes.h"
33 : : #include "gregex.h"
34 : : #include "glibintl.h"
35 : : #include "glist.h"
36 : : #include "gmessages.h"
37 : : #include "gstrfuncs.h"
38 : : #include "gatomic.h"
39 : : #include "gtestutils.h"
40 : : #include "gthread.h"
41 : :
42 : : /**
43 : : * GRegex:
44 : : *
45 : : * A `GRegex` is the "compiled" form of a regular expression pattern.
46 : : *
47 : : * `GRegex` implements regular expression pattern matching using syntax and
48 : : * semantics similar to Perl regular expression. See the
49 : : * [PCRE documentation](man:pcrepattern(3)) for the syntax definition.
50 : : *
51 : : * Some functions accept a @start_position argument, setting it differs
52 : : * from just passing over a shortened string and setting %G_REGEX_MATCH_NOTBOL
53 : : * in the case of a pattern that begins with any kind of lookbehind assertion.
54 : : * For example, consider the pattern "\Biss\B" which finds occurrences of "iss"
55 : : * in the middle of words. ("\B" matches only if the current position in the
56 : : * subject is not a word boundary.) When applied to the string "Mississipi"
57 : : * from the fourth byte, namely "issipi", it does not match, because "\B" is
58 : : * always false at the start of the subject, which is deemed to be a word
59 : : * boundary. However, if the entire string is passed , but with
60 : : * @start_position set to 4, it finds the second occurrence of "iss" because
61 : : * it is able to look behind the starting point to discover that it is
62 : : * preceded by a letter.
63 : : *
64 : : * Note that, unless you set the %G_REGEX_RAW flag, all the strings passed
65 : : * to these functions must be encoded in UTF-8. The lengths and the positions
66 : : * inside the strings are in bytes and not in characters, so, for instance,
67 : : * "\xc3\xa0" (i.e. "à") is two bytes long but it is treated as a
68 : : * single character. If you set %G_REGEX_RAW the strings can be non-valid
69 : : * UTF-8 strings and a byte is treated as a character, so "\xc3\xa0" is two
70 : : * bytes and two characters long.
71 : : *
72 : : * When matching a pattern, "\n" matches only against a "\n" character in
73 : : * the string, and "\r" matches only a "\r" character. To match any newline
74 : : * sequence use "\R". This particular group matches either the two-character
75 : : * sequence CR + LF ("\r\n"), or one of the single characters LF (linefeed,
76 : : * U+000A, "\n"), VT vertical tab, U+000B, "\v"), FF (formfeed, U+000C, "\f"),
77 : : * CR (carriage return, U+000D, "\r"), NEL (next line, U+0085), LS (line
78 : : * separator, U+2028), or PS (paragraph separator, U+2029).
79 : : *
80 : : * The behaviour of the dot, circumflex, and dollar metacharacters are
81 : : * affected by newline characters, the default is to recognize any newline
82 : : * character (the same characters recognized by "\R"). This can be changed
83 : : * with `G_REGEX_NEWLINE_CR`, `G_REGEX_NEWLINE_LF` and `G_REGEX_NEWLINE_CRLF`
84 : : * compile options, and with `G_REGEX_MATCH_NEWLINE_ANY`,
85 : : * `G_REGEX_MATCH_NEWLINE_CR`, `G_REGEX_MATCH_NEWLINE_LF` and
86 : : * `G_REGEX_MATCH_NEWLINE_CRLF` match options. These settings are also
87 : : * relevant when compiling a pattern if `G_REGEX_EXTENDED` is set, and an
88 : : * unescaped "#" outside a character class is encountered. This indicates
89 : : * a comment that lasts until after the next newline.
90 : : *
91 : : * Creating and manipulating the same `GRegex` structure from different
92 : : * threads is not a problem as `GRegex` does not modify its internal
93 : : * state between creation and destruction, on the other hand `GMatchInfo`
94 : : * is not threadsafe.
95 : : *
96 : : * The regular expressions low-level functionalities are obtained through
97 : : * the excellent [PCRE](http://www.pcre.org/) library written by Philip Hazel.
98 : : *
99 : : * Since: 2.14
100 : : */
101 : :
102 : : #define G_REGEX_PCRE_GENERIC_MASK (PCRE2_ANCHORED | \
103 : : PCRE2_NO_UTF_CHECK | \
104 : : PCRE2_ENDANCHORED)
105 : :
106 : : /* Mask of all the possible values for GRegexCompileFlags. */
107 : : #define G_REGEX_COMPILE_MASK (G_REGEX_DEFAULT | \
108 : : G_REGEX_CASELESS | \
109 : : G_REGEX_MULTILINE | \
110 : : G_REGEX_DOTALL | \
111 : : G_REGEX_EXTENDED | \
112 : : G_REGEX_ANCHORED | \
113 : : G_REGEX_DOLLAR_ENDONLY | \
114 : : G_REGEX_UNGREEDY | \
115 : : G_REGEX_RAW | \
116 : : G_REGEX_NO_AUTO_CAPTURE | \
117 : : G_REGEX_OPTIMIZE | \
118 : : G_REGEX_FIRSTLINE | \
119 : : G_REGEX_DUPNAMES | \
120 : : G_REGEX_NEWLINE_CR | \
121 : : G_REGEX_NEWLINE_LF | \
122 : : G_REGEX_NEWLINE_CRLF | \
123 : : G_REGEX_NEWLINE_ANYCRLF | \
124 : : G_REGEX_BSR_ANYCRLF)
125 : :
126 : : #define G_REGEX_PCRE2_COMPILE_MASK (PCRE2_ALLOW_EMPTY_CLASS | \
127 : : PCRE2_ALT_BSUX | \
128 : : PCRE2_AUTO_CALLOUT | \
129 : : PCRE2_CASELESS | \
130 : : PCRE2_DOLLAR_ENDONLY | \
131 : : PCRE2_DOTALL | \
132 : : PCRE2_DUPNAMES | \
133 : : PCRE2_EXTENDED | \
134 : : PCRE2_FIRSTLINE | \
135 : : PCRE2_MATCH_UNSET_BACKREF | \
136 : : PCRE2_MULTILINE | \
137 : : PCRE2_NEVER_UCP | \
138 : : PCRE2_NEVER_UTF | \
139 : : PCRE2_NO_AUTO_CAPTURE | \
140 : : PCRE2_NO_AUTO_POSSESS | \
141 : : PCRE2_NO_DOTSTAR_ANCHOR | \
142 : : PCRE2_NO_START_OPTIMIZE | \
143 : : PCRE2_UCP | \
144 : : PCRE2_UNGREEDY | \
145 : : PCRE2_UTF | \
146 : : PCRE2_NEVER_BACKSLASH_C | \
147 : : PCRE2_ALT_CIRCUMFLEX | \
148 : : PCRE2_ALT_VERBNAMES | \
149 : : PCRE2_USE_OFFSET_LIMIT | \
150 : : PCRE2_EXTENDED_MORE | \
151 : : PCRE2_LITERAL | \
152 : : PCRE2_MATCH_INVALID_UTF | \
153 : : G_REGEX_PCRE_GENERIC_MASK)
154 : :
155 : : #define G_REGEX_COMPILE_NONPCRE_MASK (PCRE2_UTF)
156 : :
157 : : /* Mask of all the possible values for GRegexMatchFlags. */
158 : : #define G_REGEX_MATCH_MASK (G_REGEX_MATCH_DEFAULT | \
159 : : G_REGEX_MATCH_ANCHORED | \
160 : : G_REGEX_MATCH_NOTBOL | \
161 : : G_REGEX_MATCH_NOTEOL | \
162 : : G_REGEX_MATCH_NOTEMPTY | \
163 : : G_REGEX_MATCH_PARTIAL | \
164 : : G_REGEX_MATCH_NEWLINE_CR | \
165 : : G_REGEX_MATCH_NEWLINE_LF | \
166 : : G_REGEX_MATCH_NEWLINE_CRLF | \
167 : : G_REGEX_MATCH_NEWLINE_ANY | \
168 : : G_REGEX_MATCH_NEWLINE_ANYCRLF | \
169 : : G_REGEX_MATCH_BSR_ANYCRLF | \
170 : : G_REGEX_MATCH_BSR_ANY | \
171 : : G_REGEX_MATCH_PARTIAL_SOFT | \
172 : : G_REGEX_MATCH_PARTIAL_HARD | \
173 : : G_REGEX_MATCH_NOTEMPTY_ATSTART)
174 : :
175 : : #define G_REGEX_PCRE2_MATCH_MASK (PCRE2_NOTBOL |\
176 : : PCRE2_NOTEOL |\
177 : : PCRE2_NOTEMPTY |\
178 : : PCRE2_NOTEMPTY_ATSTART |\
179 : : PCRE2_PARTIAL_SOFT |\
180 : : PCRE2_PARTIAL_HARD |\
181 : : PCRE2_NO_JIT |\
182 : : PCRE2_COPY_MATCHED_SUBJECT |\
183 : : G_REGEX_PCRE_GENERIC_MASK)
184 : :
185 : : /* TODO: Support PCRE2_NEWLINE_NUL */
186 : : #define G_REGEX_NEWLINE_MASK (PCRE2_NEWLINE_CR | \
187 : : PCRE2_NEWLINE_LF | \
188 : : PCRE2_NEWLINE_CRLF | \
189 : : PCRE2_NEWLINE_ANYCRLF)
190 : :
191 : : /* Some match options are not supported when using JIT as stated in the
192 : : * pcre2jit man page under the «UNSUPPORTED OPTIONS AND PATTERN ITEMS» section:
193 : : * https://www.pcre.org/current/doc/html/pcre2jit.html#SEC5
194 : : */
195 : : #define G_REGEX_PCRE2_JIT_UNSUPPORTED_OPTIONS (PCRE2_ANCHORED | \
196 : : PCRE2_ENDANCHORED)
197 : :
198 : : #define G_REGEX_COMPILE_NEWLINE_MASK (G_REGEX_NEWLINE_CR | \
199 : : G_REGEX_NEWLINE_LF | \
200 : : G_REGEX_NEWLINE_CRLF | \
201 : : G_REGEX_NEWLINE_ANYCRLF)
202 : :
203 : : #define G_REGEX_MATCH_NEWLINE_MASK (G_REGEX_MATCH_NEWLINE_CR | \
204 : : G_REGEX_MATCH_NEWLINE_LF | \
205 : : G_REGEX_MATCH_NEWLINE_CRLF | \
206 : : G_REGEX_MATCH_NEWLINE_ANY | \
207 : : G_REGEX_MATCH_NEWLINE_ANYCRLF)
208 : :
209 : : /* if the string is in UTF-8 use g_utf8_ functions, else use
210 : : * use just +/- 1. */
211 : : #define NEXT_CHAR(re, s) (((re)->compile_opts & G_REGEX_RAW) ? \
212 : : ((s) + 1) : \
213 : : g_utf8_next_char (s))
214 : : #define PREV_CHAR(re, s) (((re)->compile_opts & G_REGEX_RAW) ? \
215 : : ((s) - 1) : \
216 : : g_utf8_prev_char (s))
217 : :
218 : : struct _GMatchInfo
219 : : {
220 : : gint ref_count; /* the ref count (atomic) */
221 : : GRegex *regex; /* the regex */
222 : : uint32_t match_opts; /* pcre match options used at match time on the regex */
223 : : gint matches; /* number of matching sub patterns, guaranteed to be <= (n_subpatterns + 1) if doing a single match (rather than matching all) */
224 : : uint32_t n_subpatterns; /* total number of sub patterns in the regex */
225 : : gint pos; /* position in the string where last match left off */
226 : : uint32_t n_offsets; /* number of offsets */
227 : : gint *offsets; /* array of offsets paired 0,1 ; 2,3 ; 3,4 etc */
228 : : gint *workspace; /* workspace for pcre2_dfa_match() */
229 : : PCRE2_SIZE n_workspace; /* number of workspace elements */
230 : : const gchar *string; /* string passed to the match function */
231 : : gssize string_len; /* length of string, in bytes */
232 : : pcre2_match_context *match_context;
233 : : pcre2_match_data *match_data;
234 : : pcre2_jit_stack *jit_stack;
235 : : };
236 : :
237 : : typedef enum
238 : : {
239 : : JIT_STATUS_DEFAULT,
240 : : JIT_STATUS_ENABLED,
241 : : JIT_STATUS_DISABLED
242 : : } JITStatus;
243 : :
244 : : struct _GRegex
245 : : {
246 : : gint ref_count; /* the ref count for the immutable part (atomic) */
247 : : gchar *pattern; /* the pattern */
248 : : pcre2_code *pcre_re; /* compiled form of the pattern */
249 : : uint32_t compile_opts; /* options used at compile time on the pattern, pcre2 values */
250 : : GRegexCompileFlags orig_compile_opts; /* options used at compile time on the pattern, gregex values */
251 : : uint32_t match_opts; /* pcre2 options used at match time on the regex */
252 : : GRegexMatchFlags orig_match_opts; /* options used as default match options, gregex values */
253 : : uint32_t jit_options; /* options which were enabled for jit compiler */
254 : : JITStatus jit_status; /* indicates the status of jit compiler for this compiled regex */
255 : : /* The jit_status here does _not_ correspond to whether we used the JIT in the last invocation,
256 : : * which may be affected by match_options or a JIT_STACK_LIMIT error, but whether it was ever
257 : : * enabled for the current regex AND current set of jit_options.
258 : : * JIT_STATUS_DEFAULT means enablement was never tried,
259 : : * JIT_STATUS_ENABLED means it was tried and successful (even if we're not currently using it),
260 : : * and JIT_STATUS_DISABLED means it was tried and failed (so we shouldn't try again).
261 : : */
262 : : };
263 : :
264 : : /* TRUE if ret is an error code, FALSE otherwise. */
265 : : #define IS_PCRE2_ERROR(ret) ((ret) < PCRE2_ERROR_NOMATCH && (ret) != PCRE2_ERROR_PARTIAL)
266 : :
267 : : typedef struct _InterpolationData InterpolationData;
268 : : static gboolean interpolation_list_needs_match (GList *list);
269 : : static gboolean interpolate_replacement (const GMatchInfo *match_info,
270 : : GString *result,
271 : : gpointer data);
272 : : static GList *split_replacement (const gchar *replacement,
273 : : GError **error);
274 : : static void free_interpolation_data (InterpolationData *data);
275 : :
276 : : static uint32_t
277 : 849 : get_pcre2_compile_options (GRegexCompileFlags compile_flags)
278 : : {
279 : : /* Maps compile flags to pcre2 values */
280 : 849 : uint32_t pcre2_flags = 0;
281 : :
282 : 849 : if (compile_flags & G_REGEX_CASELESS)
283 : 26 : pcre2_flags |= PCRE2_CASELESS;
284 : 849 : if (compile_flags & G_REGEX_MULTILINE)
285 : 84 : pcre2_flags |= PCRE2_MULTILINE;
286 : 849 : if (compile_flags & G_REGEX_DOTALL)
287 : 3 : pcre2_flags |= PCRE2_DOTALL;
288 : 849 : if (compile_flags & G_REGEX_EXTENDED)
289 : 17 : pcre2_flags |= PCRE2_EXTENDED;
290 : 849 : if (compile_flags & G_REGEX_ANCHORED)
291 : 14 : pcre2_flags |= PCRE2_ANCHORED;
292 : 849 : if (compile_flags & G_REGEX_DOLLAR_ENDONLY)
293 : 0 : pcre2_flags |= PCRE2_DOLLAR_ENDONLY;
294 : 849 : if (compile_flags & G_REGEX_UNGREEDY)
295 : 0 : pcre2_flags |= PCRE2_UNGREEDY;
296 : 849 : if (!(compile_flags & G_REGEX_RAW))
297 : 838 : pcre2_flags |= PCRE2_UTF;
298 : 849 : if (compile_flags & G_REGEX_NO_AUTO_CAPTURE)
299 : 0 : pcre2_flags |= PCRE2_NO_AUTO_CAPTURE;
300 : 849 : if (compile_flags & G_REGEX_FIRSTLINE)
301 : 2 : pcre2_flags |= PCRE2_FIRSTLINE;
302 : 849 : if (compile_flags & G_REGEX_DUPNAMES)
303 : 10 : pcre2_flags |= PCRE2_DUPNAMES;
304 : :
305 : 849 : return pcre2_flags & G_REGEX_PCRE2_COMPILE_MASK;
306 : : }
307 : :
308 : : static uint32_t
309 : 1753 : get_pcre2_match_options (GRegexMatchFlags match_flags,
310 : : GRegexCompileFlags compile_flags)
311 : : {
312 : : /* Maps match flags to pcre2 values */
313 : 1753 : uint32_t pcre2_flags = 0;
314 : :
315 : 1753 : if (match_flags & G_REGEX_MATCH_ANCHORED)
316 : 43 : pcre2_flags |= PCRE2_ANCHORED;
317 : 1753 : if (match_flags & G_REGEX_MATCH_NOTBOL)
318 : 2 : pcre2_flags |= PCRE2_NOTBOL;
319 : 1753 : if (match_flags & G_REGEX_MATCH_NOTEOL)
320 : 2 : pcre2_flags |= PCRE2_NOTEOL;
321 : 1753 : if (match_flags & G_REGEX_MATCH_NOTEMPTY)
322 : 3 : pcre2_flags |= PCRE2_NOTEMPTY;
323 : 1753 : if (match_flags & G_REGEX_MATCH_PARTIAL_SOFT)
324 : 37 : pcre2_flags |= PCRE2_PARTIAL_SOFT;
325 : 1753 : if (match_flags & G_REGEX_MATCH_PARTIAL_HARD)
326 : 8 : pcre2_flags |= PCRE2_PARTIAL_HARD;
327 : 1753 : if (match_flags & G_REGEX_MATCH_NOTEMPTY_ATSTART)
328 : 2 : pcre2_flags |= PCRE2_NOTEMPTY_ATSTART;
329 : :
330 : 1753 : if (compile_flags & G_REGEX_RAW)
331 : 23 : pcre2_flags |= PCRE2_NO_UTF_CHECK;
332 : :
333 : 1753 : return pcre2_flags & G_REGEX_PCRE2_MATCH_MASK;
334 : : }
335 : :
336 : : static GRegexCompileFlags
337 : 17 : g_regex_compile_flags_from_pcre2 (uint32_t pcre2_flags)
338 : : {
339 : 17 : GRegexCompileFlags compile_flags = G_REGEX_DEFAULT;
340 : :
341 : 17 : if (pcre2_flags & PCRE2_CASELESS)
342 : 0 : compile_flags |= G_REGEX_CASELESS;
343 : 17 : if (pcre2_flags & PCRE2_MULTILINE)
344 : 0 : compile_flags |= G_REGEX_MULTILINE;
345 : 17 : if (pcre2_flags & PCRE2_DOTALL)
346 : 0 : compile_flags |= G_REGEX_DOTALL;
347 : 17 : if (pcre2_flags & PCRE2_EXTENDED)
348 : 0 : compile_flags |= G_REGEX_EXTENDED;
349 : 17 : if (pcre2_flags & PCRE2_ANCHORED)
350 : 1 : compile_flags |= G_REGEX_ANCHORED;
351 : 17 : if (pcre2_flags & PCRE2_DOLLAR_ENDONLY)
352 : 0 : compile_flags |= G_REGEX_DOLLAR_ENDONLY;
353 : 17 : if (pcre2_flags & PCRE2_UNGREEDY)
354 : 0 : compile_flags |= G_REGEX_UNGREEDY;
355 : 17 : if (!(pcre2_flags & PCRE2_UTF))
356 : 1 : compile_flags |= G_REGEX_RAW;
357 : 17 : if (pcre2_flags & PCRE2_NO_AUTO_CAPTURE)
358 : 0 : compile_flags |= G_REGEX_NO_AUTO_CAPTURE;
359 : 17 : if (pcre2_flags & PCRE2_FIRSTLINE)
360 : 0 : compile_flags |= G_REGEX_FIRSTLINE;
361 : 17 : if (pcre2_flags & PCRE2_DUPNAMES)
362 : 1 : compile_flags |= G_REGEX_DUPNAMES;
363 : :
364 : 17 : return compile_flags & G_REGEX_COMPILE_MASK;
365 : : }
366 : :
367 : : static GRegexMatchFlags
368 : 17 : g_regex_match_flags_from_pcre2 (uint32_t pcre2_flags)
369 : : {
370 : 17 : GRegexMatchFlags match_flags = G_REGEX_MATCH_DEFAULT;
371 : :
372 : 17 : if (pcre2_flags & PCRE2_ANCHORED)
373 : 0 : match_flags |= G_REGEX_MATCH_ANCHORED;
374 : 17 : if (pcre2_flags & PCRE2_NOTBOL)
375 : 0 : match_flags |= G_REGEX_MATCH_NOTBOL;
376 : 17 : if (pcre2_flags & PCRE2_NOTEOL)
377 : 0 : match_flags |= G_REGEX_MATCH_NOTEOL;
378 : 17 : if (pcre2_flags & PCRE2_NOTEMPTY)
379 : 1 : match_flags |= G_REGEX_MATCH_NOTEMPTY;
380 : 17 : if (pcre2_flags & PCRE2_PARTIAL_SOFT)
381 : 0 : match_flags |= G_REGEX_MATCH_PARTIAL_SOFT;
382 : 17 : if (pcre2_flags & PCRE2_PARTIAL_HARD)
383 : 0 : match_flags |= G_REGEX_MATCH_PARTIAL_HARD;
384 : 17 : if (pcre2_flags & PCRE2_NOTEMPTY_ATSTART)
385 : 0 : match_flags |= G_REGEX_MATCH_NOTEMPTY_ATSTART;
386 : :
387 : 17 : return (match_flags & G_REGEX_MATCH_MASK);
388 : : }
389 : :
390 : : static uint32_t
391 : 826 : get_pcre2_newline_compile_options (GRegexCompileFlags compile_flags)
392 : : {
393 : 826 : compile_flags &= G_REGEX_COMPILE_NEWLINE_MASK;
394 : :
395 : 826 : switch (compile_flags)
396 : : {
397 : 8 : case G_REGEX_NEWLINE_CR:
398 : 8 : return PCRE2_NEWLINE_CR;
399 : 6 : case G_REGEX_NEWLINE_LF:
400 : 6 : return PCRE2_NEWLINE_LF;
401 : 6 : case G_REGEX_NEWLINE_CRLF:
402 : 6 : return PCRE2_NEWLINE_CRLF;
403 : 4 : case G_REGEX_NEWLINE_ANYCRLF:
404 : 4 : return PCRE2_NEWLINE_ANYCRLF;
405 : 802 : default:
406 : 802 : if (compile_flags != 0)
407 : 1 : return 0;
408 : :
409 : 801 : return PCRE2_NEWLINE_ANY;
410 : : }
411 : : }
412 : :
413 : : static uint32_t
414 : 875 : get_pcre2_newline_match_options (GRegexMatchFlags match_flags)
415 : : {
416 : 875 : switch (match_flags & G_REGEX_MATCH_NEWLINE_MASK)
417 : : {
418 : 10 : case G_REGEX_MATCH_NEWLINE_CR:
419 : 10 : return PCRE2_NEWLINE_CR;
420 : 12 : case G_REGEX_MATCH_NEWLINE_LF:
421 : 12 : return PCRE2_NEWLINE_LF;
422 : 12 : case G_REGEX_MATCH_NEWLINE_CRLF:
423 : 12 : return PCRE2_NEWLINE_CRLF;
424 : 8 : case G_REGEX_MATCH_NEWLINE_ANY:
425 : 8 : return PCRE2_NEWLINE_ANY;
426 : 7 : case G_REGEX_MATCH_NEWLINE_ANYCRLF:
427 : 7 : return PCRE2_NEWLINE_ANYCRLF;
428 : 826 : default:
429 : 826 : return 0;
430 : : }
431 : : }
432 : :
433 : : static uint32_t
434 : 873 : get_pcre2_bsr_compile_options (GRegexCompileFlags compile_flags)
435 : : {
436 : 873 : if (compile_flags & G_REGEX_BSR_ANYCRLF)
437 : 0 : return PCRE2_BSR_ANYCRLF;
438 : :
439 : 873 : return PCRE2_BSR_UNICODE;
440 : : }
441 : :
442 : : static uint32_t
443 : 874 : get_pcre2_bsr_match_options (GRegexMatchFlags match_flags)
444 : : {
445 : 874 : if (match_flags & G_REGEX_MATCH_BSR_ANYCRLF)
446 : 1 : return PCRE2_BSR_ANYCRLF;
447 : :
448 : 873 : if (match_flags & G_REGEX_MATCH_BSR_ANY)
449 : 0 : return PCRE2_BSR_UNICODE;
450 : :
451 : 873 : return 0;
452 : : }
453 : :
454 : : static char *
455 : 2 : get_pcre2_error_string (int errcode)
456 : : {
457 : : PCRE2_UCHAR8 error_msg[2048];
458 : : int err_length;
459 : :
460 : 2 : err_length = pcre2_get_error_message (errcode, error_msg,
461 : : G_N_ELEMENTS (error_msg));
462 : :
463 : 2 : if (err_length <= 0)
464 : 0 : return NULL;
465 : :
466 : : /* The array is always filled with a trailing zero */
467 : 2 : g_assert ((size_t) err_length < G_N_ELEMENTS (error_msg));
468 : 2 : return g_memdup2 (error_msg, err_length + 1);
469 : : }
470 : :
471 : : static const gchar *
472 : 0 : translate_match_error (gint errcode)
473 : : {
474 : 0 : switch (errcode)
475 : : {
476 : 0 : case PCRE2_ERROR_NOMATCH:
477 : : /* not an error */
478 : 0 : break;
479 : 0 : case PCRE2_ERROR_NULL:
480 : : /* NULL argument, this should not happen in GRegex */
481 : 0 : g_critical ("A NULL argument was passed to PCRE");
482 : 0 : break;
483 : 0 : case PCRE2_ERROR_BADOPTION:
484 : 0 : return "bad options";
485 : 0 : case PCRE2_ERROR_BADMAGIC:
486 : 0 : return _("corrupted object");
487 : 0 : case PCRE2_ERROR_NOMEMORY:
488 : 0 : return _("out of memory");
489 : 0 : case PCRE2_ERROR_NOSUBSTRING:
490 : : /* not used by pcre2_match() */
491 : 0 : break;
492 : 0 : case PCRE2_ERROR_MATCHLIMIT:
493 : : case PCRE2_ERROR_CALLOUT:
494 : : /* callouts are not implemented */
495 : 0 : break;
496 : 0 : case PCRE2_ERROR_BADUTFOFFSET:
497 : : /* we do not check if strings are valid */
498 : 0 : break;
499 : 0 : case PCRE2_ERROR_PARTIAL:
500 : : /* not an error */
501 : 0 : break;
502 : 0 : case PCRE2_ERROR_INTERNAL:
503 : 0 : return _("internal error");
504 : 0 : case PCRE2_ERROR_DFA_UITEM:
505 : 0 : return _("the pattern contains items not supported for partial matching");
506 : 0 : case PCRE2_ERROR_DFA_UCOND:
507 : 0 : return _("back references as conditions are not supported for partial matching");
508 : 0 : case PCRE2_ERROR_DFA_WSSIZE:
509 : : /* handled expanding the workspace */
510 : 0 : break;
511 : 0 : case PCRE2_ERROR_DFA_RECURSE:
512 : : case PCRE2_ERROR_RECURSIONLIMIT:
513 : 0 : return _("recursion limit reached");
514 : 0 : case PCRE2_ERROR_BADOFFSET:
515 : 0 : return _("bad offset");
516 : 0 : case PCRE2_ERROR_RECURSELOOP:
517 : 0 : return _("recursion loop");
518 : 0 : case PCRE2_ERROR_JIT_BADOPTION:
519 : : /* should not happen in GRegex since we check modes before each match */
520 : 0 : return _("matching mode is requested that was not compiled for JIT");
521 : 0 : default:
522 : 0 : break;
523 : : }
524 : 0 : return NULL;
525 : : }
526 : :
527 : : static char *
528 : 0 : get_match_error_message (int errcode)
529 : : {
530 : 0 : const char *msg = translate_match_error (errcode);
531 : : char *error_string;
532 : :
533 : 0 : if (msg)
534 : 0 : return g_strdup (msg);
535 : :
536 : 0 : error_string = get_pcre2_error_string (errcode);
537 : :
538 : 0 : if (error_string)
539 : 0 : return error_string;
540 : :
541 : 0 : return g_strdup (_("unknown error"));
542 : : }
543 : :
544 : : static void
545 : 58 : translate_compile_error (gint *errcode, const gchar **errmsg)
546 : : {
547 : : /* If errcode is known we put the translatable error message in
548 : : * errmsg. If errcode is unknown we put the generic
549 : : * G_REGEX_ERROR_COMPILE error code in errcode.
550 : : * Note that there can be more PCRE errors with the same GRegexError
551 : : * and that some PCRE errors are useless for us.
552 : : */
553 : 58 : gint original_errcode = *errcode;
554 : :
555 : 58 : *errcode = -1;
556 : 58 : *errmsg = NULL;
557 : :
558 : 58 : switch (original_errcode)
559 : : {
560 : 4 : case PCRE2_ERROR_END_BACKSLASH:
561 : 4 : *errcode = G_REGEX_ERROR_STRAY_BACKSLASH;
562 : 4 : *errmsg = _("\\ at end of pattern");
563 : 4 : break;
564 : 1 : case PCRE2_ERROR_END_BACKSLASH_C:
565 : 1 : *errcode = G_REGEX_ERROR_MISSING_CONTROL_CHAR;
566 : 1 : *errmsg = _("\\c at end of pattern");
567 : 1 : break;
568 : 1 : case PCRE2_ERROR_UNKNOWN_ESCAPE:
569 : : case PCRE2_ERROR_UNSUPPORTED_ESCAPE_SEQUENCE:
570 : 1 : *errcode = G_REGEX_ERROR_UNRECOGNIZED_ESCAPE;
571 : 1 : *errmsg = _("unrecognized character following \\");
572 : 1 : break;
573 : 1 : case PCRE2_ERROR_QUANTIFIER_OUT_OF_ORDER:
574 : 1 : *errcode = G_REGEX_ERROR_QUANTIFIERS_OUT_OF_ORDER;
575 : 1 : *errmsg = _("numbers out of order in {} quantifier");
576 : 1 : break;
577 : 1 : case PCRE2_ERROR_QUANTIFIER_TOO_BIG:
578 : 1 : *errcode = G_REGEX_ERROR_QUANTIFIER_TOO_BIG;
579 : 1 : *errmsg = _("number too big in {} quantifier");
580 : 1 : break;
581 : 5 : case PCRE2_ERROR_MISSING_SQUARE_BRACKET:
582 : 5 : *errcode = G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS;
583 : 5 : *errmsg = _("missing terminating ] for character class");
584 : 5 : break;
585 : 1 : case PCRE2_ERROR_ESCAPE_INVALID_IN_CLASS:
586 : 1 : *errcode = G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS;
587 : 1 : *errmsg = _("invalid escape sequence in character class");
588 : 1 : break;
589 : 1 : case PCRE2_ERROR_CLASS_RANGE_ORDER:
590 : 1 : *errcode = G_REGEX_ERROR_RANGE_OUT_OF_ORDER;
591 : 1 : *errmsg = _("range out of order in character class");
592 : 1 : break;
593 : 3 : case PCRE2_ERROR_QUANTIFIER_INVALID:
594 : : case PCRE2_ERROR_INTERNAL_UNEXPECTED_REPEAT:
595 : 3 : *errcode = G_REGEX_ERROR_NOTHING_TO_REPEAT;
596 : 3 : *errmsg = _("nothing to repeat");
597 : 3 : break;
598 : 1 : case PCRE2_ERROR_INVALID_AFTER_PARENS_QUERY:
599 : 1 : *errcode = G_REGEX_ERROR_UNRECOGNIZED_CHARACTER;
600 : 1 : *errmsg = _("unrecognized character after (? or (?-");
601 : 1 : break;
602 : 1 : case PCRE2_ERROR_POSIX_CLASS_NOT_IN_CLASS:
603 : 1 : *errcode = G_REGEX_ERROR_POSIX_NAMED_CLASS_OUTSIDE_CLASS;
604 : 1 : *errmsg = _("POSIX named classes are supported only within a class");
605 : 1 : break;
606 : 1 : case PCRE2_ERROR_POSIX_NO_SUPPORT_COLLATING:
607 : 1 : *errcode = G_REGEX_ERROR_POSIX_COLLATING_ELEMENTS_NOT_SUPPORTED;
608 : 1 : *errmsg = _("POSIX collating elements are not supported");
609 : 1 : break;
610 : 5 : case PCRE2_ERROR_MISSING_CLOSING_PARENTHESIS:
611 : : case PCRE2_ERROR_UNMATCHED_CLOSING_PARENTHESIS:
612 : : case PCRE2_ERROR_PARENS_QUERY_R_MISSING_CLOSING:
613 : 5 : *errcode = G_REGEX_ERROR_UNMATCHED_PARENTHESIS;
614 : 5 : *errmsg = _("missing terminating )");
615 : 5 : break;
616 : 4 : case PCRE2_ERROR_BAD_SUBPATTERN_REFERENCE:
617 : 4 : *errcode = G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE;
618 : 4 : *errmsg = _("reference to non-existent subpattern");
619 : 4 : break;
620 : 1 : case PCRE2_ERROR_MISSING_COMMENT_CLOSING:
621 : 1 : *errcode = G_REGEX_ERROR_UNTERMINATED_COMMENT;
622 : 1 : *errmsg = _("missing ) after comment");
623 : 1 : break;
624 : 0 : case PCRE2_ERROR_PATTERN_TOO_LARGE:
625 : 0 : *errcode = G_REGEX_ERROR_EXPRESSION_TOO_LARGE;
626 : 0 : *errmsg = _("regular expression is too large");
627 : 0 : break;
628 : 1 : case PCRE2_ERROR_MISSING_CONDITION_CLOSING:
629 : 1 : *errcode = G_REGEX_ERROR_MALFORMED_CONDITION;
630 : 1 : *errmsg = _("malformed number or name after (?(");
631 : 1 : break;
632 : 1 : case PCRE2_ERROR_LOOKBEHIND_NOT_FIXED_LENGTH:
633 : 1 : *errcode = G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND;
634 : 1 : *errmsg = _("lookbehind assertion is not fixed length");
635 : 1 : break;
636 : 1 : case PCRE2_ERROR_TOO_MANY_CONDITION_BRANCHES:
637 : 1 : *errcode = G_REGEX_ERROR_TOO_MANY_CONDITIONAL_BRANCHES;
638 : 1 : *errmsg = _("conditional group contains more than two branches");
639 : 1 : break;
640 : 2 : case PCRE2_ERROR_CONDITION_ASSERTION_EXPECTED:
641 : 2 : *errcode = G_REGEX_ERROR_ASSERTION_EXPECTED;
642 : 2 : *errmsg = _("assertion expected after (?(");
643 : 2 : break;
644 : 1 : case PCRE2_ERROR_BAD_RELATIVE_REFERENCE:
645 : 1 : *errcode = G_REGEX_ERROR_INVALID_RELATIVE_REFERENCE;
646 : 1 : *errmsg = _("a numbered reference must not be zero");
647 : 1 : break;
648 : 1 : case PCRE2_ERROR_UNKNOWN_POSIX_CLASS:
649 : 1 : *errcode = G_REGEX_ERROR_UNKNOWN_POSIX_CLASS_NAME;
650 : 1 : *errmsg = _("unknown POSIX class name");
651 : 1 : break;
652 : 2 : case PCRE2_ERROR_CODE_POINT_TOO_BIG:
653 : : case PCRE2_ERROR_INVALID_HEXADECIMAL:
654 : 2 : *errcode = G_REGEX_ERROR_HEX_CODE_TOO_LARGE;
655 : 2 : *errmsg = _("character value in \\x{...} sequence is too large");
656 : 2 : break;
657 : 1 : case PCRE2_ERROR_LOOKBEHIND_INVALID_BACKSLASH_C:
658 : 1 : *errcode = G_REGEX_ERROR_SINGLE_BYTE_MATCH_IN_LOOKBEHIND;
659 : 1 : *errmsg = _("\\C not allowed in lookbehind assertion");
660 : 1 : break;
661 : 1 : case PCRE2_ERROR_MISSING_NAME_TERMINATOR:
662 : 1 : *errcode = G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR;
663 : 1 : *errmsg = _("missing terminator in subpattern name");
664 : 1 : break;
665 : 2 : case PCRE2_ERROR_DUPLICATE_SUBPATTERN_NAME:
666 : 2 : *errcode = G_REGEX_ERROR_DUPLICATE_SUBPATTERN_NAME;
667 : 2 : *errmsg = _("two named subpatterns have the same name");
668 : 2 : break;
669 : 0 : case PCRE2_ERROR_MALFORMED_UNICODE_PROPERTY:
670 : 0 : *errcode = G_REGEX_ERROR_MALFORMED_PROPERTY;
671 : 0 : *errmsg = _("malformed \\P or \\p sequence");
672 : 0 : break;
673 : 0 : case PCRE2_ERROR_UNKNOWN_UNICODE_PROPERTY:
674 : 0 : *errcode = G_REGEX_ERROR_UNKNOWN_PROPERTY;
675 : 0 : *errmsg = _("unknown property name after \\P or \\p");
676 : 0 : break;
677 : 0 : case PCRE2_ERROR_SUBPATTERN_NAME_TOO_LONG:
678 : 0 : *errcode = G_REGEX_ERROR_SUBPATTERN_NAME_TOO_LONG;
679 : 0 : *errmsg = _("subpattern name is too long (maximum 32 characters)");
680 : 0 : break;
681 : 0 : case PCRE2_ERROR_TOO_MANY_NAMED_SUBPATTERNS:
682 : 0 : *errcode = G_REGEX_ERROR_TOO_MANY_SUBPATTERNS;
683 : 0 : *errmsg = _("too many named subpatterns (maximum 10,000)");
684 : 0 : break;
685 : 1 : case PCRE2_ERROR_OCTAL_BYTE_TOO_BIG:
686 : 1 : *errcode = G_REGEX_ERROR_INVALID_OCTAL_VALUE;
687 : 1 : *errmsg = _("octal value is greater than \\377");
688 : 1 : break;
689 : 1 : case PCRE2_ERROR_DEFINE_TOO_MANY_BRANCHES:
690 : 1 : *errcode = G_REGEX_ERROR_TOO_MANY_BRANCHES_IN_DEFINE;
691 : 1 : *errmsg = _("DEFINE group contains more than one branch");
692 : 1 : break;
693 : 0 : case PCRE2_ERROR_INTERNAL_UNKNOWN_NEWLINE:
694 : 0 : *errcode = G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS;
695 : 0 : *errmsg = _("inconsistent NEWLINE options");
696 : 0 : break;
697 : 1 : case PCRE2_ERROR_BACKSLASH_G_SYNTAX:
698 : 1 : *errcode = G_REGEX_ERROR_MISSING_BACK_REFERENCE;
699 : 1 : *errmsg = _("\\g is not followed by a braced, angle-bracketed, or quoted name or "
700 : : "number, or by a plain number");
701 : 1 : break;
702 : 0 : case PCRE2_ERROR_VERB_ARGUMENT_NOT_ALLOWED:
703 : 0 : *errcode = G_REGEX_ERROR_BACKTRACKING_CONTROL_VERB_ARGUMENT_FORBIDDEN;
704 : 0 : *errmsg = _("an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)");
705 : 0 : break;
706 : 1 : case PCRE2_ERROR_VERB_UNKNOWN:
707 : 1 : *errcode = G_REGEX_ERROR_UNKNOWN_BACKTRACKING_CONTROL_VERB;
708 : 1 : *errmsg = _("(*VERB) not recognized");
709 : 1 : break;
710 : 0 : case PCRE2_ERROR_SUBPATTERN_NUMBER_TOO_BIG:
711 : 0 : *errcode = G_REGEX_ERROR_NUMBER_TOO_BIG;
712 : 0 : *errmsg = _("number is too big");
713 : 0 : break;
714 : 2 : case PCRE2_ERROR_SUBPATTERN_NAME_EXPECTED:
715 : 2 : *errcode = G_REGEX_ERROR_MISSING_SUBPATTERN_NAME;
716 : 2 : *errmsg = _("missing subpattern name after (?&");
717 : 2 : break;
718 : 1 : case PCRE2_ERROR_SUBPATTERN_NAMES_MISMATCH:
719 : 1 : *errcode = G_REGEX_ERROR_EXTRA_SUBPATTERN_NAME;
720 : 1 : *errmsg = _("different names for subpatterns of the same number are not allowed");
721 : 1 : break;
722 : 1 : case PCRE2_ERROR_MARK_MISSING_ARGUMENT:
723 : 1 : *errcode = G_REGEX_ERROR_BACKTRACKING_CONTROL_VERB_ARGUMENT_REQUIRED;
724 : 1 : *errmsg = _("(*MARK) must have an argument");
725 : 1 : break;
726 : 1 : case PCRE2_ERROR_BACKSLASH_C_SYNTAX:
727 : 1 : *errcode = G_REGEX_ERROR_INVALID_CONTROL_CHAR;
728 : 1 : *errmsg = _( "\\c must be followed by an ASCII character");
729 : 1 : break;
730 : 1 : case PCRE2_ERROR_BACKSLASH_K_SYNTAX:
731 : 1 : *errcode = G_REGEX_ERROR_MISSING_NAME;
732 : 1 : *errmsg = _("\\k is not followed by a braced, angle-bracketed, or quoted name");
733 : 1 : break;
734 : 1 : case PCRE2_ERROR_BACKSLASH_N_IN_CLASS:
735 : 1 : *errcode = G_REGEX_ERROR_NOT_SUPPORTED_IN_CLASS;
736 : 1 : *errmsg = _("\\N is not supported in a class");
737 : 1 : break;
738 : 1 : case PCRE2_ERROR_VERB_NAME_TOO_LONG:
739 : 1 : *errcode = G_REGEX_ERROR_NAME_TOO_LONG;
740 : 1 : *errmsg = _("name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)");
741 : 1 : break;
742 : 0 : case PCRE2_ERROR_INTERNAL_CODE_OVERFLOW:
743 : 0 : *errcode = G_REGEX_ERROR_INTERNAL;
744 : 0 : *errmsg = _("code overflow");
745 : 0 : break;
746 : 0 : case PCRE2_ERROR_UNRECOGNIZED_AFTER_QUERY_P:
747 : 0 : *errcode = G_REGEX_ERROR_UNRECOGNIZED_CHARACTER;
748 : 0 : *errmsg = _("unrecognized character after (?P");
749 : 0 : break;
750 : 0 : case PCRE2_ERROR_INTERNAL_OVERRAN_WORKSPACE:
751 : 0 : *errcode = G_REGEX_ERROR_INTERNAL;
752 : 0 : *errmsg = _("overran compiling workspace");
753 : 0 : break;
754 : 0 : case PCRE2_ERROR_INTERNAL_MISSING_SUBPATTERN:
755 : 0 : *errcode = G_REGEX_ERROR_INTERNAL;
756 : 0 : *errmsg = _("previously-checked referenced subpattern not found");
757 : 0 : break;
758 : 0 : case PCRE2_ERROR_HEAP_FAILED:
759 : : case PCRE2_ERROR_INTERNAL_PARSED_OVERFLOW:
760 : : case PCRE2_ERROR_UNICODE_NOT_SUPPORTED:
761 : : case PCRE2_ERROR_UNICODE_DISALLOWED_CODE_POINT:
762 : : case PCRE2_ERROR_NO_SURROGATES_IN_UTF16:
763 : : case PCRE2_ERROR_INTERNAL_BAD_CODE_LOOKBEHINDS:
764 : : case PCRE2_ERROR_UNICODE_PROPERTIES_UNAVAILABLE:
765 : : case PCRE2_ERROR_INTERNAL_STUDY_ERROR:
766 : : case PCRE2_ERROR_UTF_IS_DISABLED:
767 : : case PCRE2_ERROR_UCP_IS_DISABLED:
768 : : case PCRE2_ERROR_INTERNAL_BAD_CODE_AUTO_POSSESS:
769 : : case PCRE2_ERROR_BACKSLASH_C_LIBRARY_DISABLED:
770 : : case PCRE2_ERROR_INTERNAL_BAD_CODE:
771 : : case PCRE2_ERROR_INTERNAL_BAD_CODE_IN_SKIP:
772 : 0 : *errcode = G_REGEX_ERROR_INTERNAL;
773 : 0 : break;
774 : 2 : case PCRE2_ERROR_INVALID_SUBPATTERN_NAME:
775 : : case PCRE2_ERROR_CLASS_INVALID_RANGE:
776 : : case PCRE2_ERROR_ZERO_RELATIVE_REFERENCE:
777 : : case PCRE2_ERROR_PARENTHESES_STACK_CHECK:
778 : : case PCRE2_ERROR_LOOKBEHIND_TOO_COMPLICATED:
779 : : case PCRE2_ERROR_CALLOUT_NUMBER_TOO_BIG:
780 : : case PCRE2_ERROR_MISSING_CALLOUT_CLOSING:
781 : : case PCRE2_ERROR_ESCAPE_INVALID_IN_VERB:
782 : : case PCRE2_ERROR_NULL_PATTERN:
783 : : case PCRE2_ERROR_BAD_OPTIONS:
784 : : case PCRE2_ERROR_PARENTHESES_NEST_TOO_DEEP:
785 : : case PCRE2_ERROR_BACKSLASH_O_MISSING_BRACE:
786 : : case PCRE2_ERROR_INVALID_OCTAL:
787 : : case PCRE2_ERROR_CALLOUT_STRING_TOO_LONG:
788 : : case PCRE2_ERROR_BACKSLASH_U_CODE_POINT_TOO_BIG:
789 : : case PCRE2_ERROR_MISSING_OCTAL_OR_HEX_DIGITS:
790 : : case PCRE2_ERROR_VERSION_CONDITION_SYNTAX:
791 : : case PCRE2_ERROR_CALLOUT_NO_STRING_DELIMITER:
792 : : case PCRE2_ERROR_CALLOUT_BAD_STRING_DELIMITER:
793 : : case PCRE2_ERROR_BACKSLASH_C_CALLER_DISABLED:
794 : : case PCRE2_ERROR_QUERY_BARJX_NEST_TOO_DEEP:
795 : : case PCRE2_ERROR_PATTERN_TOO_COMPLICATED:
796 : : case PCRE2_ERROR_LOOKBEHIND_TOO_LONG:
797 : : case PCRE2_ERROR_PATTERN_STRING_TOO_LONG:
798 : : case PCRE2_ERROR_BAD_LITERAL_OPTIONS:
799 : : default:
800 : 2 : *errcode = G_REGEX_ERROR_COMPILE;
801 : 2 : break;
802 : : }
803 : :
804 : 58 : g_assert (*errcode != -1);
805 : 58 : }
806 : :
807 : : /* GMatchInfo */
808 : :
809 : : static GMatchInfo *
810 : 904 : match_info_new (const GRegex *regex,
811 : : const gchar *string,
812 : : gint string_len,
813 : : gint start_position,
814 : : GRegexMatchFlags match_options,
815 : : gboolean is_dfa)
816 : : {
817 : : GMatchInfo *match_info;
818 : :
819 : 904 : if (string_len < 0)
820 : 753 : string_len = strlen (string);
821 : :
822 : 904 : match_info = g_new0 (GMatchInfo, 1);
823 : 904 : match_info->ref_count = 1;
824 : 904 : match_info->regex = g_regex_ref ((GRegex *)regex);
825 : 904 : match_info->string = string;
826 : 904 : match_info->string_len = string_len;
827 : 904 : match_info->matches = PCRE2_ERROR_NOMATCH;
828 : 904 : match_info->pos = start_position;
829 : 904 : match_info->match_opts =
830 : 904 : get_pcre2_match_options (match_options, regex->orig_compile_opts);
831 : :
832 : 904 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_CAPTURECOUNT,
833 : 904 : &match_info->n_subpatterns);
834 : :
835 : 904 : match_info->match_context = pcre2_match_context_create (NULL);
836 : :
837 : 904 : if (is_dfa)
838 : : {
839 : : /* These values should be enough for most cases, if they are not
840 : : * enough g_regex_match_all_full() will expand them. */
841 : 26 : match_info->n_workspace = 100;
842 : 26 : match_info->workspace = g_new (gint, match_info->n_workspace);
843 : : }
844 : :
845 : 904 : match_info->n_offsets = 2;
846 : 904 : match_info->offsets = g_new0 (gint, match_info->n_offsets);
847 : : /* Set an invalid position for the previous match. */
848 : 904 : match_info->offsets[0] = -1;
849 : 904 : match_info->offsets[1] = -1;
850 : :
851 : 1808 : match_info->match_data = pcre2_match_data_create_from_pattern (
852 : 904 : match_info->regex->pcre_re,
853 : : NULL);
854 : :
855 : 904 : return match_info;
856 : : }
857 : :
858 : : static gboolean
859 : 776 : recalc_match_offsets (GMatchInfo *match_info,
860 : : GError **error)
861 : : {
862 : : PCRE2_SIZE *ovector;
863 : 776 : uint32_t ovector_size = 0;
864 : : uint32_t pre_n_offset;
865 : : uint32_t i;
866 : :
867 : 776 : g_assert (!IS_PCRE2_ERROR (match_info->matches));
868 : :
869 : 776 : if (match_info->matches == PCRE2_ERROR_PARTIAL)
870 : 28 : ovector_size = 1;
871 : 748 : else if (match_info->matches > 0)
872 : 748 : ovector_size = match_info->matches;
873 : :
874 : 776 : g_assert (ovector_size != 0);
875 : :
876 : 776 : if (pcre2_get_ovector_count (match_info->match_data) < ovector_size)
877 : : {
878 : 0 : g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
879 : : _("Error while matching regular expression %s: %s"),
880 : 0 : match_info->regex->pattern, _("code overflow"));
881 : 0 : return FALSE;
882 : : }
883 : :
884 : 776 : pre_n_offset = match_info->n_offsets;
885 : 776 : match_info->n_offsets = ovector_size * 2;
886 : 776 : ovector = pcre2_get_ovector_pointer (match_info->match_data);
887 : :
888 : 776 : if (match_info->n_offsets != pre_n_offset)
889 : : {
890 : 132 : match_info->offsets = g_realloc_n (match_info->offsets,
891 : 132 : match_info->n_offsets,
892 : : sizeof (gint));
893 : : }
894 : :
895 : 2810 : for (i = 0; i < match_info->n_offsets; i++)
896 : : {
897 : 2034 : match_info->offsets[i] = (int) ovector[i];
898 : : }
899 : :
900 : 776 : return TRUE;
901 : : }
902 : :
903 : : static JITStatus
904 : 1142 : enable_jit_with_match_options (GMatchInfo *match_info,
905 : : uint32_t match_options)
906 : : {
907 : : gint retval;
908 : : uint32_t old_jit_options, new_jit_options;
909 : :
910 : 1142 : if (!(match_info->regex->orig_compile_opts & G_REGEX_OPTIMIZE))
911 : 734 : return JIT_STATUS_DISABLED;
912 : :
913 : 408 : if (match_info->regex->jit_status == JIT_STATUS_DISABLED)
914 : 0 : return JIT_STATUS_DISABLED;
915 : :
916 : 408 : if (match_options & G_REGEX_PCRE2_JIT_UNSUPPORTED_OPTIONS)
917 : 22 : return JIT_STATUS_DISABLED;
918 : :
919 : 386 : old_jit_options = match_info->regex->jit_options;
920 : 386 : new_jit_options = old_jit_options | PCRE2_JIT_COMPLETE;
921 : 386 : if (match_options & PCRE2_PARTIAL_HARD)
922 : 4 : new_jit_options |= PCRE2_JIT_PARTIAL_HARD;
923 : 386 : if (match_options & PCRE2_PARTIAL_SOFT)
924 : 18 : new_jit_options |= PCRE2_JIT_PARTIAL_SOFT;
925 : :
926 : : /* no new options enabled */
927 : 386 : if (new_jit_options == old_jit_options)
928 : : {
929 : 140 : g_assert (match_info->regex->jit_status != JIT_STATUS_DEFAULT);
930 : 140 : return match_info->regex->jit_status;
931 : : }
932 : :
933 : 246 : retval = pcre2_jit_compile (match_info->regex->pcre_re, new_jit_options);
934 : 246 : if (retval == 0)
935 : : {
936 : 246 : match_info->regex->jit_status = JIT_STATUS_ENABLED;
937 : :
938 : 246 : match_info->regex->jit_options = new_jit_options;
939 : : /* Set min stack size for JIT to 32KiB and max to 512KiB */
940 : 246 : match_info->jit_stack = pcre2_jit_stack_create (1 << 15, 1 << 19, NULL);
941 : 246 : pcre2_jit_stack_assign (match_info->match_context, NULL, match_info->jit_stack);
942 : : }
943 : : else
944 : : {
945 : 0 : match_info->regex->jit_status = JIT_STATUS_DISABLED;
946 : :
947 : 0 : switch (retval)
948 : : {
949 : 0 : case PCRE2_ERROR_NOMEMORY:
950 : 0 : g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
951 : : "but JIT was unable to allocate executable memory for the "
952 : : "compiler. Falling back to interpretive code.");
953 : 0 : break;
954 : 0 : case PCRE2_ERROR_JIT_BADOPTION:
955 : 0 : g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
956 : : "but JIT support is not available. Falling back to "
957 : : "interpretive code.");
958 : 0 : break;
959 : 0 : default:
960 : 0 : g_debug ("JIT compilation was requested with G_REGEX_OPTIMIZE, "
961 : : "but request for JIT support had unexpectedly failed (error %d). "
962 : : "Falling back to interpretive code.",
963 : : retval);
964 : 0 : break;
965 : : }
966 : : }
967 : :
968 : 246 : return match_info->regex->jit_status;
969 : :
970 : : g_assert_not_reached ();
971 : : }
972 : :
973 : : /**
974 : : * g_match_info_get_regex:
975 : : * @match_info: a #GMatchInfo
976 : : *
977 : : * Returns #GRegex object used in @match_info. It belongs to Glib
978 : : * and must not be freed. Use g_regex_ref() if you need to keep it
979 : : * after you free @match_info object.
980 : : *
981 : : * Returns: (transfer none): #GRegex object used in @match_info
982 : : *
983 : : * Since: 2.14
984 : : */
985 : : GRegex *
986 : 24 : g_match_info_get_regex (const GMatchInfo *match_info)
987 : : {
988 : 24 : g_return_val_if_fail (match_info != NULL, NULL);
989 : 24 : return match_info->regex;
990 : : }
991 : :
992 : : /**
993 : : * g_match_info_get_string:
994 : : * @match_info: a #GMatchInfo
995 : : *
996 : : * Returns the string searched with @match_info. This is the
997 : : * string passed to g_regex_match() or g_regex_replace() so
998 : : * you may not free it before calling this function.
999 : : *
1000 : : * Returns: the string searched with @match_info
1001 : : *
1002 : : * Since: 2.14
1003 : : */
1004 : : const gchar *
1005 : 24 : g_match_info_get_string (const GMatchInfo *match_info)
1006 : : {
1007 : 24 : g_return_val_if_fail (match_info != NULL, NULL);
1008 : 24 : return match_info->string;
1009 : : }
1010 : :
1011 : : /**
1012 : : * g_match_info_ref:
1013 : : * @match_info: a #GMatchInfo
1014 : : *
1015 : : * Increases reference count of @match_info by 1.
1016 : : *
1017 : : * Returns: @match_info
1018 : : *
1019 : : * Since: 2.30
1020 : : */
1021 : : GMatchInfo *
1022 : 21 : g_match_info_ref (GMatchInfo *match_info)
1023 : : {
1024 : 21 : g_return_val_if_fail (match_info != NULL, NULL);
1025 : 21 : g_atomic_int_inc (&match_info->ref_count);
1026 : 21 : return match_info;
1027 : : }
1028 : :
1029 : : /**
1030 : : * g_match_info_unref:
1031 : : * @match_info: a #GMatchInfo
1032 : : *
1033 : : * Decreases reference count of @match_info by 1. When reference count drops
1034 : : * to zero, it frees all the memory associated with the match_info structure.
1035 : : *
1036 : : * Since: 2.30
1037 : : */
1038 : : void
1039 : 925 : g_match_info_unref (GMatchInfo *match_info)
1040 : : {
1041 : 925 : if (g_atomic_int_dec_and_test (&match_info->ref_count))
1042 : : {
1043 : 904 : g_regex_unref (match_info->regex);
1044 : 904 : if (match_info->match_context)
1045 : 904 : pcre2_match_context_free (match_info->match_context);
1046 : 904 : if (match_info->jit_stack)
1047 : 246 : pcre2_jit_stack_free (match_info->jit_stack);
1048 : 904 : if (match_info->match_data)
1049 : 904 : pcre2_match_data_free (match_info->match_data);
1050 : 904 : g_free (match_info->offsets);
1051 : 904 : g_free (match_info->workspace);
1052 : 904 : g_free (match_info);
1053 : : }
1054 : 925 : }
1055 : :
1056 : : /**
1057 : : * g_match_info_free:
1058 : : * @match_info: (nullable): a #GMatchInfo, or %NULL
1059 : : *
1060 : : * If @match_info is not %NULL, calls g_match_info_unref(); otherwise does
1061 : : * nothing.
1062 : : *
1063 : : * Since: 2.14
1064 : : */
1065 : : void
1066 : 885 : g_match_info_free (GMatchInfo *match_info)
1067 : : {
1068 : 885 : if (match_info == NULL)
1069 : 4 : return;
1070 : :
1071 : 881 : g_match_info_unref (match_info);
1072 : : }
1073 : :
1074 : : /**
1075 : : * g_match_info_next:
1076 : : * @match_info: a #GMatchInfo structure
1077 : : * @error: location to store the error occurring, or %NULL to ignore errors
1078 : : *
1079 : : * Scans for the next match using the same parameters of the previous
1080 : : * call to g_regex_match_full() or g_regex_match() that returned
1081 : : * @match_info.
1082 : : *
1083 : : * The match is done on the string passed to the match function, so you
1084 : : * cannot free it before calling this function.
1085 : : *
1086 : : * Returns: %TRUE is the string matched, %FALSE otherwise
1087 : : *
1088 : : * Since: 2.14
1089 : : */
1090 : : gboolean
1091 : 1168 : g_match_info_next (GMatchInfo *match_info,
1092 : : GError **error)
1093 : : {
1094 : : JITStatus jit_status;
1095 : : gint prev_match_start;
1096 : : gint prev_match_end;
1097 : : uint32_t opts;
1098 : :
1099 : 1168 : g_return_val_if_fail (match_info != NULL, FALSE);
1100 : 1168 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1101 : 1168 : g_return_val_if_fail (match_info->pos >= 0, FALSE);
1102 : :
1103 : 1167 : prev_match_start = match_info->offsets[0];
1104 : 1167 : prev_match_end = match_info->offsets[1];
1105 : :
1106 : 1167 : if (match_info->pos > match_info->string_len)
1107 : : {
1108 : : /* we have reached the end of the string */
1109 : 25 : match_info->pos = -1;
1110 : 25 : match_info->matches = PCRE2_ERROR_NOMATCH;
1111 : 25 : return FALSE;
1112 : : }
1113 : :
1114 : 1142 : opts = match_info->regex->match_opts | match_info->match_opts;
1115 : :
1116 : 1142 : jit_status = enable_jit_with_match_options (match_info, opts);
1117 : 1142 : if (jit_status == JIT_STATUS_ENABLED)
1118 : : {
1119 : 772 : match_info->matches = pcre2_jit_match (match_info->regex->pcre_re,
1120 : 386 : (PCRE2_SPTR8) match_info->string,
1121 : 386 : match_info->string_len,
1122 : 386 : match_info->pos,
1123 : : opts,
1124 : : match_info->match_data,
1125 : : match_info->match_context);
1126 : : /* if the JIT stack limit was reached, fall back to non-JIT matching in
1127 : : * the next conditional statement */
1128 : 386 : if (match_info->matches == PCRE2_ERROR_JIT_STACKLIMIT)
1129 : : {
1130 : 3 : g_debug ("PCRE2 JIT stack limit reached, falling back to "
1131 : : "non-optimized matching.");
1132 : 3 : opts |= PCRE2_NO_JIT;
1133 : 3 : jit_status = JIT_STATUS_DISABLED;
1134 : : }
1135 : : }
1136 : :
1137 : 1142 : if (jit_status != JIT_STATUS_ENABLED)
1138 : : {
1139 : 759 : match_info->matches = pcre2_match (match_info->regex->pcre_re,
1140 : 759 : (PCRE2_SPTR8) match_info->string,
1141 : 759 : match_info->string_len,
1142 : 759 : match_info->pos,
1143 : : opts,
1144 : : match_info->match_data,
1145 : : match_info->match_context);
1146 : : }
1147 : :
1148 : 1142 : if (IS_PCRE2_ERROR (match_info->matches))
1149 : : {
1150 : 0 : gchar *error_msg = get_match_error_message (match_info->matches);
1151 : :
1152 : 0 : g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
1153 : : _("Error while matching regular expression %s: %s"),
1154 : 0 : match_info->regex->pattern, error_msg);
1155 : 0 : g_clear_pointer (&error_msg, g_free);
1156 : 0 : return FALSE;
1157 : : }
1158 : 1142 : else if (match_info->matches == 0)
1159 : : {
1160 : : /* info->offsets is too small. */
1161 : 0 : match_info->n_offsets *= 2;
1162 : 0 : match_info->offsets = g_realloc_n (match_info->offsets,
1163 : 0 : match_info->n_offsets,
1164 : : sizeof (gint));
1165 : :
1166 : 0 : pcre2_match_data_free (match_info->match_data);
1167 : 0 : match_info->match_data = pcre2_match_data_create (match_info->n_offsets, NULL);
1168 : :
1169 : 0 : return g_match_info_next (match_info, error);
1170 : : }
1171 : 1142 : else if (match_info->matches == PCRE2_ERROR_NOMATCH)
1172 : : {
1173 : : /* We're done with this match info */
1174 : 386 : match_info->pos = -1;
1175 : 386 : return FALSE;
1176 : : }
1177 : : else
1178 : 756 : if (!recalc_match_offsets (match_info, error))
1179 : 0 : return FALSE;
1180 : :
1181 : : /* avoid infinite loops if the pattern is an empty string or something
1182 : : * equivalent */
1183 : 756 : if (match_info->pos == match_info->offsets[1])
1184 : : {
1185 : 83 : if (match_info->pos > match_info->string_len)
1186 : : {
1187 : : /* we have reached the end of the string */
1188 : 0 : match_info->pos = -1;
1189 : 0 : match_info->matches = PCRE2_ERROR_NOMATCH;
1190 : 0 : return FALSE;
1191 : : }
1192 : :
1193 : 83 : match_info->pos = NEXT_CHAR (match_info->regex,
1194 : 83 : &match_info->string[match_info->pos]) -
1195 : 83 : match_info->string;
1196 : : }
1197 : : else
1198 : : {
1199 : 673 : match_info->pos = match_info->offsets[1];
1200 : : }
1201 : :
1202 : 756 : g_assert (match_info->matches < 0 ||
1203 : : (uint32_t) match_info->matches <= match_info->n_subpatterns + 1);
1204 : :
1205 : : /* it's possible to get two identical matches when we are matching
1206 : : * empty strings, for instance if the pattern is "(?=[A-Z0-9])" and
1207 : : * the string is "RegExTest" we have:
1208 : : * - search at position 0: match from 0 to 0
1209 : : * - search at position 1: match from 3 to 3
1210 : : * - search at position 3: match from 3 to 3 (duplicate)
1211 : : * - search at position 4: match from 5 to 5
1212 : : * - search at position 5: match from 5 to 5 (duplicate)
1213 : : * - search at position 6: no match -> stop
1214 : : * so we have to ignore the duplicates.
1215 : : * see bug #515944: http://bugzilla.gnome.org/show_bug.cgi?id=515944 */
1216 : 756 : if (match_info->matches >= 0 &&
1217 : 728 : prev_match_start == match_info->offsets[0] &&
1218 : 6 : prev_match_end == match_info->offsets[1])
1219 : : {
1220 : : /* ignore this match and search the next one */
1221 : 6 : return g_match_info_next (match_info, error);
1222 : : }
1223 : :
1224 : 750 : return match_info->matches >= 0;
1225 : : }
1226 : :
1227 : : /**
1228 : : * g_match_info_matches:
1229 : : * @match_info: a #GMatchInfo structure
1230 : : *
1231 : : * Returns whether the previous match operation succeeded.
1232 : : *
1233 : : * Returns: %TRUE if the previous match operation succeeded,
1234 : : * %FALSE otherwise
1235 : : *
1236 : : * Since: 2.14
1237 : : */
1238 : : gboolean
1239 : 348 : g_match_info_matches (const GMatchInfo *match_info)
1240 : : {
1241 : 348 : g_return_val_if_fail (match_info != NULL, FALSE);
1242 : :
1243 : 348 : return match_info->matches >= 0;
1244 : : }
1245 : :
1246 : : /**
1247 : : * g_match_info_get_match_count:
1248 : : * @match_info: a #GMatchInfo structure
1249 : : *
1250 : : * Retrieves the number of matched substrings (including substring 0,
1251 : : * that is the whole matched text), so 1 is returned if the pattern
1252 : : * has no substrings in it and 0 is returned if the match failed.
1253 : : *
1254 : : * If the last match was obtained using the DFA algorithm, that is
1255 : : * using g_regex_match_all() or g_regex_match_all_full(), the retrieved
1256 : : * count is not that of the number of capturing parentheses but that of
1257 : : * the number of matched substrings.
1258 : : *
1259 : : * Returns: Number of matched substrings, or -1 if an error occurred
1260 : : *
1261 : : * Since: 2.14
1262 : : */
1263 : : gint
1264 : 129 : g_match_info_get_match_count (const GMatchInfo *match_info)
1265 : : {
1266 : 129 : g_return_val_if_fail (match_info, -1);
1267 : :
1268 : 129 : if (match_info->matches == PCRE2_ERROR_NOMATCH)
1269 : : /* no match */
1270 : 12 : return 0;
1271 : 117 : else if (match_info->matches < PCRE2_ERROR_NOMATCH)
1272 : : /* error */
1273 : 0 : return -1;
1274 : : else
1275 : : /* match */
1276 : 117 : return match_info->matches;
1277 : : }
1278 : :
1279 : : /**
1280 : : * g_match_info_is_partial_match:
1281 : : * @match_info: a #GMatchInfo structure
1282 : : *
1283 : : * Usually if the string passed to g_regex_match*() matches as far as
1284 : : * it goes, but is too short to match the entire pattern, %FALSE is
1285 : : * returned. There are circumstances where it might be helpful to
1286 : : * distinguish this case from other cases in which there is no match.
1287 : : *
1288 : : * Consider, for example, an application where a human is required to
1289 : : * type in data for a field with specific formatting requirements. An
1290 : : * example might be a date in the form ddmmmyy, defined by the pattern
1291 : : * "^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$".
1292 : : * If the application sees the user’s keystrokes one by one, and can
1293 : : * check that what has been typed so far is potentially valid, it is
1294 : : * able to raise an error as soon as a mistake is made.
1295 : : *
1296 : : * GRegex supports the concept of partial matching by means of the
1297 : : * %G_REGEX_MATCH_PARTIAL_SOFT and %G_REGEX_MATCH_PARTIAL_HARD flags.
1298 : : * When they are used, the return code for
1299 : : * g_regex_match() or g_regex_match_full() is, as usual, %TRUE
1300 : : * for a complete match, %FALSE otherwise. But, when these functions
1301 : : * return %FALSE, you can check if the match was partial calling
1302 : : * g_match_info_is_partial_match().
1303 : : *
1304 : : * The difference between %G_REGEX_MATCH_PARTIAL_SOFT and
1305 : : * %G_REGEX_MATCH_PARTIAL_HARD is that when a partial match is encountered
1306 : : * with %G_REGEX_MATCH_PARTIAL_SOFT, matching continues to search for a
1307 : : * possible complete match, while with %G_REGEX_MATCH_PARTIAL_HARD matching
1308 : : * stops at the partial match.
1309 : : * When both %G_REGEX_MATCH_PARTIAL_SOFT and %G_REGEX_MATCH_PARTIAL_HARD
1310 : : * are set, the latter takes precedence.
1311 : : *
1312 : : * There were formerly some restrictions on the pattern for partial matching.
1313 : : * The restrictions no longer apply.
1314 : : *
1315 : : * See pcrepartial(3) for more information on partial matching.
1316 : : *
1317 : : * Returns: %TRUE if the match was partial, %FALSE otherwise
1318 : : *
1319 : : * Since: 2.14
1320 : : */
1321 : : gboolean
1322 : 44 : g_match_info_is_partial_match (const GMatchInfo *match_info)
1323 : : {
1324 : 44 : g_return_val_if_fail (match_info != NULL, FALSE);
1325 : :
1326 : 44 : return match_info->matches == PCRE2_ERROR_PARTIAL;
1327 : : }
1328 : :
1329 : : /**
1330 : : * g_match_info_expand_references:
1331 : : * @match_info: (nullable): a #GMatchInfo or %NULL
1332 : : * @string_to_expand: the string to expand
1333 : : * @error: location to store the error occurring, or %NULL to ignore errors
1334 : : *
1335 : : * Returns a new string containing the text in @string_to_expand with
1336 : : * references and escape sequences expanded. References refer to the last
1337 : : * match done with @string against @regex and have the same syntax used by
1338 : : * g_regex_replace().
1339 : : *
1340 : : * The @string_to_expand must be UTF-8 encoded even if %G_REGEX_RAW was
1341 : : * passed to g_regex_new().
1342 : : *
1343 : : * The backreferences are extracted from the string passed to the match
1344 : : * function, so you cannot call this function after freeing the string.
1345 : : *
1346 : : * @match_info may be %NULL in which case @string_to_expand must not
1347 : : * contain references. For instance "foo\n" does not refer to an actual
1348 : : * pattern and '\n' merely will be replaced with \n character,
1349 : : * while to expand "\0" (whole match) one needs the result of a match.
1350 : : * Use g_regex_check_replacement() to find out whether @string_to_expand
1351 : : * contains references.
1352 : : *
1353 : : * Returns: (nullable): the expanded string, or %NULL if an error occurred
1354 : : *
1355 : : * Since: 2.14
1356 : : */
1357 : : gchar *
1358 : 66 : g_match_info_expand_references (const GMatchInfo *match_info,
1359 : : const gchar *string_to_expand,
1360 : : GError **error)
1361 : : {
1362 : : GString *result;
1363 : : GList *list;
1364 : 66 : GError *tmp_error = NULL;
1365 : :
1366 : 66 : g_return_val_if_fail (string_to_expand != NULL, NULL);
1367 : 66 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1368 : :
1369 : 66 : list = split_replacement (string_to_expand, &tmp_error);
1370 : 66 : if (tmp_error != NULL)
1371 : : {
1372 : 11 : g_propagate_error (error, tmp_error);
1373 : 11 : return NULL;
1374 : : }
1375 : :
1376 : 55 : if (!match_info && interpolation_list_needs_match (list))
1377 : : {
1378 : 0 : g_critical ("String '%s' contains references to the match, can't "
1379 : : "expand references without GMatchInfo object",
1380 : : string_to_expand);
1381 : 0 : return NULL;
1382 : : }
1383 : :
1384 : 55 : result = g_string_sized_new (strlen (string_to_expand));
1385 : 55 : interpolate_replacement (match_info, result, list);
1386 : :
1387 : 55 : g_list_free_full (list, (GDestroyNotify) free_interpolation_data);
1388 : :
1389 : 55 : return g_string_free (result, FALSE);
1390 : : }
1391 : :
1392 : : /**
1393 : : * g_match_info_fetch:
1394 : : * @match_info: #GMatchInfo structure
1395 : : * @match_num: number of the sub expression
1396 : : *
1397 : : * Retrieves the text matching the @match_num'th capturing
1398 : : * parentheses. 0 is the full text of the match, 1 is the first paren
1399 : : * set, 2 the second, and so on.
1400 : : *
1401 : : * If @match_num is a valid sub pattern but it didn't match anything
1402 : : * (e.g. sub pattern 1, matching "b" against "(a)?b") then an empty
1403 : : * string is returned.
1404 : : *
1405 : : * If the match was obtained using the DFA algorithm, that is using
1406 : : * g_regex_match_all() or g_regex_match_all_full(), the retrieved
1407 : : * string is not that of a set of parentheses but that of a matched
1408 : : * substring. Substrings are matched in reverse order of length, so
1409 : : * 0 is the longest match.
1410 : : *
1411 : : * The string is fetched from the string passed to the match function,
1412 : : * so you cannot call this function after freeing the string.
1413 : : *
1414 : : * Returns: (nullable): The matched substring, or %NULL if an error
1415 : : * occurred. You have to free the string yourself
1416 : : *
1417 : : * Since: 2.14
1418 : : */
1419 : : gchar *
1420 : 247 : g_match_info_fetch (const GMatchInfo *match_info,
1421 : : gint match_num)
1422 : : {
1423 : 247 : gchar *match = NULL;
1424 : : gint start, end;
1425 : :
1426 : 247 : g_return_val_if_fail (match_info != NULL, NULL);
1427 : 247 : g_return_val_if_fail (match_num >= 0, NULL);
1428 : :
1429 : : /* match_num does not exist or it didn't matched, i.e. matching "b"
1430 : : * against "(a)?b" then group 0 is empty. */
1431 : 247 : if (!g_match_info_fetch_pos (match_info, match_num, &start, &end))
1432 : 8 : match = NULL;
1433 : 239 : else if (start == -1)
1434 : 8 : match = g_strdup ("");
1435 : : else
1436 : 231 : match = g_strndup (&match_info->string[start], end - start);
1437 : :
1438 : 247 : return match;
1439 : : }
1440 : :
1441 : : /**
1442 : : * g_match_info_fetch_pos:
1443 : : * @match_info: #GMatchInfo structure
1444 : : * @match_num: number of the sub expression
1445 : : * @start_pos: (out) (optional): pointer to location where to store
1446 : : * the start position, or %NULL
1447 : : * @end_pos: (out) (optional): pointer to location where to store
1448 : : * the end position, or %NULL
1449 : : *
1450 : : * Retrieves the position in bytes of the @match_num'th capturing
1451 : : * parentheses. 0 is the full text of the match, 1 is the first
1452 : : * paren set, 2 the second, and so on.
1453 : : *
1454 : : * If @match_num is a valid sub pattern but it didn't match anything
1455 : : * (e.g. sub pattern 1, matching "b" against "(a)?b") then @start_pos
1456 : : * and @end_pos are set to -1 and %TRUE is returned.
1457 : : *
1458 : : * If the match was obtained using the DFA algorithm, that is using
1459 : : * g_regex_match_all() or g_regex_match_all_full(), the retrieved
1460 : : * position is not that of a set of parentheses but that of a matched
1461 : : * substring. Substrings are matched in reverse order of length, so
1462 : : * 0 is the longest match.
1463 : : *
1464 : : * Returns: %TRUE if the position was fetched, %FALSE otherwise. If
1465 : : * the position cannot be fetched, @start_pos and @end_pos are left
1466 : : * unchanged
1467 : : *
1468 : : * Since: 2.14
1469 : : */
1470 : : gboolean
1471 : 439 : g_match_info_fetch_pos (const GMatchInfo *match_info,
1472 : : gint match_num,
1473 : : gint *start_pos,
1474 : : gint *end_pos)
1475 : : {
1476 : 439 : g_return_val_if_fail (match_info != NULL, FALSE);
1477 : 439 : g_return_val_if_fail (match_num >= 0, FALSE);
1478 : :
1479 : : /* check whether there was an error */
1480 : 439 : if (match_info->matches < 0)
1481 : 56 : return FALSE;
1482 : :
1483 : : /* make sure the sub expression number they're requesting is less than
1484 : : * the total number of sub expressions in the regex. When matching all
1485 : : * (g_regex_match_all()), also compare against the number of matches */
1486 : 383 : if ((uint32_t) match_num >= MAX (match_info->n_subpatterns + 1, (uint32_t) match_info->matches))
1487 : 14 : return FALSE;
1488 : :
1489 : 369 : if (start_pos != NULL)
1490 : 369 : *start_pos = (match_num < match_info->matches) ? match_info->offsets[2 * match_num] : -1;
1491 : :
1492 : 369 : if (end_pos != NULL)
1493 : 357 : *end_pos = (match_num < match_info->matches) ? match_info->offsets[2 * match_num + 1] : -1;
1494 : :
1495 : 369 : return TRUE;
1496 : : }
1497 : :
1498 : : /*
1499 : : * Returns number of first matched subpattern with name @name.
1500 : : * There may be more than one in case when DUPNAMES is used,
1501 : : * and not all subpatterns with that name match;
1502 : : * pcre2_substring_number_from_name() does not work in that case.
1503 : : */
1504 : : static gint
1505 : 46 : get_matched_substring_number (const GMatchInfo *match_info,
1506 : : const gchar *name)
1507 : : {
1508 : : gint entrysize;
1509 : : PCRE2_SPTR first, last;
1510 : : guchar *entry;
1511 : :
1512 : 46 : if (!(match_info->regex->compile_opts & PCRE2_DUPNAMES))
1513 : 20 : return pcre2_substring_number_from_name (match_info->regex->pcre_re, (PCRE2_SPTR8) name);
1514 : :
1515 : : /* This code is analogous to code from pcre2_substring.c:
1516 : : * pcre2_substring_get_byname() */
1517 : 26 : entrysize = pcre2_substring_nametable_scan (match_info->regex->pcre_re,
1518 : : (PCRE2_SPTR8) name,
1519 : : &first,
1520 : : &last);
1521 : :
1522 : 26 : if (entrysize <= 0)
1523 : 0 : return entrysize;
1524 : :
1525 : 44 : for (entry = (guchar*) first; entry <= (guchar*) last; entry += entrysize)
1526 : : {
1527 : 43 : guint n = (entry[0] << 8) + entry[1];
1528 : 43 : if (n * 2 < match_info->n_offsets && match_info->offsets[n * 2] >= 0)
1529 : 25 : return n;
1530 : : }
1531 : :
1532 : 1 : return (first[0] << 8) + first[1];
1533 : : }
1534 : :
1535 : : /**
1536 : : * g_match_info_fetch_named:
1537 : : * @match_info: #GMatchInfo structure
1538 : : * @name: name of the subexpression
1539 : : *
1540 : : * Retrieves the text matching the capturing parentheses named @name.
1541 : : *
1542 : : * If @name is a valid sub pattern name but it didn't match anything
1543 : : * (e.g. sub pattern `"X"`, matching `"b"` against `"(?P<X>a)?b"`)
1544 : : * then an empty string is returned.
1545 : : *
1546 : : * The string is fetched from the string passed to the match function,
1547 : : * so you cannot call this function after freeing the string.
1548 : : *
1549 : : * Returns: (nullable): The matched substring, or %NULL if an error
1550 : : * occurred. You have to free the string yourself
1551 : : *
1552 : : * Since: 2.14
1553 : : */
1554 : : gchar *
1555 : 27 : g_match_info_fetch_named (const GMatchInfo *match_info,
1556 : : const gchar *name)
1557 : : {
1558 : : gint num;
1559 : :
1560 : 27 : g_return_val_if_fail (match_info != NULL, NULL);
1561 : 27 : g_return_val_if_fail (name != NULL, NULL);
1562 : :
1563 : 27 : num = get_matched_substring_number (match_info, name);
1564 : 27 : if (num < 0)
1565 : 1 : return NULL;
1566 : : else
1567 : 26 : return g_match_info_fetch (match_info, num);
1568 : : }
1569 : :
1570 : : /**
1571 : : * g_match_info_fetch_named_pos:
1572 : : * @match_info: #GMatchInfo structure
1573 : : * @name: name of the subexpression
1574 : : * @start_pos: (out) (optional): pointer to location where to store
1575 : : * the start position, or %NULL
1576 : : * @end_pos: (out) (optional): pointer to location where to store
1577 : : * the end position, or %NULL
1578 : : *
1579 : : * Retrieves the position in bytes of the capturing parentheses named @name.
1580 : : *
1581 : : * If @name is a valid sub pattern name but it didn't match anything
1582 : : * (e.g. sub pattern `"X"`, matching `"b"` against `"(?P<X>a)?b"`)
1583 : : * then @start_pos and @end_pos are set to -1 and %TRUE is returned.
1584 : : *
1585 : : * Returns: %TRUE if the position was fetched, %FALSE otherwise.
1586 : : * If the position cannot be fetched, @start_pos and @end_pos
1587 : : * are left unchanged.
1588 : : *
1589 : : * Since: 2.14
1590 : : */
1591 : : gboolean
1592 : 19 : g_match_info_fetch_named_pos (const GMatchInfo *match_info,
1593 : : const gchar *name,
1594 : : gint *start_pos,
1595 : : gint *end_pos)
1596 : : {
1597 : : gint num;
1598 : :
1599 : 19 : g_return_val_if_fail (match_info != NULL, FALSE);
1600 : 19 : g_return_val_if_fail (name != NULL, FALSE);
1601 : :
1602 : 19 : num = get_matched_substring_number (match_info, name);
1603 : 19 : if (num < 0)
1604 : 1 : return FALSE;
1605 : :
1606 : 18 : return g_match_info_fetch_pos (match_info, num, start_pos, end_pos);
1607 : : }
1608 : :
1609 : : /**
1610 : : * g_match_info_fetch_all:
1611 : : * @match_info: a #GMatchInfo structure
1612 : : *
1613 : : * Bundles up pointers to each of the matching substrings from a match
1614 : : * and stores them in an array of gchar pointers. The first element in
1615 : : * the returned array is the match number 0, i.e. the entire matched
1616 : : * text.
1617 : : *
1618 : : * If a sub pattern didn't match anything (e.g. sub pattern 1, matching
1619 : : * "b" against "(a)?b") then an empty string is inserted.
1620 : : *
1621 : : * If the last match was obtained using the DFA algorithm, that is using
1622 : : * g_regex_match_all() or g_regex_match_all_full(), the retrieved
1623 : : * strings are not that matched by sets of parentheses but that of the
1624 : : * matched substring. Substrings are matched in reverse order of length,
1625 : : * so the first one is the longest match.
1626 : : *
1627 : : * The strings are fetched from the string passed to the match function,
1628 : : * so you cannot call this function after freeing the string.
1629 : : *
1630 : : * Returns: (transfer full): a %NULL-terminated array of gchar *
1631 : : * pointers. It must be freed using g_strfreev(). If the previous
1632 : : * match failed %NULL is returned
1633 : : *
1634 : : * Since: 2.14
1635 : : */
1636 : : gchar **
1637 : 13 : g_match_info_fetch_all (const GMatchInfo *match_info)
1638 : : {
1639 : : gchar **result;
1640 : : gint i;
1641 : :
1642 : 13 : g_return_val_if_fail (match_info != NULL, NULL);
1643 : :
1644 : 13 : if (match_info->matches < 0)
1645 : 2 : return NULL;
1646 : :
1647 : 11 : result = g_new (gchar *, match_info->matches + 1);
1648 : 35 : for (i = 0; i < match_info->matches; i++)
1649 : 24 : result[i] = g_match_info_fetch (match_info, i);
1650 : 11 : result[i] = NULL;
1651 : :
1652 : 11 : return result;
1653 : : }
1654 : :
1655 : :
1656 : : /* GRegex */
1657 : :
1658 : 130 : G_DEFINE_QUARK (g-regex-error-quark, g_regex_error)
1659 : :
1660 : : /**
1661 : : * g_regex_ref:
1662 : : * @regex: a #GRegex
1663 : : *
1664 : : * Increases reference count of @regex by 1.
1665 : : *
1666 : : * Returns: @regex
1667 : : *
1668 : : * Since: 2.14
1669 : : */
1670 : : GRegex *
1671 : 905 : g_regex_ref (GRegex *regex)
1672 : : {
1673 : 905 : g_return_val_if_fail (regex != NULL, NULL);
1674 : 905 : g_atomic_int_inc (®ex->ref_count);
1675 : 905 : return regex;
1676 : : }
1677 : :
1678 : : /**
1679 : : * g_regex_unref:
1680 : : * @regex: a #GRegex
1681 : : *
1682 : : * Decreases reference count of @regex by 1. When reference count drops
1683 : : * to zero, it frees all the memory associated with the regex structure.
1684 : : *
1685 : : * Since: 2.14
1686 : : */
1687 : : void
1688 : 1691 : g_regex_unref (GRegex *regex)
1689 : : {
1690 : 1691 : g_return_if_fail (regex != NULL);
1691 : :
1692 : 1691 : if (g_atomic_int_dec_and_test (®ex->ref_count))
1693 : : {
1694 : 786 : g_free (regex->pattern);
1695 : 786 : if (regex->pcre_re != NULL)
1696 : 786 : pcre2_code_free (regex->pcre_re);
1697 : 786 : g_free (regex);
1698 : : }
1699 : : }
1700 : :
1701 : : static pcre2_code * regex_compile (const gchar *pattern,
1702 : : uint32_t compile_options,
1703 : : uint32_t newline_options,
1704 : : uint32_t bsr_options,
1705 : : GError **error);
1706 : :
1707 : : static uint32_t get_pcre2_inline_compile_options (pcre2_code *re,
1708 : : uint32_t compile_options);
1709 : :
1710 : : /**
1711 : : * g_regex_new:
1712 : : * @pattern: the regular expression
1713 : : * @compile_options: compile options for the regular expression, or 0
1714 : : * @match_options: match options for the regular expression, or 0
1715 : : * @error: return location for a #GError
1716 : : *
1717 : : * Compiles the regular expression to an internal form, and does
1718 : : * the initial setup of the #GRegex structure.
1719 : : *
1720 : : * Returns: (nullable): a #GRegex structure or %NULL if an error occurred. Call
1721 : : * g_regex_unref() when you are done with it
1722 : : *
1723 : : * Since: 2.14
1724 : : */
1725 : : GRegex *
1726 : 849 : g_regex_new (const gchar *pattern,
1727 : : GRegexCompileFlags compile_options,
1728 : : GRegexMatchFlags match_options,
1729 : : GError **error)
1730 : : {
1731 : : GRegex *regex;
1732 : : pcre2_code *re;
1733 : : static gsize initialised = 0;
1734 : : uint32_t pcre_compile_options;
1735 : : uint32_t pcre_match_options;
1736 : : uint32_t newline_options;
1737 : : uint32_t bsr_options;
1738 : :
1739 : 849 : g_return_val_if_fail (pattern != NULL, NULL);
1740 : 849 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1741 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1742 : 849 : g_return_val_if_fail ((compile_options & ~(G_REGEX_COMPILE_MASK |
1743 : : G_REGEX_JAVASCRIPT_COMPAT)) == 0, NULL);
1744 : : G_GNUC_END_IGNORE_DEPRECATIONS
1745 : 849 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
1746 : :
1747 : 849 : if (g_once_init_enter (&initialised))
1748 : : {
1749 : : int supports_utf8;
1750 : :
1751 : 5 : pcre2_config (PCRE2_CONFIG_UNICODE, &supports_utf8);
1752 : 5 : if (!supports_utf8)
1753 : 0 : g_critical (_("PCRE library is compiled without UTF8 support"));
1754 : :
1755 : 5 : g_once_init_leave (&initialised, supports_utf8 ? 1 : 2);
1756 : : }
1757 : :
1758 : 849 : if (G_UNLIKELY (initialised != 1))
1759 : : {
1760 : 0 : g_set_error_literal (error, G_REGEX_ERROR, G_REGEX_ERROR_COMPILE,
1761 : : _("PCRE library is compiled with incompatible options"));
1762 : 0 : return NULL;
1763 : : }
1764 : :
1765 : 849 : pcre_compile_options = get_pcre2_compile_options (compile_options);
1766 : 849 : pcre_match_options = get_pcre2_match_options (match_options, compile_options);
1767 : :
1768 : 849 : newline_options = get_pcre2_newline_match_options (match_options);
1769 : 849 : if (newline_options == 0)
1770 : 800 : newline_options = get_pcre2_newline_compile_options (compile_options);
1771 : :
1772 : 849 : if (newline_options == 0)
1773 : : {
1774 : 1 : g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS,
1775 : : "Invalid newline flags");
1776 : 1 : return NULL;
1777 : : }
1778 : :
1779 : 848 : bsr_options = get_pcre2_bsr_match_options (match_options);
1780 : 848 : if (!bsr_options)
1781 : 847 : bsr_options = get_pcre2_bsr_compile_options (compile_options);
1782 : :
1783 : 848 : re = regex_compile (pattern, pcre_compile_options,
1784 : : newline_options, bsr_options, error);
1785 : 848 : if (re == NULL)
1786 : 58 : return NULL;
1787 : :
1788 : 790 : pcre_compile_options |=
1789 : 790 : get_pcre2_inline_compile_options (re, pcre_compile_options);
1790 : :
1791 : 790 : regex = g_new0 (GRegex, 1);
1792 : 790 : regex->ref_count = 1;
1793 : 790 : regex->pattern = g_strdup (pattern);
1794 : 790 : regex->pcre_re = re;
1795 : 790 : regex->compile_opts = pcre_compile_options;
1796 : 790 : regex->orig_compile_opts = compile_options;
1797 : 790 : regex->match_opts = pcre_match_options;
1798 : 790 : regex->orig_match_opts = match_options;
1799 : :
1800 : 790 : return regex;
1801 : : }
1802 : :
1803 : : static pcre2_code *
1804 : 874 : regex_compile (const gchar *pattern,
1805 : : uint32_t compile_options,
1806 : : uint32_t newline_options,
1807 : : uint32_t bsr_options,
1808 : : GError **error)
1809 : : {
1810 : : pcre2_code *re;
1811 : : pcre2_compile_context *context;
1812 : : const gchar *errmsg;
1813 : : PCRE2_SIZE erroffset;
1814 : : gint errcode;
1815 : :
1816 : 874 : context = pcre2_compile_context_create (NULL);
1817 : :
1818 : : /* set newline options */
1819 : 874 : if (pcre2_set_newline (context, newline_options) != 0)
1820 : : {
1821 : 0 : g_set_error (error, G_REGEX_ERROR,
1822 : : G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS,
1823 : : "Invalid newline flags");
1824 : 0 : pcre2_compile_context_free (context);
1825 : 0 : return NULL;
1826 : : }
1827 : :
1828 : : /* set bsr options */
1829 : 874 : if (pcre2_set_bsr (context, bsr_options) != 0)
1830 : : {
1831 : 0 : g_set_error (error, G_REGEX_ERROR,
1832 : : G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS,
1833 : : "Invalid BSR flags");
1834 : 0 : pcre2_compile_context_free (context);
1835 : 0 : return NULL;
1836 : : }
1837 : :
1838 : : /* In case UTF-8 mode is used, also set PCRE2_NO_UTF_CHECK */
1839 : 874 : if (compile_options & PCRE2_UTF)
1840 : 863 : compile_options |= PCRE2_NO_UTF_CHECK;
1841 : :
1842 : 874 : compile_options |= PCRE2_UCP;
1843 : :
1844 : : /* compile the pattern */
1845 : 874 : re = pcre2_compile ((PCRE2_SPTR8) pattern,
1846 : : PCRE2_ZERO_TERMINATED,
1847 : : compile_options,
1848 : : &errcode,
1849 : : &erroffset,
1850 : : context);
1851 : 874 : pcre2_compile_context_free (context);
1852 : :
1853 : : /* if the compilation failed, set the error member and return
1854 : : * immediately */
1855 : 874 : if (re == NULL)
1856 : : {
1857 : : GError *tmp_error;
1858 : : gchar *offset_str;
1859 : 58 : gchar *pcre2_errmsg = NULL;
1860 : : int original_errcode;
1861 : :
1862 : : /* Translate the PCRE error code to GRegexError and use a translated
1863 : : * error message if possible */
1864 : 58 : original_errcode = errcode;
1865 : 58 : translate_compile_error (&errcode, &errmsg);
1866 : :
1867 : 58 : if (!errmsg)
1868 : : {
1869 : 2 : errmsg = _("unknown error");
1870 : 2 : pcre2_errmsg = get_pcre2_error_string (original_errcode);
1871 : : }
1872 : :
1873 : : /* PCRE uses byte offsets but we want to show character offsets */
1874 : 58 : erroffset = g_utf8_pointer_to_offset (pattern, &pattern[erroffset]);
1875 : :
1876 : 58 : offset_str = g_strdup_printf ("%" G_GSIZE_FORMAT, erroffset);
1877 : 58 : tmp_error = g_error_new (G_REGEX_ERROR, errcode,
1878 : : _("Error while compiling regular expression ‘%s’ "
1879 : : "at char %s: %s"),
1880 : : pattern, offset_str,
1881 : 58 : pcre2_errmsg ? pcre2_errmsg : errmsg);
1882 : 58 : g_propagate_error (error, tmp_error);
1883 : 58 : g_free (offset_str);
1884 : 58 : g_clear_pointer (&pcre2_errmsg, g_free);
1885 : :
1886 : 58 : return NULL;
1887 : : }
1888 : :
1889 : 816 : return re;
1890 : : }
1891 : :
1892 : : static uint32_t
1893 : 790 : get_pcre2_inline_compile_options (pcre2_code *re,
1894 : : uint32_t compile_options)
1895 : : {
1896 : : uint32_t pcre_compile_options;
1897 : : uint32_t nonpcre_compile_options;
1898 : :
1899 : : /* For options set at the beginning of the pattern, pcre puts them into
1900 : : * compile options, e.g. "(?i)foo" will make the pcre structure store
1901 : : * PCRE2_CASELESS even though it wasn't explicitly given for compilation. */
1902 : 790 : nonpcre_compile_options = compile_options & G_REGEX_COMPILE_NONPCRE_MASK;
1903 : 790 : pcre2_pattern_info (re, PCRE2_INFO_ALLOPTIONS, &pcre_compile_options);
1904 : 790 : compile_options = pcre_compile_options & G_REGEX_PCRE2_COMPILE_MASK;
1905 : 790 : compile_options |= nonpcre_compile_options;
1906 : :
1907 : 790 : if (!(compile_options & PCRE2_DUPNAMES))
1908 : : {
1909 : 780 : uint32_t jchanged = 0;
1910 : 780 : pcre2_pattern_info (re, PCRE2_INFO_JCHANGED, &jchanged);
1911 : 780 : if (jchanged)
1912 : 7 : compile_options |= PCRE2_DUPNAMES;
1913 : : }
1914 : :
1915 : 790 : return compile_options;
1916 : : }
1917 : :
1918 : : /**
1919 : : * g_regex_get_pattern:
1920 : : * @regex: a #GRegex structure
1921 : : *
1922 : : * Gets the pattern string associated with @regex, i.e. a copy of
1923 : : * the string passed to g_regex_new().
1924 : : *
1925 : : * Returns: the pattern of @regex
1926 : : *
1927 : : * Since: 2.14
1928 : : */
1929 : : const gchar *
1930 : 39 : g_regex_get_pattern (const GRegex *regex)
1931 : : {
1932 : 39 : g_return_val_if_fail (regex != NULL, NULL);
1933 : :
1934 : 39 : return regex->pattern;
1935 : : }
1936 : :
1937 : : /**
1938 : : * g_regex_get_max_backref:
1939 : : * @regex: a #GRegex
1940 : : *
1941 : : * Returns the number of the highest back reference
1942 : : * in the pattern, or 0 if the pattern does not contain
1943 : : * back references.
1944 : : *
1945 : : * Returns: the number of the highest back reference
1946 : : *
1947 : : * Since: 2.14
1948 : : */
1949 : : gint
1950 : 4 : g_regex_get_max_backref (const GRegex *regex)
1951 : : {
1952 : : uint32_t value;
1953 : :
1954 : 4 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_BACKREFMAX, &value);
1955 : :
1956 : 4 : return value;
1957 : : }
1958 : :
1959 : : /**
1960 : : * g_regex_get_capture_count:
1961 : : * @regex: a #GRegex
1962 : : *
1963 : : * Returns the number of capturing subpatterns in the pattern.
1964 : : *
1965 : : * Returns: the number of capturing subpatterns
1966 : : *
1967 : : * Since: 2.14
1968 : : */
1969 : : gint
1970 : 3 : g_regex_get_capture_count (const GRegex *regex)
1971 : : {
1972 : : uint32_t value;
1973 : :
1974 : 3 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_CAPTURECOUNT, &value);
1975 : :
1976 : 3 : return value;
1977 : : }
1978 : :
1979 : : /**
1980 : : * g_regex_get_has_cr_or_lf:
1981 : : * @regex: a #GRegex structure
1982 : : *
1983 : : * Checks whether the pattern contains explicit CR or LF references.
1984 : : *
1985 : : * Returns: %TRUE if the pattern contains explicit CR or LF references
1986 : : *
1987 : : * Since: 2.34
1988 : : */
1989 : : gboolean
1990 : 1 : g_regex_get_has_cr_or_lf (const GRegex *regex)
1991 : : {
1992 : : uint32_t value;
1993 : :
1994 : 1 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_HASCRORLF, &value);
1995 : :
1996 : 1 : return !!value;
1997 : : }
1998 : :
1999 : : /**
2000 : : * g_regex_get_max_lookbehind:
2001 : : * @regex: a #GRegex structure
2002 : : *
2003 : : * Gets the number of characters in the longest lookbehind assertion in the
2004 : : * pattern. This information is useful when doing multi-segment matching using
2005 : : * the partial matching facilities.
2006 : : *
2007 : : * Returns: the number of characters in the longest lookbehind assertion.
2008 : : *
2009 : : * Since: 2.38
2010 : : */
2011 : : gint
2012 : 3 : g_regex_get_max_lookbehind (const GRegex *regex)
2013 : : {
2014 : : uint32_t max_lookbehind;
2015 : :
2016 : 3 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_MAXLOOKBEHIND,
2017 : : &max_lookbehind);
2018 : :
2019 : 3 : return max_lookbehind;
2020 : : }
2021 : :
2022 : : /**
2023 : : * g_regex_get_compile_flags:
2024 : : * @regex: a #GRegex
2025 : : *
2026 : : * Returns the compile options that @regex was created with.
2027 : : *
2028 : : * Depending on the version of PCRE that is used, this may or may not
2029 : : * include flags set by option expressions such as `(?i)` found at the
2030 : : * top-level within the compiled pattern.
2031 : : *
2032 : : * Returns: flags from #GRegexCompileFlags
2033 : : *
2034 : : * Since: 2.26
2035 : : */
2036 : : GRegexCompileFlags
2037 : 17 : g_regex_get_compile_flags (const GRegex *regex)
2038 : : {
2039 : : GRegexCompileFlags extra_flags;
2040 : : uint32_t info_value;
2041 : :
2042 : 17 : g_return_val_if_fail (regex != NULL, 0);
2043 : :
2044 : : /* Preserve original G_REGEX_OPTIMIZE */
2045 : 17 : extra_flags = (regex->orig_compile_opts & G_REGEX_OPTIMIZE);
2046 : :
2047 : : /* Also include the newline options */
2048 : 17 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_NEWLINE, &info_value);
2049 : 17 : switch (info_value)
2050 : : {
2051 : 2 : case PCRE2_NEWLINE_ANYCRLF:
2052 : 2 : extra_flags |= G_REGEX_NEWLINE_ANYCRLF;
2053 : 2 : break;
2054 : 1 : case PCRE2_NEWLINE_CRLF:
2055 : 1 : extra_flags |= G_REGEX_NEWLINE_CRLF;
2056 : 1 : break;
2057 : 1 : case PCRE2_NEWLINE_LF:
2058 : 1 : extra_flags |= G_REGEX_NEWLINE_LF;
2059 : 1 : break;
2060 : 1 : case PCRE2_NEWLINE_CR:
2061 : 1 : extra_flags |= G_REGEX_NEWLINE_CR;
2062 : 1 : break;
2063 : 12 : default:
2064 : 12 : break;
2065 : : }
2066 : :
2067 : : /* Also include the bsr options */
2068 : 17 : pcre2_pattern_info (regex->pcre_re, PCRE2_INFO_BSR, &info_value);
2069 : 17 : switch (info_value)
2070 : : {
2071 : 2 : case PCRE2_BSR_ANYCRLF:
2072 : 2 : extra_flags |= G_REGEX_BSR_ANYCRLF;
2073 : 2 : break;
2074 : 15 : default:
2075 : 15 : break;
2076 : : }
2077 : :
2078 : 17 : return g_regex_compile_flags_from_pcre2 (regex->compile_opts) | extra_flags;
2079 : : }
2080 : :
2081 : : /**
2082 : : * g_regex_get_match_flags:
2083 : : * @regex: a #GRegex
2084 : : *
2085 : : * Returns the match options that @regex was created with.
2086 : : *
2087 : : * Returns: flags from #GRegexMatchFlags
2088 : : *
2089 : : * Since: 2.26
2090 : : */
2091 : : GRegexMatchFlags
2092 : 17 : g_regex_get_match_flags (const GRegex *regex)
2093 : : {
2094 : : uint32_t flags;
2095 : :
2096 : 17 : g_return_val_if_fail (regex != NULL, 0);
2097 : :
2098 : 17 : flags = g_regex_match_flags_from_pcre2 (regex->match_opts);
2099 : 17 : flags |= (regex->orig_match_opts & G_REGEX_MATCH_NEWLINE_MASK);
2100 : 17 : flags |= (regex->orig_match_opts & (G_REGEX_MATCH_BSR_ANY | G_REGEX_MATCH_BSR_ANYCRLF));
2101 : :
2102 : 17 : return flags;
2103 : : }
2104 : :
2105 : : /**
2106 : : * g_regex_match_simple:
2107 : : * @pattern: the regular expression
2108 : : * @string: the string to scan for matches
2109 : : * @compile_options: compile options for the regular expression, or 0
2110 : : * @match_options: match options, or 0
2111 : : *
2112 : : * Scans for a match in @string for @pattern.
2113 : : *
2114 : : * This function is equivalent to g_regex_match() but it does not
2115 : : * require to compile the pattern with g_regex_new(), avoiding some
2116 : : * lines of code when you need just to do a match without extracting
2117 : : * substrings, capture counts, and so on.
2118 : : *
2119 : : * If this function is to be called on the same @pattern more than
2120 : : * once, it's more efficient to compile the pattern once with
2121 : : * g_regex_new() and then use g_regex_match().
2122 : : *
2123 : : * Returns: %TRUE if the string matched, %FALSE otherwise
2124 : : *
2125 : : * Since: 2.14
2126 : : */
2127 : : gboolean
2128 : 160 : g_regex_match_simple (const gchar *pattern,
2129 : : const gchar *string,
2130 : : GRegexCompileFlags compile_options,
2131 : : GRegexMatchFlags match_options)
2132 : : {
2133 : : GRegex *regex;
2134 : : gboolean result;
2135 : :
2136 : 160 : regex = g_regex_new (pattern, compile_options, G_REGEX_MATCH_DEFAULT, NULL);
2137 : 160 : if (!regex)
2138 : 4 : return FALSE;
2139 : 156 : result = g_regex_match_full (regex, string, -1, 0, match_options, NULL, NULL);
2140 : 156 : g_regex_unref (regex);
2141 : 156 : return result;
2142 : : }
2143 : :
2144 : : /**
2145 : : * g_regex_match:
2146 : : * @regex: a #GRegex structure from g_regex_new()
2147 : : * @string: the string to scan for matches
2148 : : * @match_options: match options
2149 : : * @match_info: (out) (optional): pointer to location where to store
2150 : : * the #GMatchInfo, or %NULL if you do not need it
2151 : : *
2152 : : * Scans for a match in @string for the pattern in @regex.
2153 : : * The @match_options are combined with the match options specified
2154 : : * when the @regex structure was created, letting you have more
2155 : : * flexibility in reusing #GRegex structures.
2156 : : *
2157 : : * Unless %G_REGEX_RAW is specified in the options, @string must be valid UTF-8.
2158 : : *
2159 : : * A #GMatchInfo structure, used to get information on the match,
2160 : : * is stored in @match_info if not %NULL. Note that if @match_info
2161 : : * is not %NULL then it is created even if the function returns %FALSE,
2162 : : * i.e. you must free it regardless if regular expression actually matched.
2163 : : *
2164 : : * To retrieve all the non-overlapping matches of the pattern in
2165 : : * string you can use g_match_info_next().
2166 : : *
2167 : : * |[<!-- language="C" -->
2168 : : * static void
2169 : : * print_uppercase_words (const gchar *string)
2170 : : * {
2171 : : * // Print all uppercase-only words.
2172 : : * GRegex *regex;
2173 : : * GMatchInfo *match_info;
2174 : : *
2175 : : * regex = g_regex_new ("[A-Z]+", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
2176 : : * g_regex_match (regex, string, 0, &match_info);
2177 : : * while (g_match_info_matches (match_info))
2178 : : * {
2179 : : * gchar *word = g_match_info_fetch (match_info, 0);
2180 : : * g_print ("Found: %s\n", word);
2181 : : * g_free (word);
2182 : : * g_match_info_next (match_info, NULL);
2183 : : * }
2184 : : * g_match_info_free (match_info);
2185 : : * g_regex_unref (regex);
2186 : : * }
2187 : : * ]|
2188 : : *
2189 : : * @string is not copied and is used in #GMatchInfo internally. If
2190 : : * you use any #GMatchInfo method (except g_match_info_free()) after
2191 : : * freeing or modifying @string then the behaviour is undefined.
2192 : : *
2193 : : * Returns: %TRUE is the string matched, %FALSE otherwise
2194 : : *
2195 : : * Since: 2.14
2196 : : */
2197 : : gboolean
2198 : 329 : g_regex_match (const GRegex *regex,
2199 : : const gchar *string,
2200 : : GRegexMatchFlags match_options,
2201 : : GMatchInfo **match_info)
2202 : : {
2203 : 329 : return g_regex_match_full (regex, string, -1, 0, match_options,
2204 : : match_info, NULL);
2205 : : }
2206 : :
2207 : : /**
2208 : : * g_regex_match_full:
2209 : : * @regex: a #GRegex structure from g_regex_new()
2210 : : * @string: (array length=string_len): the string to scan for matches
2211 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
2212 : : * @start_position: starting index of the string to match, in bytes
2213 : : * @match_options: match options
2214 : : * @match_info: (out) (optional): pointer to location where to store
2215 : : * the #GMatchInfo, or %NULL if you do not need it
2216 : : * @error: location to store the error occurring, or %NULL to ignore errors
2217 : : *
2218 : : * Scans for a match in @string for the pattern in @regex.
2219 : : * The @match_options are combined with the match options specified
2220 : : * when the @regex structure was created, letting you have more
2221 : : * flexibility in reusing #GRegex structures.
2222 : : *
2223 : : * Setting @start_position differs from just passing over a shortened
2224 : : * string and setting %G_REGEX_MATCH_NOTBOL in the case of a pattern
2225 : : * that begins with any kind of lookbehind assertion, such as "\b".
2226 : : *
2227 : : * Unless %G_REGEX_RAW is specified in the options, @string must be valid UTF-8.
2228 : : *
2229 : : * A #GMatchInfo structure, used to get information on the match, is
2230 : : * stored in @match_info if not %NULL. Note that if @match_info is
2231 : : * not %NULL then it is created even if the function returns %FALSE,
2232 : : * i.e. you must free it regardless if regular expression actually
2233 : : * matched.
2234 : : *
2235 : : * @string is not copied and is used in #GMatchInfo internally. If
2236 : : * you use any #GMatchInfo method (except g_match_info_free()) after
2237 : : * freeing or modifying @string then the behaviour is undefined.
2238 : : *
2239 : : * To retrieve all the non-overlapping matches of the pattern in
2240 : : * string you can use g_match_info_next().
2241 : : *
2242 : : * |[<!-- language="C" -->
2243 : : * static void
2244 : : * print_uppercase_words (const gchar *string)
2245 : : * {
2246 : : * // Print all uppercase-only words.
2247 : : * GRegex *regex;
2248 : : * GMatchInfo *match_info;
2249 : : * GError *error = NULL;
2250 : : *
2251 : : * regex = g_regex_new ("[A-Z]+", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
2252 : : * g_regex_match_full (regex, string, -1, 0, 0, &match_info, &error);
2253 : : * while (g_match_info_matches (match_info))
2254 : : * {
2255 : : * gchar *word = g_match_info_fetch (match_info, 0);
2256 : : * g_print ("Found: %s\n", word);
2257 : : * g_free (word);
2258 : : * g_match_info_next (match_info, &error);
2259 : : * }
2260 : : * g_match_info_free (match_info);
2261 : : * g_regex_unref (regex);
2262 : : * if (error != NULL)
2263 : : * {
2264 : : * g_printerr ("Error while matching: %s\n", error->message);
2265 : : * g_error_free (error);
2266 : : * }
2267 : : * }
2268 : : * ]|
2269 : : *
2270 : : * Returns: %TRUE is the string matched, %FALSE otherwise
2271 : : *
2272 : : * Since: 2.14
2273 : : */
2274 : : gboolean
2275 : 878 : g_regex_match_full (const GRegex *regex,
2276 : : const gchar *string,
2277 : : gssize string_len,
2278 : : gint start_position,
2279 : : GRegexMatchFlags match_options,
2280 : : GMatchInfo **match_info,
2281 : : GError **error)
2282 : : {
2283 : : GMatchInfo *info;
2284 : : gboolean match_ok;
2285 : :
2286 : 878 : g_return_val_if_fail (regex != NULL, FALSE);
2287 : 878 : g_return_val_if_fail (string != NULL, FALSE);
2288 : 878 : g_return_val_if_fail (start_position >= 0, FALSE);
2289 : 878 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2290 : 878 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, FALSE);
2291 : :
2292 : 878 : info = match_info_new (regex, string, string_len, start_position,
2293 : : match_options, FALSE);
2294 : 878 : match_ok = g_match_info_next (info, error);
2295 : 878 : if (match_info != NULL)
2296 : 404 : *match_info = info;
2297 : : else
2298 : 474 : g_match_info_free (info);
2299 : :
2300 : 878 : return match_ok;
2301 : : }
2302 : :
2303 : : /**
2304 : : * g_regex_match_all:
2305 : : * @regex: a #GRegex structure from g_regex_new()
2306 : : * @string: the string to scan for matches
2307 : : * @match_options: match options
2308 : : * @match_info: (out) (optional): pointer to location where to store
2309 : : * the #GMatchInfo, or %NULL if you do not need it
2310 : : *
2311 : : * Using the standard algorithm for regular expression matching only
2312 : : * the longest match in the string is retrieved. This function uses
2313 : : * a different algorithm so it can retrieve all the possible matches.
2314 : : * For more documentation see g_regex_match_all_full().
2315 : : *
2316 : : * A #GMatchInfo structure, used to get information on the match, is
2317 : : * stored in @match_info if not %NULL. Note that if @match_info is
2318 : : * not %NULL then it is created even if the function returns %FALSE,
2319 : : * i.e. you must free it regardless if regular expression actually
2320 : : * matched.
2321 : : *
2322 : : * @string is not copied and is used in #GMatchInfo internally. If
2323 : : * you use any #GMatchInfo method (except g_match_info_free()) after
2324 : : * freeing or modifying @string then the behaviour is undefined.
2325 : : *
2326 : : * Returns: %TRUE is the string matched, %FALSE otherwise
2327 : : *
2328 : : * Since: 2.14
2329 : : */
2330 : : gboolean
2331 : 11 : g_regex_match_all (const GRegex *regex,
2332 : : const gchar *string,
2333 : : GRegexMatchFlags match_options,
2334 : : GMatchInfo **match_info)
2335 : : {
2336 : 11 : return g_regex_match_all_full (regex, string, -1, 0, match_options,
2337 : : match_info, NULL);
2338 : : }
2339 : :
2340 : : /**
2341 : : * g_regex_match_all_full:
2342 : : * @regex: a #GRegex structure from g_regex_new()
2343 : : * @string: (array length=string_len): the string to scan for matches
2344 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
2345 : : * @start_position: starting index of the string to match, in bytes
2346 : : * @match_options: match options
2347 : : * @match_info: (out) (optional): pointer to location where to store
2348 : : * the #GMatchInfo, or %NULL if you do not need it
2349 : : * @error: location to store the error occurring, or %NULL to ignore errors
2350 : : *
2351 : : * Using the standard algorithm for regular expression matching only
2352 : : * the longest match in the @string is retrieved, it is not possible
2353 : : * to obtain all the available matches. For instance matching
2354 : : * `"<a> <b> <c>"` against the pattern `"<.*>"`
2355 : : * you get `"<a> <b> <c>"`.
2356 : : *
2357 : : * This function uses a different algorithm (called DFA, i.e. deterministic
2358 : : * finite automaton), so it can retrieve all the possible matches, all
2359 : : * starting at the same point in the string. For instance matching
2360 : : * `"<a> <b> <c>"` against the pattern `"<.*>"`
2361 : : * you would obtain three matches: `"<a> <b> <c>"`,
2362 : : * `"<a> <b>"` and `"<a>"`.
2363 : : *
2364 : : * The number of matched strings is retrieved using
2365 : : * g_match_info_get_match_count(). To obtain the matched strings and
2366 : : * their position you can use, respectively, g_match_info_fetch() and
2367 : : * g_match_info_fetch_pos(). Note that the strings are returned in
2368 : : * reverse order of length; that is, the longest matching string is
2369 : : * given first.
2370 : : *
2371 : : * Note that the DFA algorithm is slower than the standard one and it
2372 : : * is not able to capture substrings, so backreferences do not work.
2373 : : *
2374 : : * Setting @start_position differs from just passing over a shortened
2375 : : * string and setting %G_REGEX_MATCH_NOTBOL in the case of a pattern
2376 : : * that begins with any kind of lookbehind assertion, such as "\b".
2377 : : *
2378 : : * Unless %G_REGEX_RAW is specified in the options, @string must be valid UTF-8.
2379 : : *
2380 : : * A #GMatchInfo structure, used to get information on the match, is
2381 : : * stored in @match_info if not %NULL. Note that if @match_info is
2382 : : * not %NULL then it is created even if the function returns %FALSE,
2383 : : * i.e. you must free it regardless if regular expression actually
2384 : : * matched.
2385 : : *
2386 : : * @string is not copied and is used in #GMatchInfo internally. If
2387 : : * you use any #GMatchInfo method (except g_match_info_free()) after
2388 : : * freeing or modifying @string then the behaviour is undefined.
2389 : : *
2390 : : * Returns: %TRUE is the string matched, %FALSE otherwise
2391 : : *
2392 : : * Since: 2.14
2393 : : */
2394 : : gboolean
2395 : 26 : g_regex_match_all_full (const GRegex *regex,
2396 : : const gchar *string,
2397 : : gssize string_len,
2398 : : gint start_position,
2399 : : GRegexMatchFlags match_options,
2400 : : GMatchInfo **match_info,
2401 : : GError **error)
2402 : : {
2403 : : GMatchInfo *info;
2404 : : gboolean done;
2405 : : pcre2_code *pcre_re;
2406 : : gboolean retval;
2407 : : uint32_t newline_options;
2408 : : uint32_t bsr_options;
2409 : :
2410 : 26 : g_return_val_if_fail (regex != NULL, FALSE);
2411 : 26 : g_return_val_if_fail (string != NULL, FALSE);
2412 : 26 : g_return_val_if_fail (start_position >= 0, FALSE);
2413 : 26 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2414 : 26 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, FALSE);
2415 : :
2416 : 26 : newline_options = get_pcre2_newline_match_options (match_options);
2417 : 26 : if (!newline_options)
2418 : 26 : newline_options = get_pcre2_newline_compile_options (regex->orig_compile_opts);
2419 : :
2420 : 26 : bsr_options = get_pcre2_bsr_match_options (match_options);
2421 : 26 : if (!bsr_options)
2422 : 26 : bsr_options = get_pcre2_bsr_compile_options (regex->orig_compile_opts);
2423 : :
2424 : : /* For PCRE2 we need to turn off PCRE2_NO_AUTO_POSSESS, which is an
2425 : : * optimization for normal regex matching, but results in omitting some
2426 : : * shorter matches here, and an observable behaviour change.
2427 : : *
2428 : : * DFA matching is rather niche, and very rarely used according to
2429 : : * codesearch.debian.net, so don't bother caching the recompiled RE. */
2430 : 26 : pcre_re = regex_compile (regex->pattern,
2431 : 26 : regex->compile_opts | PCRE2_NO_AUTO_POSSESS,
2432 : : newline_options, bsr_options, error);
2433 : 26 : if (pcre_re == NULL)
2434 : 0 : return FALSE;
2435 : :
2436 : 26 : info = match_info_new (regex, string, string_len, start_position,
2437 : : match_options, TRUE);
2438 : :
2439 : 26 : done = FALSE;
2440 : 62 : while (!done)
2441 : : {
2442 : 36 : done = TRUE;
2443 : 72 : info->matches = pcre2_dfa_match (pcre_re,
2444 : 36 : (PCRE2_SPTR8) info->string, info->string_len,
2445 : 36 : info->pos,
2446 : 36 : (regex->match_opts | info->match_opts),
2447 : : info->match_data,
2448 : : info->match_context,
2449 : 36 : info->workspace, info->n_workspace);
2450 : 36 : if (info->matches == PCRE2_ERROR_DFA_WSSIZE)
2451 : : {
2452 : : /* info->workspace is too small. */
2453 : 0 : info->n_workspace *= 2;
2454 : 0 : info->workspace = g_realloc_n (info->workspace,
2455 : : info->n_workspace,
2456 : : sizeof (gint));
2457 : 0 : done = FALSE;
2458 : : }
2459 : 36 : else if (info->matches == 0)
2460 : : {
2461 : : /* info->offsets is too small. */
2462 : 10 : info->n_offsets *= 2;
2463 : 20 : info->offsets = g_realloc_n (info->offsets,
2464 : 10 : info->n_offsets,
2465 : : sizeof (gint));
2466 : 10 : pcre2_match_data_free (info->match_data);
2467 : 10 : info->match_data = pcre2_match_data_create (info->n_offsets, NULL);
2468 : 10 : done = FALSE;
2469 : : }
2470 : 26 : else if (IS_PCRE2_ERROR (info->matches))
2471 : 0 : {
2472 : 0 : gchar *error_msg = get_match_error_message (info->matches);
2473 : :
2474 : 0 : g_set_error (error, G_REGEX_ERROR, G_REGEX_ERROR_MATCH,
2475 : : _("Error while matching regular expression %s: %s"),
2476 : 0 : regex->pattern, error_msg);
2477 : 0 : g_clear_pointer (&error_msg, g_free);
2478 : : }
2479 : 26 : else if (info->matches != PCRE2_ERROR_NOMATCH)
2480 : : {
2481 : 20 : if (!recalc_match_offsets (info, error))
2482 : 0 : info->matches = PCRE2_ERROR_NOMATCH;
2483 : : }
2484 : : }
2485 : :
2486 : 26 : pcre2_code_free (pcre_re);
2487 : :
2488 : : /* don’t assert that (info->matches <= info->n_subpatterns + 1) as that only
2489 : : * holds true for a single match, rather than matching all */
2490 : :
2491 : : /* set info->pos to -1 so that a call to g_match_info_next() fails. */
2492 : 26 : info->pos = -1;
2493 : 26 : retval = info->matches >= 0;
2494 : :
2495 : 26 : if (match_info != NULL)
2496 : 26 : *match_info = info;
2497 : : else
2498 : 0 : g_match_info_free (info);
2499 : :
2500 : 26 : return retval;
2501 : : }
2502 : :
2503 : : /**
2504 : : * g_regex_get_string_number:
2505 : : * @regex: #GRegex structure
2506 : : * @name: name of the subexpression
2507 : : *
2508 : : * Retrieves the number of the subexpression named @name.
2509 : : *
2510 : : * Returns: The number of the subexpression or -1 if @name
2511 : : * does not exists
2512 : : *
2513 : : * Since: 2.14
2514 : : */
2515 : : gint
2516 : 15 : g_regex_get_string_number (const GRegex *regex,
2517 : : const gchar *name)
2518 : : {
2519 : : gint num;
2520 : :
2521 : 15 : g_return_val_if_fail (regex != NULL, -1);
2522 : 15 : g_return_val_if_fail (name != NULL, -1);
2523 : :
2524 : 15 : num = pcre2_substring_number_from_name (regex->pcre_re, (PCRE2_SPTR8) name);
2525 : 15 : if (num == PCRE2_ERROR_NOSUBSTRING)
2526 : 6 : num = -1;
2527 : :
2528 : 15 : return num;
2529 : : }
2530 : :
2531 : : /**
2532 : : * g_regex_split_simple:
2533 : : * @pattern: the regular expression
2534 : : * @string: the string to scan for matches
2535 : : * @compile_options: compile options for the regular expression, or 0
2536 : : * @match_options: match options, or 0
2537 : : *
2538 : : * Breaks the string on the pattern, and returns an array of
2539 : : * the tokens. If the pattern contains capturing parentheses,
2540 : : * then the text for each of the substrings will also be returned.
2541 : : * If the pattern does not match anywhere in the string, then the
2542 : : * whole string is returned as the first token.
2543 : : *
2544 : : * This function is equivalent to g_regex_split() but it does
2545 : : * not require to compile the pattern with g_regex_new(), avoiding
2546 : : * some lines of code when you need just to do a split without
2547 : : * extracting substrings, capture counts, and so on.
2548 : : *
2549 : : * If this function is to be called on the same @pattern more than
2550 : : * once, it's more efficient to compile the pattern once with
2551 : : * g_regex_new() and then use g_regex_split().
2552 : : *
2553 : : * As a special case, the result of splitting the empty string ""
2554 : : * is an empty vector, not a vector containing a single string.
2555 : : * The reason for this special case is that being able to represent
2556 : : * an empty vector is typically more useful than consistent handling
2557 : : * of empty elements. If you do need to represent empty elements,
2558 : : * you'll need to check for the empty string before calling this
2559 : : * function.
2560 : : *
2561 : : * A pattern that can match empty strings splits @string into
2562 : : * separate characters wherever it matches the empty string between
2563 : : * characters. For example splitting "ab c" using as a separator
2564 : : * "\s*", you will get "a", "b" and "c".
2565 : : *
2566 : : * Returns: (transfer full): a %NULL-terminated array of strings. Free
2567 : : * it using g_strfreev()
2568 : : *
2569 : : * Since: 2.14
2570 : : **/
2571 : : gchar **
2572 : 18 : g_regex_split_simple (const gchar *pattern,
2573 : : const gchar *string,
2574 : : GRegexCompileFlags compile_options,
2575 : : GRegexMatchFlags match_options)
2576 : : {
2577 : : GRegex *regex;
2578 : : gchar **result;
2579 : :
2580 : 18 : regex = g_regex_new (pattern, compile_options, 0, NULL);
2581 : 18 : if (!regex)
2582 : 2 : return NULL;
2583 : :
2584 : 16 : result = g_regex_split_full (regex, string, -1, 0, match_options, 0, NULL);
2585 : 16 : g_regex_unref (regex);
2586 : 16 : return result;
2587 : : }
2588 : :
2589 : : /**
2590 : : * g_regex_split:
2591 : : * @regex: a #GRegex structure
2592 : : * @string: the string to split with the pattern
2593 : : * @match_options: match time option flags
2594 : : *
2595 : : * Breaks the string on the pattern, and returns an array of the tokens.
2596 : : * If the pattern contains capturing parentheses, then the text for each
2597 : : * of the substrings will also be returned. If the pattern does not match
2598 : : * anywhere in the string, then the whole string is returned as the first
2599 : : * token.
2600 : : *
2601 : : * As a special case, the result of splitting the empty string "" is an
2602 : : * empty vector, not a vector containing a single string. The reason for
2603 : : * this special case is that being able to represent an empty vector is
2604 : : * typically more useful than consistent handling of empty elements. If
2605 : : * you do need to represent empty elements, you'll need to check for the
2606 : : * empty string before calling this function.
2607 : : *
2608 : : * A pattern that can match empty strings splits @string into separate
2609 : : * characters wherever it matches the empty string between characters.
2610 : : * For example splitting "ab c" using as a separator "\s*", you will get
2611 : : * "a", "b" and "c".
2612 : : *
2613 : : * Returns: (transfer full): a %NULL-terminated gchar ** array. Free
2614 : : * it using g_strfreev()
2615 : : *
2616 : : * Since: 2.14
2617 : : **/
2618 : : gchar **
2619 : 18 : g_regex_split (const GRegex *regex,
2620 : : const gchar *string,
2621 : : GRegexMatchFlags match_options)
2622 : : {
2623 : 18 : return g_regex_split_full (regex, string, -1, 0,
2624 : : match_options, 0, NULL);
2625 : : }
2626 : :
2627 : : /**
2628 : : * g_regex_split_full:
2629 : : * @regex: a #GRegex structure
2630 : : * @string: (array length=string_len): the string to split with the pattern
2631 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
2632 : : * @start_position: starting index of the string to match, in bytes
2633 : : * @match_options: match time option flags
2634 : : * @max_tokens: the maximum number of tokens to split @string into.
2635 : : * If this is less than 1, the string is split completely
2636 : : * @error: return location for a #GError
2637 : : *
2638 : : * Breaks the string on the pattern, and returns an array of the tokens.
2639 : : * If the pattern contains capturing parentheses, then the text for each
2640 : : * of the substrings will also be returned. If the pattern does not match
2641 : : * anywhere in the string, then the whole string is returned as the first
2642 : : * token.
2643 : : *
2644 : : * As a special case, the result of splitting the empty string "" is an
2645 : : * empty vector, not a vector containing a single string. The reason for
2646 : : * this special case is that being able to represent an empty vector is
2647 : : * typically more useful than consistent handling of empty elements. If
2648 : : * you do need to represent empty elements, you'll need to check for the
2649 : : * empty string before calling this function.
2650 : : *
2651 : : * A pattern that can match empty strings splits @string into separate
2652 : : * characters wherever it matches the empty string between characters.
2653 : : * For example splitting "ab c" using as a separator "\s*", you will get
2654 : : * "a", "b" and "c".
2655 : : *
2656 : : * Setting @start_position differs from just passing over a shortened
2657 : : * string and setting %G_REGEX_MATCH_NOTBOL in the case of a pattern
2658 : : * that begins with any kind of lookbehind assertion, such as "\b".
2659 : : *
2660 : : * Returns: (transfer full): a %NULL-terminated gchar ** array. Free
2661 : : * it using g_strfreev()
2662 : : *
2663 : : * Since: 2.14
2664 : : **/
2665 : : gchar **
2666 : 61 : g_regex_split_full (const GRegex *regex,
2667 : : const gchar *string,
2668 : : gssize string_len,
2669 : : gint start_position,
2670 : : GRegexMatchFlags match_options,
2671 : : gint max_tokens,
2672 : : GError **error)
2673 : : {
2674 : 61 : GError *tmp_error = NULL;
2675 : : GMatchInfo *match_info;
2676 : : GList *list, *last;
2677 : : gint i;
2678 : : gint token_count;
2679 : : gboolean match_ok;
2680 : : /* position of the last separator. */
2681 : : gint last_separator_end;
2682 : : /* was the last match 0 bytes long? */
2683 : : gboolean last_match_is_empty;
2684 : : /* the returned array of char **s */
2685 : : gchar **string_list;
2686 : :
2687 : 61 : g_return_val_if_fail (regex != NULL, NULL);
2688 : 61 : g_return_val_if_fail (string != NULL, NULL);
2689 : 61 : g_return_val_if_fail (start_position >= 0, NULL);
2690 : 61 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2691 : 61 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
2692 : :
2693 : 61 : if (max_tokens <= 0)
2694 : 53 : max_tokens = G_MAXINT;
2695 : :
2696 : 61 : if (string_len < 0)
2697 : 61 : string_len = strlen (string);
2698 : :
2699 : : /* zero-length string */
2700 : 61 : if (string_len - start_position == 0)
2701 : 9 : return g_new0 (gchar *, 1);
2702 : :
2703 : 52 : if (max_tokens == 1)
2704 : : {
2705 : 2 : string_list = g_new0 (gchar *, 2);
2706 : 4 : string_list[0] = g_strndup (&string[start_position],
2707 : 2 : string_len - start_position);
2708 : 2 : return string_list;
2709 : : }
2710 : :
2711 : 50 : list = NULL;
2712 : 50 : token_count = 0;
2713 : 50 : last_separator_end = start_position;
2714 : 50 : last_match_is_empty = FALSE;
2715 : :
2716 : 50 : match_ok = g_regex_match_full (regex, string, string_len, start_position,
2717 : : match_options, &match_info, &tmp_error);
2718 : :
2719 : 133 : while (tmp_error == NULL)
2720 : : {
2721 : 133 : if (match_ok)
2722 : : {
2723 : 87 : last_match_is_empty =
2724 : 87 : (match_info->offsets[0] == match_info->offsets[1]);
2725 : :
2726 : : /* we need to skip empty separators at the same position of the end
2727 : : * of another separator. e.g. the string is "a b" and the separator
2728 : : * is " *", so from 1 to 2 we have a match and at position 2 we have
2729 : : * an empty match. */
2730 : 87 : if (last_separator_end != match_info->offsets[1])
2731 : : {
2732 : : gchar *token;
2733 : : gint match_count;
2734 : :
2735 : 70 : token = g_strndup (string + last_separator_end,
2736 : 70 : match_info->offsets[0] - last_separator_end);
2737 : 70 : list = g_list_prepend (list, token);
2738 : 70 : token_count++;
2739 : :
2740 : : /* if there were substrings, these need to be added to
2741 : : * the list. */
2742 : 70 : match_count = g_match_info_get_match_count (match_info);
2743 : 70 : if (match_count > 1)
2744 : : {
2745 : 18 : for (i = 1; i < match_count; i++)
2746 : 9 : list = g_list_prepend (list, g_match_info_fetch (match_info, i));
2747 : : }
2748 : : }
2749 : : }
2750 : : else
2751 : : {
2752 : : /* if there was no match, copy to end of string. */
2753 : 46 : if (!last_match_is_empty)
2754 : : {
2755 : 38 : gchar *token = g_strndup (string + last_separator_end,
2756 : 38 : match_info->string_len - last_separator_end);
2757 : 38 : list = g_list_prepend (list, token);
2758 : : }
2759 : : /* no more tokens, end the loop. */
2760 : 46 : break;
2761 : : }
2762 : :
2763 : : /* -1 to leave room for the last part. */
2764 : 87 : if (token_count >= max_tokens - 1)
2765 : : {
2766 : : /* we have reached the maximum number of tokens, so we copy
2767 : : * the remaining part of the string. */
2768 : 4 : if (last_match_is_empty)
2769 : : {
2770 : : /* the last match was empty, so we have moved one char
2771 : : * after the real position to avoid empty matches at the
2772 : : * same position. */
2773 : 2 : match_info->pos = PREV_CHAR (regex, &string[match_info->pos]) - string;
2774 : : }
2775 : : /* the if is needed in the case we have terminated the available
2776 : : * tokens, but we are at the end of the string, so there are no
2777 : : * characters left to copy. */
2778 : 4 : if (string_len > match_info->pos)
2779 : : {
2780 : 3 : gchar *token = g_strndup (string + match_info->pos,
2781 : 3 : string_len - match_info->pos);
2782 : 3 : list = g_list_prepend (list, token);
2783 : : }
2784 : : /* end the loop. */
2785 : 4 : break;
2786 : : }
2787 : :
2788 : 83 : last_separator_end = match_info->pos;
2789 : 83 : if (last_match_is_empty)
2790 : : /* if the last match was empty, g_match_info_next() has moved
2791 : : * forward to avoid infinite loops, but we still need to copy that
2792 : : * character. */
2793 : 37 : last_separator_end = PREV_CHAR (regex, &string[last_separator_end]) - string;
2794 : :
2795 : 83 : match_ok = g_match_info_next (match_info, &tmp_error);
2796 : : }
2797 : 50 : g_match_info_free (match_info);
2798 : 50 : if (tmp_error != NULL)
2799 : : {
2800 : 0 : g_propagate_error (error, tmp_error);
2801 : 0 : g_list_free_full (list, g_free);
2802 : 0 : return NULL;
2803 : : }
2804 : :
2805 : 50 : string_list = g_new (gchar *, g_list_length (list) + 1);
2806 : 50 : i = 0;
2807 : 170 : for (last = g_list_last (list); last; last = g_list_previous (last))
2808 : 120 : string_list[i++] = last->data;
2809 : 50 : string_list[i] = NULL;
2810 : 50 : g_list_free (list);
2811 : :
2812 : 50 : return string_list;
2813 : : }
2814 : :
2815 : : enum
2816 : : {
2817 : : REPL_TYPE_STRING,
2818 : : REPL_TYPE_CHARACTER,
2819 : : REPL_TYPE_SYMBOLIC_REFERENCE,
2820 : : REPL_TYPE_NUMERIC_REFERENCE,
2821 : : REPL_TYPE_CHANGE_CASE
2822 : : };
2823 : :
2824 : : typedef enum
2825 : : {
2826 : : CHANGE_CASE_NONE = 1 << 0,
2827 : : CHANGE_CASE_UPPER = 1 << 1,
2828 : : CHANGE_CASE_LOWER = 1 << 2,
2829 : : CHANGE_CASE_UPPER_SINGLE = 1 << 3,
2830 : : CHANGE_CASE_LOWER_SINGLE = 1 << 4,
2831 : : CHANGE_CASE_SINGLE_MASK = CHANGE_CASE_UPPER_SINGLE | CHANGE_CASE_LOWER_SINGLE,
2832 : : CHANGE_CASE_LOWER_MASK = CHANGE_CASE_LOWER | CHANGE_CASE_LOWER_SINGLE,
2833 : : CHANGE_CASE_UPPER_MASK = CHANGE_CASE_UPPER | CHANGE_CASE_UPPER_SINGLE
2834 : : } ChangeCase;
2835 : :
2836 : : struct _InterpolationData
2837 : : {
2838 : : gchar *text;
2839 : : gint type;
2840 : : gint num;
2841 : : gchar c;
2842 : : ChangeCase change_case;
2843 : : };
2844 : :
2845 : : static void
2846 : 225 : free_interpolation_data (InterpolationData *data)
2847 : : {
2848 : 225 : g_free (data->text);
2849 : 225 : g_free (data);
2850 : 225 : }
2851 : :
2852 : : static const gchar *
2853 : 138 : expand_escape (const gchar *replacement,
2854 : : const gchar *p,
2855 : : InterpolationData *data,
2856 : : GError **error)
2857 : : {
2858 : : const gchar *q, *r;
2859 : : gint x, d, h, i;
2860 : : const gchar *error_detail;
2861 : 138 : gint base = 0;
2862 : 138 : GError *tmp_error = NULL;
2863 : :
2864 : 138 : p++;
2865 : 138 : switch (*p)
2866 : : {
2867 : 2 : case 't':
2868 : 2 : p++;
2869 : 2 : data->c = '\t';
2870 : 2 : data->type = REPL_TYPE_CHARACTER;
2871 : 2 : break;
2872 : 6 : case 'n':
2873 : 6 : p++;
2874 : 6 : data->c = '\n';
2875 : 6 : data->type = REPL_TYPE_CHARACTER;
2876 : 6 : break;
2877 : 2 : case 'v':
2878 : 2 : p++;
2879 : 2 : data->c = '\v';
2880 : 2 : data->type = REPL_TYPE_CHARACTER;
2881 : 2 : break;
2882 : 2 : case 'r':
2883 : 2 : p++;
2884 : 2 : data->c = '\r';
2885 : 2 : data->type = REPL_TYPE_CHARACTER;
2886 : 2 : break;
2887 : 2 : case 'f':
2888 : 2 : p++;
2889 : 2 : data->c = '\f';
2890 : 2 : data->type = REPL_TYPE_CHARACTER;
2891 : 2 : break;
2892 : 2 : case 'a':
2893 : 2 : p++;
2894 : 2 : data->c = '\a';
2895 : 2 : data->type = REPL_TYPE_CHARACTER;
2896 : 2 : break;
2897 : 3 : case 'b':
2898 : 3 : p++;
2899 : 3 : data->c = '\b';
2900 : 3 : data->type = REPL_TYPE_CHARACTER;
2901 : 3 : break;
2902 : 3 : case '\\':
2903 : 3 : p++;
2904 : 3 : data->c = '\\';
2905 : 3 : data->type = REPL_TYPE_CHARACTER;
2906 : 3 : break;
2907 : 11 : case 'x':
2908 : 11 : p++;
2909 : 11 : x = 0;
2910 : 11 : if (*p == '{')
2911 : : {
2912 : 7 : p++;
2913 : : do
2914 : : {
2915 : 20 : h = g_ascii_xdigit_value (*p);
2916 : 20 : if (h < 0)
2917 : : {
2918 : 1 : error_detail = _("hexadecimal digit or “}” expected");
2919 : 1 : goto error;
2920 : : }
2921 : 19 : x = x * 16 + h;
2922 : 19 : p++;
2923 : : }
2924 : 19 : while (*p != '}');
2925 : 6 : p++;
2926 : : }
2927 : : else
2928 : : {
2929 : 11 : for (i = 0; i < 2; i++)
2930 : : {
2931 : 8 : h = g_ascii_xdigit_value (*p);
2932 : 8 : if (h < 0)
2933 : : {
2934 : 1 : error_detail = _("hexadecimal digit expected");
2935 : 1 : goto error;
2936 : : }
2937 : 7 : x = x * 16 + h;
2938 : 7 : p++;
2939 : : }
2940 : : }
2941 : 9 : data->type = REPL_TYPE_STRING;
2942 : 9 : data->text = g_new0 (gchar, 8);
2943 : 9 : g_unichar_to_utf8 (x, data->text);
2944 : 9 : break;
2945 : 5 : case 'l':
2946 : 5 : p++;
2947 : 5 : data->type = REPL_TYPE_CHANGE_CASE;
2948 : 5 : data->change_case = CHANGE_CASE_LOWER_SINGLE;
2949 : 5 : break;
2950 : 6 : case 'u':
2951 : 6 : p++;
2952 : 6 : data->type = REPL_TYPE_CHANGE_CASE;
2953 : 6 : data->change_case = CHANGE_CASE_UPPER_SINGLE;
2954 : 6 : break;
2955 : 4 : case 'L':
2956 : 4 : p++;
2957 : 4 : data->type = REPL_TYPE_CHANGE_CASE;
2958 : 4 : data->change_case = CHANGE_CASE_LOWER;
2959 : 4 : break;
2960 : 7 : case 'U':
2961 : 7 : p++;
2962 : 7 : data->type = REPL_TYPE_CHANGE_CASE;
2963 : 7 : data->change_case = CHANGE_CASE_UPPER;
2964 : 7 : break;
2965 : 11 : case 'E':
2966 : 11 : p++;
2967 : 11 : data->type = REPL_TYPE_CHANGE_CASE;
2968 : 11 : data->change_case = CHANGE_CASE_NONE;
2969 : 11 : break;
2970 : 12 : case 'g':
2971 : 12 : p++;
2972 : 12 : if (*p != '<')
2973 : : {
2974 : 2 : error_detail = _("missing “<” in symbolic reference");
2975 : 2 : goto error;
2976 : : }
2977 : 10 : q = p + 1;
2978 : : do
2979 : : {
2980 : 22 : p++;
2981 : 22 : if (!*p)
2982 : : {
2983 : 1 : error_detail = _("unfinished symbolic reference");
2984 : 1 : goto error;
2985 : : }
2986 : : }
2987 : 21 : while (*p != '>');
2988 : 9 : if (p - q == 0)
2989 : : {
2990 : 1 : error_detail = _("zero-length symbolic reference");
2991 : 1 : goto error;
2992 : : }
2993 : 8 : if (g_ascii_isdigit (*q))
2994 : : {
2995 : 4 : x = 0;
2996 : : do
2997 : : {
2998 : 5 : h = g_ascii_digit_value (*q);
2999 : 5 : if (h < 0)
3000 : : {
3001 : 1 : error_detail = _("digit expected");
3002 : 1 : p = q;
3003 : 1 : goto error;
3004 : : }
3005 : 4 : x = x * 10 + h;
3006 : 4 : q++;
3007 : : }
3008 : 4 : while (q != p);
3009 : 3 : data->num = x;
3010 : 3 : data->type = REPL_TYPE_NUMERIC_REFERENCE;
3011 : : }
3012 : : else
3013 : : {
3014 : 4 : r = q;
3015 : : do
3016 : : {
3017 : 7 : if (!g_ascii_isalnum (*r))
3018 : : {
3019 : 1 : error_detail = _("illegal symbolic reference");
3020 : 1 : p = r;
3021 : 1 : goto error;
3022 : : }
3023 : 6 : r++;
3024 : : }
3025 : 6 : while (r != p);
3026 : 3 : data->text = g_strndup (q, p - q);
3027 : 3 : data->type = REPL_TYPE_SYMBOLIC_REFERENCE;
3028 : : }
3029 : 6 : p++;
3030 : 6 : break;
3031 : 27 : case '0':
3032 : : /* if \0 is followed by a number is an octal number representing a
3033 : : * character, else it is a numeric reference. */
3034 : 27 : if (g_ascii_digit_value (*g_utf8_next_char (p)) >= 0)
3035 : : {
3036 : 7 : base = 8;
3037 : 7 : p = g_utf8_next_char (p);
3038 : : }
3039 : : G_GNUC_FALLTHROUGH;
3040 : : case '1':
3041 : : case '2':
3042 : : case '3':
3043 : : case '4':
3044 : : case '5':
3045 : : case '6':
3046 : : case '7':
3047 : : case '8':
3048 : : case '9':
3049 : 51 : x = 0;
3050 : 51 : d = 0;
3051 : 112 : for (i = 0; i < 3; i++)
3052 : : {
3053 : 108 : h = g_ascii_digit_value (*p);
3054 : 108 : if (h < 0)
3055 : 45 : break;
3056 : 63 : if (h > 7)
3057 : : {
3058 : 2 : if (base == 8)
3059 : 2 : break;
3060 : : else
3061 : 0 : base = 10;
3062 : : }
3063 : 61 : if (i == 2 && base == 10)
3064 : 0 : break;
3065 : 61 : x = x * 8 + h;
3066 : 61 : d = d * 10 + h;
3067 : 61 : p++;
3068 : : }
3069 : 51 : if (base == 8 || i == 3)
3070 : : {
3071 : 7 : data->type = REPL_TYPE_STRING;
3072 : 7 : data->text = g_new0 (gchar, 8);
3073 : 7 : g_unichar_to_utf8 (x, data->text);
3074 : : }
3075 : : else
3076 : : {
3077 : 44 : data->type = REPL_TYPE_NUMERIC_REFERENCE;
3078 : 44 : data->num = d;
3079 : : }
3080 : 51 : break;
3081 : 1 : case 0:
3082 : 1 : error_detail = _("stray final “\\”");
3083 : 1 : goto error;
3084 : : break;
3085 : 8 : default:
3086 : 8 : error_detail = _("unknown escape sequence");
3087 : 8 : goto error;
3088 : : }
3089 : :
3090 : 121 : return p;
3091 : :
3092 : 17 : error:
3093 : : /* G_GSSIZE_FORMAT doesn't work with gettext, so we use %lu */
3094 : 17 : tmp_error = g_error_new (G_REGEX_ERROR,
3095 : : G_REGEX_ERROR_REPLACE,
3096 : : _("Error while parsing replacement "
3097 : : "text “%s” at char %lu: %s"),
3098 : : replacement,
3099 : 17 : (gulong)(p - replacement),
3100 : : error_detail);
3101 : 17 : g_propagate_error (error, tmp_error);
3102 : :
3103 : 17 : return NULL;
3104 : : }
3105 : :
3106 : : static GList *
3107 : 130 : split_replacement (const gchar *replacement,
3108 : : GError **error)
3109 : : {
3110 : 130 : GList *list = NULL;
3111 : : InterpolationData *data;
3112 : : const gchar *p, *start;
3113 : :
3114 : 130 : start = p = replacement;
3115 : 356 : while (*p)
3116 : : {
3117 : 243 : if (*p == '\\')
3118 : : {
3119 : 138 : data = g_new0 (InterpolationData, 1);
3120 : 138 : start = p = expand_escape (replacement, p, data, error);
3121 : 138 : if (p == NULL)
3122 : : {
3123 : 17 : g_list_free_full (list, (GDestroyNotify) free_interpolation_data);
3124 : 17 : free_interpolation_data (data);
3125 : :
3126 : 17 : return NULL;
3127 : : }
3128 : 121 : list = g_list_prepend (list, data);
3129 : : }
3130 : : else
3131 : : {
3132 : 105 : p++;
3133 : 105 : if (*p == '\\' || *p == '\0')
3134 : : {
3135 : 87 : if (p - start > 0)
3136 : : {
3137 : 87 : data = g_new0 (InterpolationData, 1);
3138 : 87 : data->text = g_strndup (start, p - start);
3139 : 87 : data->type = REPL_TYPE_STRING;
3140 : 87 : list = g_list_prepend (list, data);
3141 : : }
3142 : : }
3143 : : }
3144 : : }
3145 : :
3146 : 113 : return g_list_reverse (list);
3147 : : }
3148 : :
3149 : : /* Change the case of c based on change_case. */
3150 : : #define CHANGE_CASE(c, change_case) \
3151 : : (((change_case) & CHANGE_CASE_LOWER_MASK) ? \
3152 : : g_unichar_tolower (c) : \
3153 : : g_unichar_toupper (c))
3154 : :
3155 : : static void
3156 : 179 : string_append (GString *string,
3157 : : const gchar *text,
3158 : : ChangeCase *change_case)
3159 : : {
3160 : : gunichar c;
3161 : :
3162 : 179 : if (text[0] == '\0')
3163 : 4 : return;
3164 : :
3165 : 175 : if (*change_case == CHANGE_CASE_NONE)
3166 : : {
3167 : : g_string_append (string, text);
3168 : : }
3169 : 33 : else if (*change_case & CHANGE_CASE_SINGLE_MASK)
3170 : : {
3171 : 10 : c = g_utf8_get_char (text);
3172 : 10 : g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
3173 : 10 : g_string_append (string, g_utf8_next_char (text));
3174 : 10 : *change_case = CHANGE_CASE_NONE;
3175 : : }
3176 : : else
3177 : : {
3178 : 73 : while (*text != '\0')
3179 : : {
3180 : 50 : c = g_utf8_get_char (text);
3181 : 50 : g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
3182 : 50 : text = g_utf8_next_char (text);
3183 : : }
3184 : : }
3185 : : }
3186 : :
3187 : : static gboolean
3188 : 133 : interpolate_replacement (const GMatchInfo *match_info,
3189 : : GString *result,
3190 : : gpointer data)
3191 : : {
3192 : : GList *list;
3193 : : InterpolationData *idata;
3194 : : gchar *match;
3195 : 133 : ChangeCase change_case = CHANGE_CASE_NONE;
3196 : :
3197 : 368 : for (list = data; list; list = list->next)
3198 : : {
3199 : 235 : idata = list->data;
3200 : 235 : switch (idata->type)
3201 : : {
3202 : 122 : case REPL_TYPE_STRING:
3203 : 122 : string_append (result, idata->text, &change_case);
3204 : 122 : break;
3205 : 13 : case REPL_TYPE_CHARACTER:
3206 : 13 : g_string_append_c (result, CHANGE_CASE (idata->c, change_case));
3207 : 13 : if (change_case & CHANGE_CASE_SINGLE_MASK)
3208 : 1 : change_case = CHANGE_CASE_NONE;
3209 : 13 : break;
3210 : 57 : case REPL_TYPE_NUMERIC_REFERENCE:
3211 : 57 : match = g_match_info_fetch (match_info, idata->num);
3212 : 57 : if (match)
3213 : : {
3214 : 55 : string_append (result, match, &change_case);
3215 : 55 : g_free (match);
3216 : : }
3217 : 57 : break;
3218 : 2 : case REPL_TYPE_SYMBOLIC_REFERENCE:
3219 : 2 : match = g_match_info_fetch_named (match_info, idata->text);
3220 : 2 : if (match)
3221 : : {
3222 : 2 : string_append (result, match, &change_case);
3223 : 2 : g_free (match);
3224 : : }
3225 : 2 : break;
3226 : 41 : case REPL_TYPE_CHANGE_CASE:
3227 : 41 : change_case = idata->change_case;
3228 : 41 : break;
3229 : : }
3230 : : }
3231 : :
3232 : 133 : return FALSE;
3233 : : }
3234 : :
3235 : : /* whether actual match_info is needed for replacement, i.e.
3236 : : * whether there are references
3237 : : */
3238 : : static gboolean
3239 : 8 : interpolation_list_needs_match (GList *list)
3240 : : {
3241 : 20 : while (list != NULL)
3242 : : {
3243 : 15 : InterpolationData *data = list->data;
3244 : :
3245 : 15 : if (data->type == REPL_TYPE_SYMBOLIC_REFERENCE ||
3246 : 14 : data->type == REPL_TYPE_NUMERIC_REFERENCE)
3247 : : {
3248 : 3 : return TRUE;
3249 : : }
3250 : :
3251 : 12 : list = list->next;
3252 : : }
3253 : :
3254 : 5 : return FALSE;
3255 : : }
3256 : :
3257 : : /**
3258 : : * g_regex_replace:
3259 : : * @regex: a #GRegex structure
3260 : : * @string: (array length=string_len): the string to perform matches against
3261 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
3262 : : * @start_position: starting index of the string to match, in bytes
3263 : : * @replacement: text to replace each match with
3264 : : * @match_options: options for the match
3265 : : * @error: location to store the error occurring, or %NULL to ignore errors
3266 : : *
3267 : : * Replaces all occurrences of the pattern in @regex with the
3268 : : * replacement text. Backreferences of the form `\number` or
3269 : : * `\g<number>` in the replacement text are interpolated by the
3270 : : * number-th captured subexpression of the match, `\g<name>` refers
3271 : : * to the captured subexpression with the given name. `\0` refers
3272 : : * to the complete match, but `\0` followed by a number is the octal
3273 : : * representation of a character. To include a literal `\` in the
3274 : : * replacement, write `\\\\`.
3275 : : *
3276 : : * There are also escapes that changes the case of the following text:
3277 : : *
3278 : : * - \l: Convert to lower case the next character
3279 : : * - \u: Convert to upper case the next character
3280 : : * - \L: Convert to lower case till \E
3281 : : * - \U: Convert to upper case till \E
3282 : : * - \E: End case modification
3283 : : *
3284 : : * If you do not need to use backreferences use g_regex_replace_literal().
3285 : : *
3286 : : * The @replacement string must be UTF-8 encoded even if %G_REGEX_RAW was
3287 : : * passed to g_regex_new(). If you want to use not UTF-8 encoded strings
3288 : : * you can use g_regex_replace_literal().
3289 : : *
3290 : : * Setting @start_position differs from just passing over a shortened
3291 : : * string and setting %G_REGEX_MATCH_NOTBOL in the case of a pattern that
3292 : : * begins with any kind of lookbehind assertion, such as "\b".
3293 : : *
3294 : : * Returns: a newly allocated string containing the replacements
3295 : : *
3296 : : * Since: 2.14
3297 : : */
3298 : : gchar *
3299 : 56 : g_regex_replace (const GRegex *regex,
3300 : : const gchar *string,
3301 : : gssize string_len,
3302 : : gint start_position,
3303 : : const gchar *replacement,
3304 : : GRegexMatchFlags match_options,
3305 : : GError **error)
3306 : : {
3307 : : gchar *result;
3308 : : GList *list;
3309 : 56 : GError *tmp_error = NULL;
3310 : :
3311 : 56 : g_return_val_if_fail (regex != NULL, NULL);
3312 : 56 : g_return_val_if_fail (string != NULL, NULL);
3313 : 56 : g_return_val_if_fail (start_position >= 0, NULL);
3314 : 56 : g_return_val_if_fail (replacement != NULL, NULL);
3315 : 56 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3316 : 56 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
3317 : :
3318 : 56 : list = split_replacement (replacement, &tmp_error);
3319 : 56 : if (tmp_error != NULL)
3320 : : {
3321 : 4 : g_propagate_error (error, tmp_error);
3322 : 4 : return NULL;
3323 : : }
3324 : :
3325 : 52 : result = g_regex_replace_eval (regex,
3326 : : string, string_len, start_position,
3327 : : match_options,
3328 : : interpolate_replacement,
3329 : : (gpointer)list,
3330 : : &tmp_error);
3331 : 52 : if (tmp_error != NULL)
3332 : 0 : g_propagate_error (error, tmp_error);
3333 : :
3334 : 52 : g_list_free_full (list, (GDestroyNotify) free_interpolation_data);
3335 : :
3336 : 52 : return result;
3337 : : }
3338 : :
3339 : : static gboolean
3340 : 60 : literal_replacement (const GMatchInfo *match_info,
3341 : : GString *result,
3342 : : gpointer data)
3343 : : {
3344 : : g_string_append (result, data);
3345 : 60 : return FALSE;
3346 : : }
3347 : :
3348 : : /**
3349 : : * g_regex_replace_literal:
3350 : : * @regex: a #GRegex structure
3351 : : * @string: (array length=string_len): the string to perform matches against
3352 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
3353 : : * @start_position: starting index of the string to match, in bytes
3354 : : * @replacement: text to replace each match with
3355 : : * @match_options: options for the match
3356 : : * @error: location to store the error occurring, or %NULL to ignore errors
3357 : : *
3358 : : * Replaces all occurrences of the pattern in @regex with the
3359 : : * replacement text. @replacement is replaced literally, to
3360 : : * include backreferences use g_regex_replace().
3361 : : *
3362 : : * Setting @start_position differs from just passing over a
3363 : : * shortened string and setting %G_REGEX_MATCH_NOTBOL in the
3364 : : * case of a pattern that begins with any kind of lookbehind
3365 : : * assertion, such as "\b".
3366 : : *
3367 : : * Returns: a newly allocated string containing the replacements
3368 : : *
3369 : : * Since: 2.14
3370 : : */
3371 : : gchar *
3372 : 38 : g_regex_replace_literal (const GRegex *regex,
3373 : : const gchar *string,
3374 : : gssize string_len,
3375 : : gint start_position,
3376 : : const gchar *replacement,
3377 : : GRegexMatchFlags match_options,
3378 : : GError **error)
3379 : : {
3380 : 38 : g_return_val_if_fail (replacement != NULL, NULL);
3381 : 38 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
3382 : :
3383 : 38 : return g_regex_replace_eval (regex,
3384 : : string, string_len, start_position,
3385 : : match_options,
3386 : : literal_replacement,
3387 : : (gpointer)replacement,
3388 : : error);
3389 : : }
3390 : :
3391 : : /**
3392 : : * g_regex_replace_eval:
3393 : : * @regex: a #GRegex structure from g_regex_new()
3394 : : * @string: (array length=string_len): string to perform matches against
3395 : : * @string_len: the length of @string, in bytes, or -1 if @string is nul-terminated
3396 : : * @start_position: starting index of the string to match, in bytes
3397 : : * @match_options: options for the match
3398 : : * @eval: (scope call): a function to call for each match
3399 : : * @user_data: user data to pass to the function
3400 : : * @error: location to store the error occurring, or %NULL to ignore errors
3401 : : *
3402 : : * Replaces occurrences of the pattern in regex with the output of
3403 : : * @eval for that occurrence.
3404 : : *
3405 : : * Setting @start_position differs from just passing over a shortened
3406 : : * string and setting %G_REGEX_MATCH_NOTBOL in the case of a pattern
3407 : : * that begins with any kind of lookbehind assertion, such as "\b".
3408 : : *
3409 : : * The following example uses g_regex_replace_eval() to replace multiple
3410 : : * strings at once:
3411 : : * |[<!-- language="C" -->
3412 : : * static gboolean
3413 : : * eval_cb (const GMatchInfo *info,
3414 : : * GString *res,
3415 : : * gpointer data)
3416 : : * {
3417 : : * gchar *match;
3418 : : * gchar *r;
3419 : : *
3420 : : * match = g_match_info_fetch (info, 0);
3421 : : * r = g_hash_table_lookup ((GHashTable *)data, match);
3422 : : * g_string_append (res, r);
3423 : : * g_free (match);
3424 : : *
3425 : : * return FALSE;
3426 : : * }
3427 : : *
3428 : : * ...
3429 : : *
3430 : : * GRegex *reg;
3431 : : * GHashTable *h;
3432 : : * gchar *res;
3433 : : *
3434 : : * h = g_hash_table_new (g_str_hash, g_str_equal);
3435 : : *
3436 : : * g_hash_table_insert (h, "1", "ONE");
3437 : : * g_hash_table_insert (h, "2", "TWO");
3438 : : * g_hash_table_insert (h, "3", "THREE");
3439 : : * g_hash_table_insert (h, "4", "FOUR");
3440 : : *
3441 : : * reg = g_regex_new ("1|2|3|4", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
3442 : : * res = g_regex_replace_eval (reg, text, -1, 0, 0, eval_cb, h, NULL);
3443 : : * g_hash_table_destroy (h);
3444 : : *
3445 : : * ...
3446 : : * ]|
3447 : : *
3448 : : * Returns: a newly allocated string containing the replacements
3449 : : *
3450 : : * Since: 2.14
3451 : : */
3452 : : gchar *
3453 : 90 : g_regex_replace_eval (const GRegex *regex,
3454 : : const gchar *string,
3455 : : gssize string_len,
3456 : : gint start_position,
3457 : : GRegexMatchFlags match_options,
3458 : : GRegexEvalCallback eval,
3459 : : gpointer user_data,
3460 : : GError **error)
3461 : : {
3462 : : GMatchInfo *match_info;
3463 : : GString *result;
3464 : 90 : gint str_pos = 0;
3465 : 90 : gboolean done = FALSE;
3466 : 90 : GError *tmp_error = NULL;
3467 : :
3468 : 90 : g_return_val_if_fail (regex != NULL, NULL);
3469 : 90 : g_return_val_if_fail (string != NULL, NULL);
3470 : 90 : g_return_val_if_fail (start_position >= 0, NULL);
3471 : 90 : g_return_val_if_fail (eval != NULL, NULL);
3472 : 90 : g_return_val_if_fail ((match_options & ~G_REGEX_MATCH_MASK) == 0, NULL);
3473 : :
3474 : 90 : if (string_len < 0)
3475 : 90 : string_len = strlen (string);
3476 : :
3477 : 90 : result = g_string_sized_new (string_len);
3478 : :
3479 : : /* run down the string making matches. */
3480 : 90 : g_regex_match_full (regex, string, string_len, start_position,
3481 : : match_options, &match_info, &tmp_error);
3482 : 228 : while (!done && g_match_info_matches (match_info))
3483 : : {
3484 : 138 : g_string_append_len (result,
3485 : : string + str_pos,
3486 : : match_info->offsets[0] - str_pos);
3487 : 138 : done = (*eval) (match_info, result, user_data);
3488 : 138 : str_pos = match_info->offsets[1];
3489 : 138 : g_match_info_next (match_info, &tmp_error);
3490 : : }
3491 : 90 : g_match_info_free (match_info);
3492 : 90 : if (tmp_error != NULL)
3493 : : {
3494 : 0 : g_propagate_error (error, tmp_error);
3495 : 0 : g_string_free (result, TRUE);
3496 : 0 : return NULL;
3497 : : }
3498 : :
3499 : 90 : g_string_append_len (result, string + str_pos, string_len - str_pos);
3500 : 90 : return g_string_free (result, FALSE);
3501 : : }
3502 : :
3503 : : /**
3504 : : * g_regex_check_replacement:
3505 : : * @replacement: the replacement string
3506 : : * @has_references: (out) (optional): location to store information about
3507 : : * references in @replacement or %NULL
3508 : : * @error: location to store error
3509 : : *
3510 : : * Checks whether @replacement is a valid replacement string
3511 : : * (see g_regex_replace()), i.e. that all escape sequences in
3512 : : * it are valid.
3513 : : *
3514 : : * If @has_references is not %NULL then @replacement is checked
3515 : : * for pattern references. For instance, replacement text 'foo\n'
3516 : : * does not contain references and may be evaluated without information
3517 : : * about actual match, but '\0\1' (whole match followed by first
3518 : : * subpattern) requires valid #GMatchInfo object.
3519 : : *
3520 : : * Returns: whether @replacement is a valid replacement string
3521 : : *
3522 : : * Since: 2.14
3523 : : */
3524 : : gboolean
3525 : 8 : g_regex_check_replacement (const gchar *replacement,
3526 : : gboolean *has_references,
3527 : : GError **error)
3528 : : {
3529 : : GList *list;
3530 : 8 : GError *tmp = NULL;
3531 : :
3532 : 8 : list = split_replacement (replacement, &tmp);
3533 : :
3534 : 8 : if (tmp)
3535 : : {
3536 : 2 : g_propagate_error (error, tmp);
3537 : 2 : return FALSE;
3538 : : }
3539 : :
3540 : 6 : if (has_references)
3541 : 6 : *has_references = interpolation_list_needs_match (list);
3542 : :
3543 : 6 : g_list_free_full (list, (GDestroyNotify) free_interpolation_data);
3544 : :
3545 : 6 : return TRUE;
3546 : : }
3547 : :
3548 : : /**
3549 : : * g_regex_escape_nul:
3550 : : * @string: the string to escape
3551 : : * @length: the length of @string
3552 : : *
3553 : : * Escapes the nul characters in @string to "\x00". It can be used
3554 : : * to compile a regex with embedded nul characters.
3555 : : *
3556 : : * For completeness, @length can be -1 for a nul-terminated string.
3557 : : * In this case the output string will be of course equal to @string.
3558 : : *
3559 : : * Returns: a newly-allocated escaped string
3560 : : *
3561 : : * Since: 2.30
3562 : : */
3563 : : gchar *
3564 : 15 : g_regex_escape_nul (const gchar *string,
3565 : : gint length)
3566 : : {
3567 : : GString *escaped;
3568 : : const gchar *p, *piece_start, *end;
3569 : : gint backslashes;
3570 : :
3571 : 15 : g_return_val_if_fail (string != NULL, NULL);
3572 : :
3573 : 15 : if (length < 0)
3574 : 3 : return g_strdup (string);
3575 : :
3576 : 12 : end = string + length;
3577 : 12 : p = piece_start = string;
3578 : 12 : escaped = g_string_sized_new (length + 1);
3579 : :
3580 : 12 : backslashes = 0;
3581 : 125 : while (p < end)
3582 : : {
3583 : 113 : switch (*p)
3584 : : {
3585 : 9 : case '\0':
3586 : 9 : if (p != piece_start)
3587 : : {
3588 : : /* copy the previous piece. */
3589 : 6 : g_string_append_len (escaped, piece_start, p - piece_start);
3590 : : }
3591 : 9 : if ((backslashes & 1) == 0)
3592 : : g_string_append_c (escaped, '\\');
3593 : : g_string_append_c (escaped, 'x');
3594 : : g_string_append_c (escaped, '0');
3595 : : g_string_append_c (escaped, '0');
3596 : 9 : piece_start = ++p;
3597 : 9 : backslashes = 0;
3598 : 9 : break;
3599 : 6 : case '\\':
3600 : 6 : backslashes++;
3601 : 6 : ++p;
3602 : 6 : break;
3603 : 98 : default:
3604 : 98 : backslashes = 0;
3605 : 98 : p = g_utf8_next_char (p);
3606 : 98 : break;
3607 : : }
3608 : : }
3609 : :
3610 : 12 : if (piece_start < end)
3611 : 9 : g_string_append_len (escaped, piece_start, end - piece_start);
3612 : :
3613 : 12 : return g_string_free (escaped, FALSE);
3614 : : }
3615 : :
3616 : : /**
3617 : : * g_regex_escape_string:
3618 : : * @string: the string to escape
3619 : : * @length: the length of @string, in bytes, or -1 if @string is nul-terminated
3620 : : *
3621 : : * Escapes the special characters used for regular expressions
3622 : : * in @string, for instance "a.b*c" becomes "a\.b\*c". This
3623 : : * function is useful to dynamically generate regular expressions.
3624 : : *
3625 : : * @string can contain nul characters that are replaced with "\0",
3626 : : * in this case remember to specify the correct length of @string
3627 : : * in @length.
3628 : : *
3629 : : * Returns: a newly-allocated escaped string
3630 : : *
3631 : : * Since: 2.14
3632 : : */
3633 : : gchar *
3634 : 18 : g_regex_escape_string (const gchar *string,
3635 : : gint length)
3636 : : {
3637 : : GString *escaped;
3638 : : const char *p, *piece_start, *end;
3639 : :
3640 : 18 : g_return_val_if_fail (string != NULL, NULL);
3641 : :
3642 : 18 : if (length < 0)
3643 : 11 : length = strlen (string);
3644 : :
3645 : 18 : end = string + length;
3646 : 18 : p = piece_start = string;
3647 : 18 : escaped = g_string_sized_new (length + 1);
3648 : :
3649 : 131 : while (p < end)
3650 : : {
3651 : 113 : switch (*p)
3652 : : {
3653 : 45 : case '\0':
3654 : : case '\\':
3655 : : case '|':
3656 : : case '(':
3657 : : case ')':
3658 : : case '[':
3659 : : case ']':
3660 : : case '{':
3661 : : case '}':
3662 : : case '^':
3663 : : case '$':
3664 : : case '*':
3665 : : case '+':
3666 : : case '?':
3667 : : case '.':
3668 : 45 : if (p != piece_start)
3669 : : /* copy the previous piece. */
3670 : 24 : g_string_append_len (escaped, piece_start, p - piece_start);
3671 : : g_string_append_c (escaped, '\\');
3672 : 45 : if (*p == '\0')
3673 : : g_string_append_c (escaped, '0');
3674 : : else
3675 : 43 : g_string_append_c (escaped, *p);
3676 : 45 : piece_start = ++p;
3677 : 45 : break;
3678 : 68 : default:
3679 : 68 : p = g_utf8_next_char (p);
3680 : 68 : break;
3681 : : }
3682 : : }
3683 : :
3684 : 18 : if (piece_start < end)
3685 : 10 : g_string_append_len (escaped, piece_start, end - piece_start);
3686 : :
3687 : 18 : return g_string_free (escaped, FALSE);
3688 : : }
|