LCOV - code coverage report
Current view: top level - glib - gregex.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 85.8 % 1281 1099
Test Date: 2026-01-13 05:17:23 Functions: 97.0 % 66 64
Branches: - 0 0

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

Generated by: LCOV version 2.0-1