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