summaryrefslogtreecommitdiff
path: root/glib/tests/regex.c
diff options
context:
space:
mode:
Diffstat (limited to 'glib/tests/regex.c')
-rw-r--r--glib/tests/regex.c694
1 files changed, 535 insertions, 159 deletions
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
index e19f97587..cf2bb8199 100644
--- a/glib/tests/regex.c
+++ b/glib/tests/regex.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2005 - 2006, Marco Barisione <marco@barisione.org>
* Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2022, Marco Trevisan <marco.trevisan@canonical.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
@@ -27,7 +28,8 @@
#include <locale.h>
#include "glib.h"
-#include <pcre.h>
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
/* U+20AC EURO SIGN (symbol, currency) */
#define EURO "\xe2\x82\xac"
@@ -104,7 +106,7 @@ test_new (gconstpointer d)
data = g_new0 (TestNewData, 1); \
data->pattern = _pattern; \
data->compile_opts = _compile_opts; \
- data->match_opts = 0; \
+ data->match_opts = _match_opts; \
data->expected_error = 0; \
data->check_flags = TRUE; \
data->real_compile_opts = _real_compile_opts; \
@@ -171,7 +173,24 @@ test_match_simple (gconstpointer d)
data->compile_opts = _compile_opts; \
data->match_opts = _match_opts; \
data->expected = _expected; \
- path = g_strdup_printf ("/regex/match-%s/%d", _name, ++total); \
+ total++; \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ path = g_strdup_printf ("/regex/match-%s-optimized/%d", _name, total); \
+ else \
+ path = g_strdup_printf ("/regex/match-%s/%d", _name, total); \
+ g_test_add_data_func_full (path, data, test_match_simple, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestMatchData)); \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ { \
+ data->compile_opts &= ~G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match-%s/%d", _name, total); \
+ } \
+ else \
+ { \
+ data->compile_opts |= G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match-%s-optimized/%d", _name, total); \
+ } \
g_test_add_data_func_full (path, data, test_match_simple, g_free); \
g_free (path); \
}
@@ -183,6 +202,108 @@ test_match_simple (gconstpointer d)
#define TEST_MATCH_NOTEMPTY_ATSTART(_pattern, _string, _expected) \
TEST_MATCH_SIMPLE_NAMED("notempty-atstart", _pattern, _string, 0, G_REGEX_MATCH_NOTEMPTY_ATSTART, _expected)
+static char *
+compile_options_to_string (GRegexCompileFlags compile_flags)
+{
+ GStrvBuilder *builder = g_strv_builder_new();
+ GStrv strv;
+ char *ret;
+
+ if (compile_flags & G_REGEX_DEFAULT)
+ g_strv_builder_add (builder, "default");
+ if (compile_flags & G_REGEX_CASELESS)
+ g_strv_builder_add (builder, "caseless");
+ if (compile_flags & G_REGEX_MULTILINE)
+ g_strv_builder_add (builder, "multiline");
+ if (compile_flags & G_REGEX_DOTALL)
+ g_strv_builder_add (builder, "dotall");
+ if (compile_flags & G_REGEX_EXTENDED)
+ g_strv_builder_add (builder, "extended");
+ if (compile_flags & G_REGEX_ANCHORED)
+ g_strv_builder_add (builder, "anchored");
+ if (compile_flags & G_REGEX_DOLLAR_ENDONLY)
+ g_strv_builder_add (builder, "dollar-endonly");
+ if (compile_flags & G_REGEX_UNGREEDY)
+ g_strv_builder_add (builder, "ungreedy");
+ if (compile_flags & G_REGEX_RAW)
+ g_strv_builder_add (builder, "raw");
+ if (compile_flags & G_REGEX_NO_AUTO_CAPTURE)
+ g_strv_builder_add (builder, "no-auto-capture");
+ if (compile_flags & G_REGEX_OPTIMIZE)
+ g_strv_builder_add (builder, "optimize");
+ if (compile_flags & G_REGEX_FIRSTLINE)
+ g_strv_builder_add (builder, "firstline");
+ if (compile_flags & G_REGEX_DUPNAMES)
+ g_strv_builder_add (builder, "dupnames");
+ if (compile_flags & G_REGEX_NEWLINE_CR)
+ g_strv_builder_add (builder, "newline-cr");
+ if (compile_flags & G_REGEX_NEWLINE_LF)
+ g_strv_builder_add (builder, "newline-lf");
+ if (compile_flags & G_REGEX_NEWLINE_CRLF)
+ g_strv_builder_add (builder, "newline-crlf");
+ if (compile_flags & G_REGEX_NEWLINE_ANYCRLF)
+ g_strv_builder_add (builder, "newline-anycrlf");
+ if (compile_flags & G_REGEX_BSR_ANYCRLF)
+ g_strv_builder_add (builder, "bsr-anycrlf");
+
+ strv = g_strv_builder_end (builder);
+ ret = g_strjoinv ("|", strv);
+
+ g_strfreev (strv);
+ g_strv_builder_unref (builder);
+
+ return ret;
+}
+
+static char *
+match_options_to_string (GRegexMatchFlags match_flags)
+{
+ GStrvBuilder *builder = g_strv_builder_new();
+ GStrv strv;
+ char *ret;
+
+ if (match_flags & G_REGEX_MATCH_DEFAULT)
+ g_strv_builder_add (builder, "default");
+ if (match_flags & G_REGEX_MATCH_ANCHORED)
+ g_strv_builder_add (builder, "anchored");
+ if (match_flags & G_REGEX_MATCH_NOTBOL)
+ g_strv_builder_add (builder, "notbol");
+ if (match_flags & G_REGEX_MATCH_NOTEOL)
+ g_strv_builder_add (builder, "noteol");
+ if (match_flags & G_REGEX_MATCH_NOTEMPTY)
+ g_strv_builder_add (builder, "notempty");
+ if (match_flags & G_REGEX_MATCH_PARTIAL)
+ g_strv_builder_add (builder, "partial");
+ if (match_flags & G_REGEX_MATCH_NEWLINE_CR)
+ g_strv_builder_add (builder, "newline-cr");
+ if (match_flags & G_REGEX_MATCH_NEWLINE_LF)
+ g_strv_builder_add (builder, "newline-lf");
+ if (match_flags & G_REGEX_MATCH_NEWLINE_CRLF)
+ g_strv_builder_add (builder, "newline-crlf");
+ if (match_flags & G_REGEX_MATCH_NEWLINE_ANY)
+ g_strv_builder_add (builder, "newline-any");
+ if (match_flags & G_REGEX_MATCH_NEWLINE_ANYCRLF)
+ g_strv_builder_add (builder, "newline-anycrlf");
+ if (match_flags & G_REGEX_MATCH_BSR_ANYCRLF)
+ g_strv_builder_add (builder, "bsr-anycrlf");
+ if (match_flags & G_REGEX_MATCH_BSR_ANY)
+ g_strv_builder_add (builder, "bsr-any");
+ if (match_flags & G_REGEX_MATCH_PARTIAL_SOFT)
+ g_strv_builder_add (builder, "partial-soft");
+ if (match_flags & G_REGEX_MATCH_PARTIAL_HARD)
+ g_strv_builder_add (builder, "partial-hard");
+ if (match_flags & G_REGEX_MATCH_NOTEMPTY_ATSTART)
+ g_strv_builder_add (builder, "notempty-atstart");
+
+ strv = g_strv_builder_end (builder);
+ ret = g_strjoinv ("|", strv);
+
+ g_strfreev (strv);
+ g_strv_builder_unref (builder);
+
+ return ret;
+}
+
static void
test_match (gconstpointer d)
{
@@ -190,6 +311,9 @@ test_match (gconstpointer d)
GRegex *regex;
gboolean match;
GError *error = NULL;
+ gchar *compile_opts_str;
+ gchar *match_opts_str;
+ gchar *match_opts2_str;
regex = g_regex_new (data->pattern, data->compile_opts, data->match_opts, &error);
g_assert (regex != NULL);
@@ -198,31 +322,35 @@ test_match (gconstpointer d)
match = g_regex_match_full (regex, data->string, data->string_len,
data->start_position, data->match_opts2, NULL, NULL);
+ compile_opts_str = compile_options_to_string (data->compile_opts);
+ match_opts_str = match_options_to_string (data->match_opts);
+ match_opts2_str = match_options_to_string (data->match_opts2);
+
if (data->expected)
{
if (!match)
- g_error ("Regex '%s' (with compile options %u and "
- "match options %u) should have matched '%.*s' "
- "(of length %d, at position %d, with match options %u) but did not",
- data->pattern, data->compile_opts, data->match_opts,
+ g_error ("Regex '%s' (with compile options '%s' and "
+ "match options '%s') should have matched '%.*s' "
+ "(of length %d, at position %d, with match options '%s') but did not",
+ data->pattern, compile_opts_str, match_opts_str,
data->string_len == -1 ? (int) strlen (data->string) :
(int) data->string_len,
data->string, (int) data->string_len,
- data->start_position, data->match_opts2);
+ data->start_position, match_opts2_str);
g_assert_cmpint (match, ==, TRUE);
}
else
{
if (match)
- g_error ("Regex '%s' (with compile options %u and "
- "match options %u) should not have matched '%.*s' "
- "(of length %d, at position %d, with match options %u) but did",
- data->pattern, data->compile_opts, data->match_opts,
+ g_error ("Regex '%s' (with compile options '%s' and "
+ "match options '%s') should not have matched '%.*s' "
+ "(of length %d, at position %d, with match options '%s') but did",
+ data->pattern, compile_opts_str, match_opts_str,
data->string_len == -1 ? (int) strlen (data->string) :
(int) data->string_len,
data->string, (int) data->string_len,
- data->start_position, data->match_opts2);
+ data->start_position, match_opts2_str);
}
if (data->string_len == -1 && data->start_position == 0)
@@ -231,6 +359,9 @@ test_match (gconstpointer d)
g_assert_cmpint (match, ==, data->expected);
}
+ g_free (compile_opts_str);
+ g_free (match_opts_str);
+ g_free (match_opts2_str);
g_regex_unref (regex);
}
@@ -247,7 +378,24 @@ test_match (gconstpointer d)
data->start_position = _start_position; \
data->match_opts2 = _match_opts2; \
data->expected = _expected; \
- path = g_strdup_printf ("/regex/match/%d", ++total); \
+ total++; \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ path = g_strdup_printf ("/regex/match-optimized/%d", total); \
+ else \
+ path = g_strdup_printf ("/regex/match/%d", total); \
+ g_test_add_data_func_full (path, data, test_match, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestMatchData)); \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ { \
+ data->compile_opts &= ~G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match/%d", total); \
+ } \
+ else \
+ { \
+ data->compile_opts |= G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match-optimized/%d", total); \
+ } \
g_test_add_data_func_full (path, data, test_match, g_free); \
g_free (path); \
}
@@ -286,7 +434,7 @@ test_match_next (gconstpointer d)
GSList *matches;
GSList *l_exp, *l_match;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -466,6 +614,7 @@ typedef struct {
const gchar *pattern;
const gchar *string;
gint start_position;
+ GRegexCompileFlags compile_flags;
GRegexMatchFlags match_opts;
gint expected_count;
} TestMatchCountData;
@@ -478,7 +627,8 @@ test_match_count (gconstpointer d)
GMatchInfo *match_info;
gint count;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, data->compile_flags,
+ G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -503,7 +653,14 @@ test_match_count (gconstpointer d)
data->start_position = _start_position; \
data->match_opts = _match_opts; \
data->expected_count = _expected_count; \
- path = g_strdup_printf ("/regex/match/count/%d", ++total); \
+ data->compile_flags = G_REGEX_DEFAULT; \
+ total++; \
+ path = g_strdup_printf ("/regex/match/count/%d", total); \
+ g_test_add_data_func_full (path, data, test_match_count, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestMatchCountData)); \
+ data->compile_flags |= G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match/count-optimized/%d", total); \
g_test_add_data_func_full (path, data, test_match_count, g_free); \
g_free (path); \
}
@@ -515,7 +672,7 @@ test_partial (gconstpointer d)
GRegex *regex;
GMatchInfo *match_info;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, data->compile_opts, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -533,24 +690,43 @@ test_partial (gconstpointer d)
g_regex_unref (regex);
}
-#define TEST_PARTIAL_FULL(_pattern, _string, _match_opts, _expected) { \
+#define TEST_PARTIAL_FULL(_pattern, _string, _compile_opts, _match_opts, _expected) { \
TestMatchData *data; \
gchar *path; \
data = g_new0 (TestMatchData, 1); \
data->pattern = _pattern; \
data->string = _string; \
+ data->compile_opts = _compile_opts; \
data->match_opts = _match_opts; \
data->expected = _expected; \
- path = g_strdup_printf ("/regex/match/partial/%d", ++total); \
+ total++; \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ path = g_strdup_printf ("/regex/match/partial-optimized/%d", total); \
+ else \
+ path = g_strdup_printf ("/regex/match/partial%d", total); \
+ g_test_add_data_func_full (path, data, test_partial, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestMatchData)); \
+ if (data->compile_opts & G_REGEX_OPTIMIZE) \
+ { \
+ data->compile_opts &= ~G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match/partial%d", total); \
+ } \
+ else \
+ { \
+ data->compile_opts |= G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match/partial-optimized/%d", total); \
+ } \
g_test_add_data_func_full (path, data, test_partial, g_free); \
g_free (path); \
}
-#define TEST_PARTIAL(_pattern, _string, _expected) TEST_PARTIAL_FULL(_pattern, _string, G_REGEX_MATCH_PARTIAL, _expected)
+#define TEST_PARTIAL(_pattern, _string, _compile_opts, _expected) TEST_PARTIAL_FULL(_pattern, _string, _compile_opts, G_REGEX_MATCH_PARTIAL, _expected)
typedef struct {
const gchar *pattern;
const gchar *string;
+ GRegexCompileFlags compile_flags;
gint start_position;
gint sub_n;
const gchar *expected_sub;
@@ -567,7 +743,7 @@ test_sub_pattern (gconstpointer d)
gchar *sub_expr;
gint start = UNTOUCHED, end = UNTOUCHED;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, data->compile_flags, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -597,7 +773,14 @@ test_sub_pattern (gconstpointer d)
data->expected_sub = _expected_sub; \
data->expected_start = _expected_start; \
data->expected_end = _expected_end; \
- path = g_strdup_printf ("/regex/match/subpattern/%d", ++total); \
+ data->compile_flags = G_REGEX_DEFAULT; \
+ total++; \
+ path = g_strdup_printf ("/regex/match/subpattern/%d", total); \
+ g_test_add_data_func_full (path, data, test_sub_pattern, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestSubData)); \
+ data->compile_flags = G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/match/subpattern-optimized/%d", total); \
g_test_add_data_func_full (path, data, test_sub_pattern, g_free); \
g_free (path); \
}
@@ -622,7 +805,7 @@ test_named_sub_pattern (gconstpointer d)
gint start = UNTOUCHED, end = UNTOUCHED;
gchar *sub_expr;
- regex = g_regex_new (data->pattern, data->flags, 0, NULL);
+ regex = g_regex_new (data->pattern, data->flags, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -694,7 +877,7 @@ test_fetch_all (gconstpointer d)
gint match_count;
gint i;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -788,7 +971,8 @@ test_split_simple (gconstpointer d)
gint token_count;
gint i;
- tokens = g_regex_split_simple (data->pattern, data->string, 0, 0);
+ tokens = g_regex_split_simple (data->pattern, data->string,
+ G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
if (tokens)
token_count = g_strv_length (tokens);
else
@@ -867,7 +1051,7 @@ test_split_full (gconstpointer d)
gint token_count;
gint i;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -901,7 +1085,7 @@ test_split (gconstpointer d)
gint token_count;
gint i;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert (regex != NULL);
@@ -1057,8 +1241,8 @@ test_expand (gconstpointer d)
if (data->pattern)
{
- regex = g_regex_new (data->pattern, data->raw ? G_REGEX_RAW : 0, 0,
- &error);
+ regex = g_regex_new (data->pattern, data->raw ? G_REGEX_RAW : 0,
+ G_REGEX_MATCH_DEFAULT, &error);
g_assert_no_error (error);
g_regex_match (regex, data->string, 0, &match_info);
}
@@ -1091,6 +1275,8 @@ typedef struct {
gint start_position;
const gchar *replacement;
const gchar *expected;
+ GRegexCompileFlags compile_flags;
+ GRegexMatchFlags match_flags;
} TestReplaceData;
static void
@@ -1099,17 +1285,25 @@ test_replace (gconstpointer d)
const TestReplaceData *data = d;
GRegex *regex;
gchar *res;
+ GError *error = NULL;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
- res = g_regex_replace (regex, data->string, -1, data->start_position, data->replacement, 0, NULL);
+ regex = g_regex_new (data->pattern, data->compile_flags, G_REGEX_MATCH_DEFAULT, &error);
+ g_assert_no_error (error);
+
+ res = g_regex_replace (regex, data->string, -1, data->start_position,
+ data->replacement, data->match_flags, &error);
g_assert_cmpstr (res, ==, data->expected);
+ if (data->expected)
+ g_assert_no_error (error);
+
g_free (res);
g_regex_unref (regex);
+ g_clear_error (&error);
}
-#define TEST_REPLACE(_pattern, _string, _start_position, _replacement, _expected) { \
+#define TEST_REPLACE_OPTIONS(_pattern, _string, _start_position, _replacement, _expected, _compile_flags, _match_flags) { \
TestReplaceData *data; \
gchar *path; \
data = g_new0 (TestReplaceData, 1); \
@@ -1118,11 +1312,33 @@ test_replace (gconstpointer d)
data->start_position = _start_position; \
data->replacement = _replacement; \
data->expected = _expected; \
- path = g_strdup_printf ("/regex/replace/%d", ++total); \
+ data->compile_flags = _compile_flags; \
+ data->match_flags = _match_flags; \
+ total++; \
+ if (data->compile_flags & G_REGEX_OPTIMIZE) \
+ path = g_strdup_printf ("/regex/replace-optimized/%d", total); \
+ else \
+ path = g_strdup_printf ("/regex/replace/%d", total); \
+ g_test_add_data_func_full (path, data, test_replace, g_free); \
+ g_free (path); \
+ data = g_memdup2 (data, sizeof (TestReplaceData)); \
+ if (data->compile_flags & G_REGEX_OPTIMIZE) \
+ { \
+ data->compile_flags &= ~G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/replace/%d", total); \
+ } \
+ else \
+ { \
+ data->compile_flags |= G_REGEX_OPTIMIZE; \
+ path = g_strdup_printf ("/regex/replace-optimized/%d", total); \
+ } \
g_test_add_data_func_full (path, data, test_replace, g_free); \
g_free (path); \
}
+#define TEST_REPLACE(_pattern, _string, _start_position, _replacement, _expected) \
+ TEST_REPLACE_OPTIONS (_pattern, _string, _start_position, _replacement, _expected, 0, 0)
+
static void
test_replace_lit (gconstpointer d)
{
@@ -1130,7 +1346,7 @@ test_replace_lit (gconstpointer d)
GRegex *regex;
gchar *res;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
res = g_regex_replace_literal (regex, data->string, -1, data->start_position,
data->replacement, 0, NULL);
g_assert_cmpstr (res, ==, data->expected);
@@ -1166,7 +1382,7 @@ test_get_string_number (gconstpointer d)
GRegex *regex;
gint num;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
num = g_regex_get_string_number (regex, data->name);
g_assert_cmpint (num, ==, data->expected_num);
@@ -1260,7 +1476,7 @@ test_match_all_full (gconstpointer d)
gint match_count;
gint i;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
match_ok = g_regex_match_all_full (regex, data->string, data->string_len, data->start_position,
0, &match_info, NULL);
@@ -1305,7 +1521,7 @@ test_match_all (gconstpointer d)
gboolean match_ok;
guint i, match_count;
- regex = g_regex_new (data->pattern, 0, 0, NULL);
+ regex = g_regex_new (data->pattern, G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
match_ok = g_regex_match_all (regex, data->string, 0, &match_info);
if (g_slist_length (data->expected) == 0)
@@ -1502,7 +1718,7 @@ test_properties (void)
gchar *str;
error = NULL;
- regex = g_regex_new ("\\p{L}\\p{Ll}\\p{Lu}\\p{L&}\\p{N}\\p{Nd}", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("\\p{L}\\p{Ll}\\p{Lu}\\p{L&}\\p{N}\\p{Nd}", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
res = g_regex_match (regex, "ppPP01", 0, &match);
g_assert (res);
str = g_match_info_fetch (match, 0);
@@ -1523,7 +1739,7 @@ test_class (void)
gchar *str;
error = NULL;
- regex = g_regex_new ("[abc\\x{0B1E}\\p{Mn}\\x{0391}-\\x{03A9}]", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("[abc\\x{0B1E}\\p{Mn}\\x{0391}-\\x{03A9}]", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
res = g_regex_match (regex, "a:b:\340\254\236:\333\253:\316\240", 0, &match);
g_assert (res);
str = g_match_info_fetch (match, 0);
@@ -1553,6 +1769,12 @@ test_class (void)
res = g_match_info_next (match, NULL);
g_assert (!res);
+ /* Accessing match again should not crash */
+ g_test_expect_message ("GLib", G_LOG_LEVEL_CRITICAL,
+ "*match_info->pos >= 0*");
+ g_assert_false (g_match_info_next (match, NULL));
+ g_test_assert_expected_messages ();
+
g_match_info_free (match);
g_regex_unref (regex);
}
@@ -1569,7 +1791,7 @@ test_lookahead (void)
gint start, end;
error = NULL;
- regex = g_regex_new ("\\w+(?=;)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("\\w+(?=;)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "word1 word2: word3;", 0, &match);
@@ -1583,7 +1805,7 @@ test_lookahead (void)
g_regex_unref (regex);
error = NULL;
- regex = g_regex_new ("foo(?!bar)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("foo(?!bar)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "foobar foobaz", 0, &match);
@@ -1598,7 +1820,7 @@ test_lookahead (void)
g_regex_unref (regex);
error = NULL;
- regex = g_regex_new ("(?!bar)foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?!bar)foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "foobar foobaz", 0, &match);
@@ -1631,7 +1853,7 @@ test_lookbehind (void)
gint start, end;
error = NULL;
- regex = g_regex_new ("(?<!foo)bar", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<!foo)bar", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "foobar boobar", 0, &match);
@@ -1646,7 +1868,7 @@ test_lookbehind (void)
g_regex_unref (regex);
error = NULL;
- regex = g_regex_new ("(?<=bullock|donkey) poo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=bullock|donkey) poo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "don poo, and bullock poo", 0, &match);
@@ -1659,17 +1881,17 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<!dogs?|cats?) x", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<!dogs?|cats?) x", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex == NULL);
g_assert_error (error, G_REGEX_ERROR, G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND);
g_clear_error (&error);
- regex = g_regex_new ("(?<=ab(c|de)) foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=ab(c|de)) foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex == NULL);
g_assert_error (error, G_REGEX_ERROR, G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND);
g_clear_error (&error);
- regex = g_regex_new ("(?<=abc|abde)foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=abc|abde)foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abfoo, abdfoo, abcfoo", 0, &match);
@@ -1681,7 +1903,7 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^.*+(?<=abcd)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^.*+(?<=abcd)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abcabcabcabcabcabcabcabcabcd", 0, &match);
@@ -1690,7 +1912,7 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<=\\d{3})(?<!999)foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=\\d{3})(?<!999)foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "999foo 123abcfoo 123foo", 0, &match);
@@ -1702,7 +1924,7 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<=\\d{3}...)(?<!999)foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=\\d{3}...)(?<!999)foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "999foo 123abcfoo 123foo", 0, &match);
@@ -1714,7 +1936,7 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<=\\d{3}(?!999)...)foo", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=\\d{3}(?!999)...)foo", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "999foo 123abcfoo 123foo", 0, &match);
@@ -1726,7 +1948,7 @@ test_lookbehind (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<=(?<!foo)bar)baz", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?<=(?<!foo)bar)baz", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "foobarbaz barfoobaz barbarbaz", 0, &match);
@@ -1751,7 +1973,7 @@ test_subpattern (void)
gint start;
error = NULL;
- regex = g_regex_new ("cat(aract|erpillar|)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("cat(aract|erpillar|)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
g_assert_cmpint (g_regex_get_capture_count (regex), ==, 1);
@@ -1769,7 +1991,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("the ((red|white) (king|queen))", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("the ((red|white) (king|queen))", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
g_assert_cmpint (g_regex_get_capture_count (regex), ==, 3);
@@ -1793,7 +2015,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("the ((?:red|white) (king|queen))", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("the ((?:red|white) (king|queen))", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "the white queen", 0, &match);
@@ -1813,7 +2035,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?|(Sat)(ur)|(Sun))day (morning|afternoon)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?|(Sat)(ur)|(Sun))day (morning|afternoon)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
g_assert_cmpint (g_regex_get_capture_count (regex), ==, 3);
@@ -1833,7 +2055,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?|(abc)|(def))\\1", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?|(abc)|(def))\\1", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
g_assert_cmpint (g_regex_get_max_backref (regex), ==, 1);
@@ -1851,7 +2073,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?|(abc)|(def))(?1)", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("(?|(abc)|(def))(?1)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abcabc abcdef defabc defdef", 0, &match);
@@ -1868,7 +2090,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("(?<DN>Mon|Fri|Sun)(?:day)?|(?<DN>Tue)(?:sday)?|(?<DN>Wed)(?:nesday)?|(?<DN>Thu)(?:rsday)?|(?<DN>Sat)(?:urday)?", G_REGEX_OPTIMIZE|G_REGEX_DUPNAMES, 0, &error);
+ regex = g_regex_new ("(?<DN>Mon|Fri|Sun)(?:day)?|(?<DN>Tue)(?:sday)?|(?<DN>Wed)(?:nesday)?|(?<DN>Thu)(?:rsday)?|(?<DN>Sat)(?:urday)?", G_REGEX_OPTIMIZE|G_REGEX_DUPNAMES, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "Mon Tuesday Wed Saturday", 0, &match);
@@ -1895,7 +2117,7 @@ test_subpattern (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^(a|b\\1)+$", G_REGEX_OPTIMIZE|G_REGEX_DUPNAMES, 0, &error);
+ regex = g_regex_new ("^(a|b\\1)+$", G_REGEX_OPTIMIZE|G_REGEX_DUPNAMES, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "aaaaaaaaaaaaaaaa", 0, &match);
@@ -1919,7 +2141,7 @@ test_condition (void)
gboolean res;
error = NULL;
- regex = g_regex_new ("^(a+)(\\()?[^()]+(?(-1)\\))(b+)$", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^(a+)(\\()?[^()]+(?(-1)\\))(b+)$", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "a(zzzzzz)b", 0, &match);
@@ -1933,7 +2155,7 @@ test_condition (void)
g_regex_unref (regex);
error = NULL;
- regex = g_regex_new ("^(a+)(?<OPEN>\\()?[^()]+(?(<OPEN>)\\))(b+)$", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^(a+)(?<OPEN>\\()?[^()]+(?(<OPEN>)\\))(b+)$", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "a(zzzzzz)b", 0, &match);
@@ -1946,7 +2168,7 @@ test_condition (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^(a+)(?(+1)\\[|\\<)?[^()]+(\\])?(b+)$", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^(a+)(?(+1)\\[|\\<)?[^()]+(\\])?(b+)$", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "a[zzzzzz]b", 0, &match);
@@ -2013,7 +2235,7 @@ test_recursion (void)
gint start;
error = NULL;
- regex = g_regex_new ("\\( ( [^()]++ | (?R) )* \\)", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, 0, &error);
+ regex = g_regex_new ("\\( ( [^()]++ | (?R) )* \\)", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "(middle)", 0, &match);
@@ -2030,7 +2252,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^( \\( ( [^()]++ | (?1) )* \\) )$", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, 0, &error);
+ regex = g_regex_new ("^( \\( ( [^()]++ | (?1) )* \\) )$", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "((((((((((((((((middle))))))))))))))))", 0, &match);
@@ -2043,7 +2265,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^(?<pn> \\( ( [^()]++ | (?&pn) )* \\) )$", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, 0, &error);
+ regex = g_regex_new ("^(?<pn> \\( ( [^()]++ | (?&pn) )* \\) )$", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
g_regex_match (regex, "(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()", 0, &match);
@@ -2052,7 +2274,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("< (?: (?(R) \\d++ | [^<>]*+) | (?R)) * >", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, 0, &error);
+ regex = g_regex_new ("< (?: (?(R) \\d++ | [^<>]*+) | (?R)) * >", G_REGEX_OPTIMIZE|G_REGEX_EXTENDED, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "<ab<01<23<4>>>>", 0, &match);
@@ -2071,7 +2293,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^((.)(?1)\\2|.)$", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^((.)(?1)\\2|.)$", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abcdcba", 0, &match);
@@ -2084,7 +2306,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^(?:((.)(?1)\\2|)|((.)(?3)\\4|.))$", G_REGEX_OPTIMIZE, 0, &error);
+ regex = g_regex_new ("^(?:((.)(?1)\\2|)|((.)(?3)\\4|.))$", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abcdcba", 0, &match);
@@ -2097,7 +2319,7 @@ test_recursion (void)
g_match_info_free (match);
g_regex_unref (regex);
- regex = g_regex_new ("^\\W*+(?:((.)\\W*+(?1)\\W*+\\2|)|((.)\\W*+(?3)\\W*+\\4|\\W*+.\\W*+))\\W*+$", G_REGEX_OPTIMIZE|G_REGEX_CASELESS, 0, &error);
+ regex = g_regex_new ("^\\W*+(?:((.)\\W*+(?1)\\W*+\\2|)|((.)\\W*+(?3)\\W*+\\4|\\W*+.\\W*+))\\W*+$", G_REGEX_OPTIMIZE|G_REGEX_CASELESS, G_REGEX_MATCH_DEFAULT, &error);
g_assert (regex);
g_assert_no_error (error);
res = g_regex_match (regex, "abcdcba", 0, &match);
@@ -2124,7 +2346,7 @@ test_multiline (void)
g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=640489");
- regex = g_regex_new ("^a$", G_REGEX_MULTILINE|G_REGEX_DOTALL, 0, NULL);
+ regex = g_regex_new ("^a$", G_REGEX_MULTILINE|G_REGEX_DOTALL, G_REGEX_MATCH_DEFAULT, NULL);
count = 0;
g_regex_match (regex, "a\nb\na", 0, &info);
@@ -2144,7 +2366,7 @@ test_explicit_crlf (void)
{
GRegex *regex;
- regex = g_regex_new ("[\r\n]a", 0, 0, NULL);
+ regex = g_regex_new ("[\r\n]a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert_cmpint (g_regex_get_has_cr_or_lf (regex), ==, TRUE);
g_regex_unref (regex);
}
@@ -2154,35 +2376,141 @@ test_max_lookbehind (void)
{
GRegex *regex;
- regex = g_regex_new ("abc", 0, 0, NULL);
+ regex = g_regex_new ("abc", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert_cmpint (g_regex_get_max_lookbehind (regex), ==, 0);
g_regex_unref (regex);
- regex = g_regex_new ("\\babc", 0, 0, NULL);
+ regex = g_regex_new ("\\babc", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert_cmpint (g_regex_get_max_lookbehind (regex), ==, 1);
g_regex_unref (regex);
- regex = g_regex_new ("(?<=123)abc", 0, 0, NULL);
+ regex = g_regex_new ("(?<=123)abc", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, NULL);
g_assert_cmpint (g_regex_get_max_lookbehind (regex), ==, 3);
g_regex_unref (regex);
}
static gboolean
-pcre_ge (guint64 major, guint64 minor)
+pcre2_ge (guint64 major, guint64 minor)
{
- const char *version;
- gchar *ptr;
- guint64 pcre_major, pcre_minor;
+ gchar version[32];
+ const gchar *ptr;
+ guint64 pcre2_major, pcre2_minor;
- /* e.g. 8.35 2014-04-04 */
- version = pcre_version ();
+ /* e.g. 10.36 2020-12-04 */
+ pcre2_config (PCRE2_CONFIG_VERSION, version);
- pcre_major = g_ascii_strtoull (version, &ptr, 10);
+ pcre2_major = g_ascii_strtoull (version, (gchar **) &ptr, 10);
/* ptr points to ".MINOR (release date)" */
g_assert (ptr[0] == '.');
- pcre_minor = g_ascii_strtoull (ptr + 1, NULL, 10);
+ pcre2_minor = g_ascii_strtoull (ptr + 1, NULL, 10);
+
+ return (pcre2_major > major) || (pcre2_major == major && pcre2_minor >= minor);
+}
+
+static void
+test_compile_errors (void)
+{
+ GRegex *regex;
+ GError *error = NULL;
+
+ regex = g_regex_new ("\\o{999}", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT, &error);
+ g_assert_null (regex);
+ g_assert_error (error, G_REGEX_ERROR, G_REGEX_ERROR_COMPILE);
+ g_clear_error (&error);
+}
+
+static void
+test_jit_unsupported_matching_options (void)
+{
+ GRegex *regex;
+ GMatchInfo *info;
+ gchar *substring;
+
+ regex = g_regex_new ("(\\w+)#(\\w+)", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT, NULL);
+
+ g_assert_true (g_regex_match (regex, "aa#bb cc#dd", G_REGEX_MATCH_DEFAULT, &info));
+ g_assert_cmpint (g_match_info_get_match_count (info), ==, 3);
+ substring = g_match_info_fetch (info, 1);
+ g_assert_cmpstr (substring, ==, "aa");
+ g_clear_pointer (&substring, g_free);
+ substring = g_match_info_fetch (info, 2);
+ g_assert_cmpstr (substring, ==, "bb");
+ g_clear_pointer (&substring, g_free);
+ g_assert_true (g_match_info_next (info, NULL));
+ g_assert_cmpint (g_match_info_get_match_count (info), ==, 3);
+ substring = g_match_info_fetch (info, 1);
+ g_assert_cmpstr (substring, ==, "cc");
+ g_clear_pointer (&substring, g_free);
+ substring = g_match_info_fetch (info, 2);
+ g_assert_cmpstr (substring, ==, "dd");
+ g_clear_pointer (&substring, g_free);
+ g_assert_false (g_match_info_next (info, NULL));
+ g_match_info_free (info);
- return (pcre_major > major) || (pcre_major == major && pcre_minor >= minor);
+ g_assert_true (g_regex_match (regex, "aa#bb cc#dd", G_REGEX_MATCH_ANCHORED, &info));
+ g_assert_cmpint (g_match_info_get_match_count (info), ==, 3);
+ substring = g_match_info_fetch (info, 1);
+ g_assert_cmpstr (substring, ==, "aa");
+ g_clear_pointer (&substring, g_free);
+ substring = g_match_info_fetch (info, 2);
+ g_assert_cmpstr (substring, ==, "bb");
+ g_clear_pointer (&substring, g_free);
+ g_assert_false (g_match_info_next (info, NULL));
+ g_match_info_free (info);
+
+ g_assert_true (g_regex_match (regex, "aa#bb cc#dd", G_REGEX_MATCH_DEFAULT, &info));
+ g_assert_cmpint (g_match_info_get_match_count (info), ==, 3);
+ substring = g_match_info_fetch (info, 1);
+ g_assert_cmpstr (substring, ==, "aa");
+ g_clear_pointer (&substring, g_free);
+ substring = g_match_info_fetch (info, 2);
+ g_assert_cmpstr (substring, ==, "bb");
+ g_clear_pointer (&substring, g_free);
+ g_assert_true (g_match_info_next (info, NULL));
+ g_assert_cmpint (g_match_info_get_match_count (info), ==, 3);
+ substring = g_match_info_fetch (info, 1);
+ g_assert_cmpstr (substring, ==, "cc");
+ g_clear_pointer (&substring, g_free);
+ substring = g_match_info_fetch (info, 2);
+ g_assert_cmpstr (substring, ==, "dd");
+ g_clear_pointer (&substring, g_free);
+ g_assert_false (g_match_info_next (info, NULL));
+ g_match_info_free (info);
+
+ g_regex_unref (regex);
+}
+
+static void
+test_unmatched_named_subpattern (void)
+{
+ GRegex *regex = NULL;
+ GMatchInfo *match_info = NULL;
+ const char *string = "Test";
+
+ g_test_summary ("Test that unmatched subpatterns can still be queried");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2881");
+
+ regex = g_regex_new ("((?<Key>[^\\s\"'\\=]+)|\"(?<Key>[^\"]*)\"|'(?<Key>[^']*)')"
+ "(?:\\=((?<Value>[^\\s\"']+)|\"(?<Value>[^\"]*)\"|'(?<Value>[^']*)'))?",
+ G_REGEX_DUPNAMES, 0, NULL);
+
+ g_assert_true (g_regex_match (regex, string, 0, &match_info));
+
+ while (g_match_info_matches (match_info))
+ {
+ char *key = g_match_info_fetch_named (match_info, "Key");
+ char *value = g_match_info_fetch_named (match_info, "Value");
+
+ g_assert_cmpstr (key, ==, "Test");
+ g_assert_cmpstr (value, ==, "");
+
+ g_free (key);
+ g_free (value);
+ g_match_info_next (match_info, NULL);
+ }
+
+ g_match_info_unref (match_info);
+ g_regex_unref (regex);
}
int
@@ -2202,33 +2530,41 @@ main (int argc, char *argv[])
g_test_add_func ("/regex/multiline", test_multiline);
g_test_add_func ("/regex/explicit-crlf", test_explicit_crlf);
g_test_add_func ("/regex/max-lookbehind", test_max_lookbehind);
+ g_test_add_func ("/regex/compile-errors", test_compile_errors);
+ g_test_add_func ("/regex/jit-unsupported-matching", test_jit_unsupported_matching_options);
+ g_test_add_func ("/regex/unmatched-named-subpattern", test_unmatched_named_subpattern);
/* TEST_NEW(pattern, compile_opts, match_opts) */
TEST_NEW("[A-Z]+", G_REGEX_CASELESS | G_REGEX_EXTENDED | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTBOL | G_REGEX_MATCH_PARTIAL);
- TEST_NEW("", 0, 0);
- TEST_NEW(".*", 0, 0);
- TEST_NEW(".*", G_REGEX_OPTIMIZE, 0);
- TEST_NEW(".*", G_REGEX_MULTILINE, 0);
- TEST_NEW(".*", G_REGEX_DOTALL, 0);
+ TEST_NEW("", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW(".*", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW(".*", G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW(".*", G_REGEX_MULTILINE, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW(".*", G_REGEX_DOTALL, G_REGEX_MATCH_DEFAULT);
TEST_NEW(".*", G_REGEX_DOTALL, G_REGEX_MATCH_NOTBOL);
- TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", 0, 0);
- TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", G_REGEX_CASELESS, 0);
- TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0);
- TEST_NEW("(?P<A>x)|(?P<A>y)", G_REGEX_DUPNAMES, 0);
- TEST_NEW("(?P<A>x)|(?P<A>y)", G_REGEX_DUPNAMES | G_REGEX_OPTIMIZE, 0);
+ TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", G_REGEX_CASELESS, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW("(123\\d*)[a-zA-Z]+(?P<hello>.*)", G_REGEX_CASELESS | G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW("(?P<A>x)|(?P<A>y)", G_REGEX_DUPNAMES, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW("(?P<A>x)|(?P<A>y)", G_REGEX_DUPNAMES | G_REGEX_OPTIMIZE, G_REGEX_MATCH_DEFAULT);
/* This gives "internal error: code overflow" with pcre 6.0 */
- TEST_NEW("(?i)(?-i)", 0, 0);
- TEST_NEW ("(?i)a", 0, 0);
- TEST_NEW ("(?m)a", 0, 0);
- TEST_NEW ("(?s)a", 0, 0);
- TEST_NEW ("(?x)a", 0, 0);
- TEST_NEW ("(?J)a", 0, 0);
- TEST_NEW ("(?U)[a-z]+", 0, 0);
+ TEST_NEW("(?i)(?-i)", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?i)a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?m)a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?s)a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?x)a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?J)a", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
+ TEST_NEW ("(?U)[a-z]+", G_REGEX_DEFAULT, G_REGEX_MATCH_DEFAULT);
/* TEST_NEW_CHECK_FLAGS(pattern, compile_opts, match_ops, real_compile_opts, real_match_opts) */
TEST_NEW_CHECK_FLAGS ("a", G_REGEX_OPTIMIZE, 0, G_REGEX_OPTIMIZE, 0);
+ TEST_NEW_CHECK_FLAGS ("a", G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY,
+ G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY);
+ TEST_NEW_CHECK_FLAGS ("a", 0, G_REGEX_MATCH_NEWLINE_ANYCRLF | G_REGEX_MATCH_BSR_ANYCRLF,
+ G_REGEX_NEWLINE_ANYCRLF | G_REGEX_BSR_ANYCRLF,
+ G_REGEX_MATCH_NEWLINE_ANYCRLF | G_REGEX_MATCH_BSR_ANYCRLF);
TEST_NEW_CHECK_FLAGS ("a", G_REGEX_RAW, 0, G_REGEX_RAW, 0);
- TEST_NEW_CHECK_FLAGS ("(?X)a", 0, 0, 0 /* not exposed by GRegex */, 0);
+ TEST_NEW_CHECK_FLAGS ("(?J)a", 0, 0, G_REGEX_DUPNAMES, 0);
TEST_NEW_CHECK_FLAGS ("^.*", 0, 0, G_REGEX_ANCHORED, 0);
TEST_NEW_CHECK_FLAGS ("(*UTF8)a", 0, 0, 0 /* this is the default in GRegex */, 0);
TEST_NEW_CHECK_FLAGS ("(*UCP)a", 0, 0, 0 /* this always on in GRegex */, 0);
@@ -2240,6 +2576,10 @@ main (int argc, char *argv[])
TEST_NEW_CHECK_FLAGS ("(*BSR_ANYCRLF)a", 0, 0, G_REGEX_BSR_ANYCRLF, 0);
TEST_NEW_CHECK_FLAGS ("(*BSR_UNICODE)a", 0, 0, 0 /* this is the default in GRegex */, 0);
TEST_NEW_CHECK_FLAGS ("(*NO_START_OPT)a", 0, 0, 0 /* not exposed in GRegex */, 0);
+ /* Make sure we ignore deprecated G_REGEX_JAVASCRIPT_COMPAT */
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ TEST_NEW_CHECK_FLAGS ("a", G_REGEX_JAVASCRIPT_COMPAT, 0, 0, 0);
+G_GNUC_END_IGNORE_DEPRECATIONS
/* TEST_NEW_FAIL(pattern, compile_opts, expected_error) */
TEST_NEW_FAIL("(", 0, G_REGEX_ERROR_UNMATCHED_PARENTHESIS);
@@ -2256,16 +2596,17 @@ main (int argc, char *argv[])
TEST_NEW_FAIL ("a{4,2}", 0, G_REGEX_ERROR_QUANTIFIERS_OUT_OF_ORDER);
TEST_NEW_FAIL ("a{999999,}", 0, G_REGEX_ERROR_QUANTIFIER_TOO_BIG);
TEST_NEW_FAIL ("[a-z", 0, G_REGEX_ERROR_UNTERMINATED_CHARACTER_CLASS);
- TEST_NEW_FAIL ("(?X)[\\B]", 0, G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS);
+ TEST_NEW_FAIL ("[\\B]", 0, G_REGEX_ERROR_INVALID_ESCAPE_IN_CHARACTER_CLASS);
TEST_NEW_FAIL ("[z-a]", 0, G_REGEX_ERROR_RANGE_OUT_OF_ORDER);
+ TEST_NEW_FAIL ("^[[:alnum:]-_.]+$", 0, G_REGEX_ERROR_COMPILE);
TEST_NEW_FAIL ("{2,4}", 0, G_REGEX_ERROR_NOTHING_TO_REPEAT);
TEST_NEW_FAIL ("a(?u)", 0, G_REGEX_ERROR_UNRECOGNIZED_CHARACTER);
- TEST_NEW_FAIL ("a(?<$foo)bar", 0, G_REGEX_ERROR_UNRECOGNIZED_CHARACTER);
+ TEST_NEW_FAIL ("a(?<$foo)bar", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME);
TEST_NEW_FAIL ("a[:alpha:]b", 0, G_REGEX_ERROR_POSIX_NAMED_CLASS_OUTSIDE_CLASS);
TEST_NEW_FAIL ("a(b", 0, G_REGEX_ERROR_UNMATCHED_PARENTHESIS);
TEST_NEW_FAIL ("a)b", 0, G_REGEX_ERROR_UNMATCHED_PARENTHESIS);
TEST_NEW_FAIL ("a(?R", 0, G_REGEX_ERROR_UNMATCHED_PARENTHESIS);
- TEST_NEW_FAIL ("a(?-54", 0, G_REGEX_ERROR_UNMATCHED_PARENTHESIS);
+ TEST_NEW_FAIL ("a(?-54", 0, G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE);
TEST_NEW_FAIL ("(ab\\2)", 0, G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE);
TEST_NEW_FAIL ("a(?#abc", 0, G_REGEX_ERROR_UNTERMINATED_COMMENT);
TEST_NEW_FAIL ("(?<=a+)b", 0, G_REGEX_ERROR_VARIABLE_LENGTH_LOOKBEHIND);
@@ -2275,51 +2616,41 @@ main (int argc, char *argv[])
TEST_NEW_FAIL ("a[[:fubar:]]b", 0, G_REGEX_ERROR_UNKNOWN_POSIX_CLASS_NAME);
TEST_NEW_FAIL ("[[.ch.]]", 0, G_REGEX_ERROR_POSIX_COLLATING_ELEMENTS_NOT_SUPPORTED);
TEST_NEW_FAIL ("\\x{110000}", 0, G_REGEX_ERROR_HEX_CODE_TOO_LARGE);
- TEST_NEW_FAIL ("^(?(0)f|b)oo", 0, G_REGEX_ERROR_INVALID_CONDITION);
+ TEST_NEW_FAIL ("^(?(0)f|b)oo", 0, G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE);
TEST_NEW_FAIL ("(?<=\\C)X", 0, G_REGEX_ERROR_SINGLE_BYTE_MATCH_IN_LOOKBEHIND);
- TEST_NEW_FAIL ("(?!\\w)(?R)", 0, G_REGEX_ERROR_INFINITE_LOOP);
- if (pcre_ge (8, 37))
- {
- /* The expected errors changed here. */
- TEST_NEW_FAIL ("(?(?<ab))", 0, G_REGEX_ERROR_ASSERTION_EXPECTED);
- }
- else
- {
- TEST_NEW_FAIL ("(?(?<ab))", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR);
- }
-
- if (pcre_ge (8, 35))
- {
- /* The expected errors changed here. */
- TEST_NEW_FAIL ("(?P<sub>foo)\\g<sub", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR);
- }
- else
- {
- TEST_NEW_FAIL ("(?P<sub>foo)\\g<sub", 0, G_REGEX_ERROR_MISSING_BACK_REFERENCE);
- }
+ TEST_NEW ("(?!\\w)(?R)", 0, 0);
+ TEST_NEW_FAIL ("(?(?<ab))", 0, G_REGEX_ERROR_ASSERTION_EXPECTED);
+ TEST_NEW_FAIL ("(?P<sub>foo)\\g<sub", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME_TERMINATOR);
TEST_NEW_FAIL ("(?P<x>eks)(?P<x>eccs)", 0, G_REGEX_ERROR_DUPLICATE_SUBPATTERN_NAME);
-#if 0
- TEST_NEW_FAIL (?, 0, G_REGEX_ERROR_MALFORMED_PROPERTY);
- TEST_NEW_FAIL (?, 0, G_REGEX_ERROR_UNKNOWN_PROPERTY);
-#endif
TEST_NEW_FAIL ("\\666", G_REGEX_RAW, G_REGEX_ERROR_INVALID_OCTAL_VALUE);
TEST_NEW_FAIL ("^(?(DEFINE) abc | xyz ) ", 0, G_REGEX_ERROR_TOO_MANY_BRANCHES_IN_DEFINE);
TEST_NEW_FAIL ("a", G_REGEX_NEWLINE_CRLF | G_REGEX_NEWLINE_ANYCRLF, G_REGEX_ERROR_INCONSISTENT_NEWLINE_OPTIONS);
TEST_NEW_FAIL ("^(a)\\g{3", 0, G_REGEX_ERROR_MISSING_BACK_REFERENCE);
- TEST_NEW_FAIL ("^(a)\\g{0}", 0, G_REGEX_ERROR_INVALID_RELATIVE_REFERENCE);
- TEST_NEW_FAIL ("abc(*FAIL:123)xyz", 0, G_REGEX_ERROR_BACKTRACKING_CONTROL_VERB_ARGUMENT_FORBIDDEN);
+ TEST_NEW_FAIL ("^(a)\\g{0}", 0, G_REGEX_ERROR_INEXISTENT_SUBPATTERN_REFERENCE);
+ TEST_NEW ("abc(*FAIL:123)xyz", 0, 0);
TEST_NEW_FAIL ("a(*FOOBAR)b", 0, G_REGEX_ERROR_UNKNOWN_BACKTRACKING_CONTROL_VERB);
- TEST_NEW_FAIL ("(?i:A{1,}\\6666666666)", 0, G_REGEX_ERROR_NUMBER_TOO_BIG);
+ if (pcre2_ge (10, 37))
+ {
+ TEST_NEW ("(?i:A{1,}\\6666666666)", 0, 0);
+ }
TEST_NEW_FAIL ("(?<a>)(?&)", 0, G_REGEX_ERROR_MISSING_SUBPATTERN_NAME);
- TEST_NEW_FAIL ("(?+-a)", 0, G_REGEX_ERROR_MISSING_DIGIT);
- TEST_NEW_FAIL ("TA]", G_REGEX_JAVASCRIPT_COMPAT, G_REGEX_ERROR_INVALID_DATA_CHARACTER);
+ TEST_NEW_FAIL ("(?+-a)", 0, G_REGEX_ERROR_INVALID_RELATIVE_REFERENCE);
TEST_NEW_FAIL ("(?|(?<a>A)|(?<b>B))", 0, G_REGEX_ERROR_EXTRA_SUBPATTERN_NAME);
TEST_NEW_FAIL ("a(*MARK)b", 0, G_REGEX_ERROR_BACKTRACKING_CONTROL_VERB_ARGUMENT_REQUIRED);
TEST_NEW_FAIL ("^\\c€", 0, G_REGEX_ERROR_INVALID_CONTROL_CHAR);
TEST_NEW_FAIL ("\\k", 0, G_REGEX_ERROR_MISSING_NAME);
TEST_NEW_FAIL ("a[\\NB]c", 0, G_REGEX_ERROR_NOT_SUPPORTED_IN_CLASS);
TEST_NEW_FAIL ("(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFG)XX", 0, G_REGEX_ERROR_NAME_TOO_LONG);
- TEST_NEW_FAIL ("\\u0100", G_REGEX_RAW | G_REGEX_JAVASCRIPT_COMPAT, G_REGEX_ERROR_CHARACTER_VALUE_TOO_LARGE);
+ /* See https://gitlab.gnome.org/GNOME/gtksourceview/-/issues/278 */
+ TEST_NEW_FAIL ("(?i-x)((?:(?i-x)[^\\x00\\t\\n\\f\\r \"'/<=>\\x{007F}-\\x{009F}" \
+ "\\x{FDD0}-\\x{FDEF}\\x{FFFE}\\x{FFFF}\\x{1FFFE}\\x{1FFFF}" \
+ "\\x{2FFFE}\\x{2FFFF}\\x{3FFFE}\\x{3FFFF}\\x{4FFFE}\\x{4FFFF}" \
+ "\\x{5FFFE}\\x{5FFFF}\\x{6FFFE}\\x{6FFFF}\\x{7FFFE}\\x{7FFFF}" \
+ "\\x{8FFFE}\\x{8FFFF}\\x{9FFFE}\\x{9FFFF}\\x{AFFFE}\\x{AFFFF}" \
+ "\\x{BFFFE}\\x{BFFFF}\\x{CFFFE}\\x{CFFFF}\\x{DFFFE}\\x{DFFFF}" \
+ "\\x{EFFFE}\\x{EFFFF}\\x{FFFFE}\\x{FFFFF}\\x{10FFFE}\\x{10FFFF}]+)" \
+ "\\s*=\\s*)(\\\")",
+ G_REGEX_RAW, G_REGEX_ERROR_HEX_CODE_TOO_LARGE);
/* These errors can't really be tested easily:
* G_REGEX_ERROR_EXPRESSION_TOO_LARGE
@@ -2343,6 +2674,8 @@ main (int argc, char *argv[])
TEST_MATCH_SIMPLE("a", "ab", 0, G_REGEX_MATCH_ANCHORED, TRUE);
TEST_MATCH_SIMPLE("a", "a", G_REGEX_CASELESS, 0, TRUE);
TEST_MATCH_SIMPLE("a", "A", G_REGEX_CASELESS, 0, TRUE);
+ TEST_MATCH_SIMPLE("\\C\\C", "ab", G_REGEX_OPTIMIZE | G_REGEX_RAW, 0, TRUE);
+ TEST_MATCH_SIMPLE("^[[:alnum:]\\-_.]+$", "admin-foo", 0, 0, TRUE);
/* These are needed to test extended properties. */
TEST_MATCH_SIMPLE(AGRAVE, AGRAVE, G_REGEX_CASELESS, 0, TRUE);
TEST_MATCH_SIMPLE(AGRAVE, AGRAVE_UPPER, G_REGEX_CASELESS, 0, TRUE);
@@ -2454,6 +2787,8 @@ main (int argc, char *argv[])
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CR, 0, "a\rb\rc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_LF, 0, "a\rb\rc", -1, 0, 0, FALSE);
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, 0, "a\rb\rc", -1, 0, 0, FALSE);
+ TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_ANYCRLF, 0, "a\r\nb\nc", -1, 0, 0, TRUE);
+ TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_ANYCRLF, 0, "a\r\nb\rc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CR, "a\nb\nc", -1, 0, 0, FALSE);
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_LF, "a\nb\nc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CRLF, "a\nb\nc", -1, 0, 0, FALSE);
@@ -2463,6 +2798,8 @@ main (int argc, char *argv[])
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CR, "a\rb\rc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_LF, "a\rb\rc", -1, 0, 0, FALSE);
TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CRLF, "a\rb\rc", -1, 0, 0, FALSE);
+ TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANYCRLF, "a\r\nb\rc", -1, 0, 0, TRUE);
+ TEST_MATCH("^b$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANYCRLF, "a\r\nb\nc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CR, G_REGEX_MATCH_NEWLINE_ANY, "a\nb\nc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CR, G_REGEX_MATCH_NEWLINE_ANY, "a\rb\rc", -1, 0, 0, TRUE);
@@ -2472,10 +2809,25 @@ main (int argc, char *argv[])
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CR, G_REGEX_MATCH_NEWLINE_CRLF, "a\r\nb\r\nc", -1, 0, 0, TRUE);
TEST_MATCH("^b$", G_REGEX_MULTILINE | G_REGEX_NEWLINE_CR, G_REGEX_MATCH_NEWLINE_CRLF, "a\rb\rc", -1, 0, 0, FALSE);
+ /* See https://gitlab.gnome.org/GNOME/glib/-/issues/2729#note_1544130 */
+ TEST_MATCH("^a$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANY, "a", -1, 0, 0, TRUE);
+ TEST_MATCH("^a$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_LF, "a", -1, 0, 0, TRUE);
+ TEST_MATCH("^a$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CR, "a", -1, 0, 0, TRUE);
+ TEST_MATCH("^a$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_CRLF, "a", -1, 0, 0, TRUE);
+ TEST_MATCH("^a$", G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANYCRLF, "a", -1, 0, 0, TRUE);
+
TEST_MATCH("a#\nb", G_REGEX_EXTENDED, 0, "a", -1, 0, 0, FALSE);
TEST_MATCH("a#\r\nb", G_REGEX_EXTENDED, 0, "a", -1, 0, 0, FALSE);
TEST_MATCH("a#\rb", G_REGEX_EXTENDED, 0, "a", -1, 0, 0, FALSE);
- TEST_MATCH("a#\nb", G_REGEX_EXTENDED, G_REGEX_MATCH_NEWLINE_CR, "a", -1, 0, 0, FALSE);
+ /* Due to PCRE2 only supporting newline settings passed to pcre2_compile (and
+ * not to pcre2_match also), we have to compile the pattern with the
+ * effective (combined from compile and match options) newline setting.
+ * However, this setting also affects how newlines are interpreted *inside*
+ * the pattern. With G_REGEX_EXTENDED, this changes where the comment
+ * (started with `#`) ends.
+ */
+ /* On PCRE1, this test expected no match; on PCRE2 it matches because of the above. */
+ TEST_MATCH("a#\nb", G_REGEX_EXTENDED, G_REGEX_MATCH_NEWLINE_CR, "a", -1, 0, 0, TRUE /*FALSE*/);
TEST_MATCH("a#\nb", G_REGEX_EXTENDED | G_REGEX_NEWLINE_CR, 0, "a", -1, 0, 0, TRUE);
TEST_MATCH("line\nbreak", G_REGEX_MULTILINE, 0, "this is a line\nbreak", -1, 0, 0, TRUE);
@@ -2488,21 +2840,23 @@ main (int argc, char *argv[])
* with pcre's internal tables. Bug #678273 */
TEST_MATCH("[DŽ]", G_REGEX_CASELESS, 0, "DŽ", -1, 0, 0, TRUE);
TEST_MATCH("[DŽ]", G_REGEX_CASELESS, 0, "dž", -1, 0, 0, TRUE);
-#if PCRE_MAJOR > 8 || (PCRE_MAJOR == 8 && PCRE_MINOR >= 32)
- /* This would incorrectly fail to match in pcre < 8.32, so only assert
- * this for known-good pcre. */
TEST_MATCH("[DŽ]", G_REGEX_CASELESS, 0, "Dž", -1, 0, 0, TRUE);
-#endif
+
+ /* see https://gitlab.gnome.org/GNOME/glib/-/issues/2700 */
+ TEST_MATCH("(\n.+)+", G_REGEX_DEFAULT, 0, "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n", -1, 0, 0, TRUE);
+ TEST_MATCH("\n([\\-\\.a-zA-Z]+[\\-\\.0-9]*) +connected ([^(\n ]*)[^\n]*((\n +[0-9]+x[0-9]+[^\n]+)+)", G_REGEX_DEFAULT, 0, "Screen 0: minimum 1 x 1, current 3840 x 1080, maximum 8192 x 8192\nVirtual1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 0mm x 0mm\n 1920x1080 60.00*+ 59.96 \n 3840x2400 59.97 \n 3840x2160 59.97 \n 2880x1800 59.95 \n 2560x1600 59.99 \n 2560x1440 59.95 \n 1920x1440 60.00 \n 1856x1392 60.00 \n 1792x1344 60.00 \n 1920x1200 59.88 \n 1600x1200 60.00 \n 1680x1050 59.95 \n 1400x1050 59.98 \n 1280x1024 60.02 \n 1440x900 59.89 \n 1280x960 60.00 \n 1360x768 60.02 \n 1280x800 59.81 \n 1152x864 75.00 \n 1280x768 59.87 \n 1280x720 59.86 \n 1024x768 60.00 \n 800x600 60.32 \n 640x480 59.94 \nVirtual2 connected 1920x1080+1920+0 (normal left inverted right x axis y axis) 0mm x 0mm\n 1920x1080 60.00*+ 59.96 \n 3840x2400 59.97 \n 3840x2160 59.97 \n 2880x1800 59.95 \n 2560x1600 59.99 \n 2560x1440 59.95 \n 1920x1440 60.00 \n 1856x1392 60.00 \n 1792x1344 60.00 \n 1920x1200 59.88 \n 1600x1200 60.00 \n 1680x1050 59.95 \n 1400x1050 59.98 \n 1280x1024 60.02 \n 1440x900 59.89 \n 1280x960 60.00 \n 1360x768 60.02 \n 1280x800 59.81 \n 1152x864 75.00 \n 1280x768 59.87 \n 1280x720 59.86 \n 1024x768 60.00 \n 800x600 60.32 \n 640x480 59.94 \nVirtual3 disconnected (normal left inverted right x axis y axis)\nVirtual4 disconnected (normal left inverted right x axis y axis)\nVirtual5 disconnected (normal left inverted right x axis y axis)\nVirtual6 disconnected (normal left inverted right x axis y axis)\nVirtual7 disconnected (normal left inverted right x axis y axis)\nVirtual8 disconnected (normal left inverted right x axis y axis)\n", -1, 0, 0, TRUE);
/* TEST_MATCH_NEXT#(pattern, string, string_len, start_position, ...) */
TEST_MATCH_NEXT0("a", "x", -1, 0);
TEST_MATCH_NEXT0("a", "ax", -1, 1);
TEST_MATCH_NEXT0("a", "xa", 1, 0);
TEST_MATCH_NEXT0("a", "axa", 1, 2);
+ TEST_MATCH_NEXT1("", "", -1, 0, "", 0, 0);
TEST_MATCH_NEXT1("a", "a", -1, 0, "a", 0, 1);
TEST_MATCH_NEXT1("a", "xax", -1, 0, "a", 1, 2);
TEST_MATCH_NEXT1(EURO, ENG EURO, -1, 0, EURO, 2, 5);
TEST_MATCH_NEXT1("a*", "", -1, 0, "", 0, 0);
+ TEST_MATCH_NEXT2("", "a", -1, 0, "", 0, 0, "", 1, 1);
TEST_MATCH_NEXT2("a*", "aa", -1, 0, "aa", 0, 2, "", 2, 2);
TEST_MATCH_NEXT2(EURO "*", EURO EURO, -1, 0, EURO EURO, 0, 6, "", 6, 6);
TEST_MATCH_NEXT2("a", "axa", -1, 0, "a", 0, 1, "a", 2, 3);
@@ -2530,18 +2884,35 @@ main (int argc, char *argv[])
TEST_MATCH_COUNT("(a)?(b)", "b", 0, 0, 3);
TEST_MATCH_COUNT("(a)?(b)", "ab", 0, 0, 3);
- /* TEST_PARTIAL(pattern, string, expected) */
- TEST_PARTIAL("^ab", "a", TRUE);
- TEST_PARTIAL("^ab", "xa", FALSE);
- TEST_PARTIAL("ab", "xa", TRUE);
- TEST_PARTIAL("ab", "ab", FALSE); /* normal match. */
- TEST_PARTIAL("a+b", "aa", TRUE);
- TEST_PARTIAL("(a)+b", "aa", TRUE);
- TEST_PARTIAL("a?b", "a", TRUE);
-
- /* Test soft vs. hard partial matching */
- TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_MATCH_PARTIAL_SOFT, FALSE);
- TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_MATCH_PARTIAL_HARD, TRUE);
+ /* TEST_PARTIAL(pattern, string, expected), no JIT */
+ TEST_PARTIAL("^ab", "a", G_REGEX_DEFAULT, TRUE);
+ TEST_PARTIAL("^ab", "xa", G_REGEX_DEFAULT, FALSE);
+ TEST_PARTIAL("ab", "xa", G_REGEX_DEFAULT, TRUE);
+ TEST_PARTIAL("ab", "ab", G_REGEX_DEFAULT, FALSE); /* normal match. */
+ TEST_PARTIAL("a+b", "aa", G_REGEX_DEFAULT, TRUE);
+ TEST_PARTIAL("(a)+b", "aa", G_REGEX_DEFAULT, TRUE);
+ TEST_PARTIAL("a?b", "a", G_REGEX_DEFAULT, TRUE);
+
+ /* TEST_PARTIAL(pattern, string, expected) with JIT */
+ TEST_PARTIAL("^ab", "a", G_REGEX_OPTIMIZE, TRUE);
+ TEST_PARTIAL("^ab", "xa", G_REGEX_OPTIMIZE, FALSE);
+ TEST_PARTIAL("ab", "xa", G_REGEX_OPTIMIZE, TRUE);
+ TEST_PARTIAL("ab", "ab", G_REGEX_OPTIMIZE, FALSE); /* normal match. */
+ TEST_PARTIAL("a+b", "aa", G_REGEX_OPTIMIZE, TRUE);
+ TEST_PARTIAL("(a)+b", "aa", G_REGEX_OPTIMIZE, TRUE);
+ TEST_PARTIAL("a?b", "a", G_REGEX_OPTIMIZE, TRUE);
+
+ /* Test soft vs. hard partial matching, no JIT */
+ TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_DEFAULT, G_REGEX_MATCH_PARTIAL_SOFT, FALSE);
+ TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_DEFAULT, G_REGEX_MATCH_PARTIAL_HARD, TRUE);
+ TEST_PARTIAL_FULL("ab+", "ab", G_REGEX_DEFAULT, G_REGEX_MATCH_PARTIAL_SOFT, FALSE);
+ TEST_PARTIAL_FULL("ab+", "ab", G_REGEX_DEFAULT, G_REGEX_MATCH_PARTIAL_HARD, TRUE);
+
+ /* Test soft vs. hard partial matching with JIT */
+ TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_OPTIMIZE, G_REGEX_MATCH_PARTIAL_SOFT, FALSE);
+ TEST_PARTIAL_FULL("cat(fish)?", "cat", G_REGEX_OPTIMIZE, G_REGEX_MATCH_PARTIAL_HARD, TRUE);
+ TEST_PARTIAL_FULL("ab+", "ab", G_REGEX_OPTIMIZE, G_REGEX_MATCH_PARTIAL_SOFT, FALSE);
+ TEST_PARTIAL_FULL("ab+", "ab", G_REGEX_OPTIMIZE, G_REGEX_MATCH_PARTIAL_HARD, TRUE);
/* TEST_SUB_PATTERN(pattern, string, start_position, sub_n, expected_sub,
* expected_start, expected_end) */
@@ -2676,11 +3047,6 @@ main (int argc, char *argv[])
TEST_EXPAND("a", "a", "\\0130", FALSE, "X");
TEST_EXPAND("a", "a", "\\\\\\0", FALSE, "\\a");
TEST_EXPAND("a(?P<G>.)c", "xabcy", "X\\g<G>X", FALSE, "XbX");
-#if !(PCRE_MAJOR > 8 || (PCRE_MAJOR == 8 && PCRE_MINOR >= 34))
- /* PCRE >= 8.34 no longer allows this usage. */
- TEST_EXPAND("(.)(?P<1>.)", "ab", "\\1", FALSE, "a");
- TEST_EXPAND("(.)(?P<1>.)", "ab", "\\g<1>", FALSE, "a");
-#endif
TEST_EXPAND(".", EURO, "\\0", FALSE, EURO);
TEST_EXPAND("(.)", EURO, "\\1", FALSE, EURO);
TEST_EXPAND("(?P<G>.)", EURO, "\\g<G>", FALSE, EURO);
@@ -2769,6 +3135,12 @@ main (int argc, char *argv[])
TEST_REPLACE("\\S+", "hello world", 0, "\\U-\\0-", "-HELLO- -WORLD-");
TEST_REPLACE(".", "a", 0, "\\A", NULL);
TEST_REPLACE(".", "a", 0, "\\g", NULL);
+ TEST_REPLACE_OPTIONS("(\\w+)#(\\w+)", "aa#bb cc#dd", 0, "\\2#\\1", "bb#aa dd#cc",
+ G_REGEX_OPTIMIZE|G_REGEX_MULTILINE|G_REGEX_CASELESS,
+ 0);
+ TEST_REPLACE_OPTIONS("(\\w+)#(\\w+)", "aa#bb cc#dd", 0, "\\2#\\1", "bb#aa cc#dd",
+ G_REGEX_OPTIMIZE|G_REGEX_MULTILINE|G_REGEX_CASELESS,
+ G_REGEX_MATCH_ANCHORED);
/* TEST_REPLACE_LIT(pattern, string, start_position, replacement, expected) */
TEST_REPLACE_LIT("a", "ababa", 0, "A", "AbAbA");
@@ -2799,6 +3171,10 @@ main (int argc, char *argv[])
TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)", "A", 1);
TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)", "B", 2);
TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)", "C", -1);
+ TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)(?P<C>b)", "A", 1);
+ TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)(?P<C>b)", "B", 2);
+ TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)(?P<C>b)", "C", 3);
+ TEST_GET_STRING_NUMBER("(?P<A>.)(?P<B>a)(?P<C>b)", "D", -1);
TEST_GET_STRING_NUMBER("(?P<A>.)(.)(?P<B>a)", "A", 1);
TEST_GET_STRING_NUMBER("(?P<A>.)(.)(?P<B>a)", "B", 3);
TEST_GET_STRING_NUMBER("(?P<A>.)(.)(?P<B>a)", "C", -1);