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

Generated by: LCOV version 2.0-1