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