return TRUE;
}
+/*
+ * Returns number of first matched subpattern with name @name.
+ * There may be more than one in case when DUPNAMES is used,
+ * and not all subpatterns with that name match;
+ * pcre_get_stringnumber() does not work in that case.
+ */
+static gint
+get_matched_substring_number (const GMatchInfo *match_info,
+ const gchar *name)
+{
+ gint entrysize;
+ gchar *first, *last;
+ guchar *entry;
+
+ if ((match_info->regex->compile_opts & G_REGEX_DUPNAMES) == 0)
+ return pcre_get_stringnumber (match_info->regex->pcre_re, name);
+
+ /* This code is copied from pcre_get.c: get_first_set() */
+ entrysize = pcre_get_stringtable_entries (match_info->regex->pcre_re,
+ name,
+ &first,
+ &last);
+
+ if (entrysize <= 0)
+ return entrysize;
+
+ for (entry = (guchar*) first; entry <= (guchar*) last; entry += entrysize)
+ {
+ gint n = (entry[0] << 8) + entry[1];
+ if (match_info->offsets[n*2] >= 0)
+ return n;
+ }
+
+ return (first[0] << 8) + first[1];
+}
+
/**
* g_match_info_fetch_named:
* @match_info: #GMatchInfo structure
g_return_val_if_fail (match_info != NULL, NULL);
g_return_val_if_fail (name != NULL, NULL);
- num = g_regex_get_string_number (match_info->regex, name);
- if (num == -1)
+ num = get_matched_substring_number (match_info, name);
+ if (num < 0)
return NULL;
else
return g_match_info_fetch (match_info, num);
g_return_val_if_fail (match_info != NULL, FALSE);
g_return_val_if_fail (name != NULL, FALSE);
-
- num = g_regex_get_string_number (match_info->regex, name);
- if (num == -1)
+
+ num = get_matched_substring_number (match_info, name);
+ if (num < 0)
return FALSE;
return g_match_info_fetch_pos (match_info, num, start_pos, end_pos);
static gboolean
test_named_sub_pattern (const gchar *pattern,
+ GRegexCompileFlags flags,
const gchar *string,
gint start_position,
const gchar *sub_name,
verbose ("fetching sub-pattern \"%s\" from \"%s\" (pattern: \"%s\") \t",
sub_name, string, pattern);
- regex = g_regex_new (pattern, 0, 0, NULL);
+ regex = g_regex_new (pattern, flags, 0, NULL);
g_regex_match_full (regex, string, -1, start_position, 0, &match_info, NULL);
sub_expr = g_match_info_fetch_named (match_info, sub_name);
#define TEST_NAMED_SUB_PATTERN(pattern, string, start_position, sub_name, \
expected_sub, expected_start, expected_end) { \
total++; \
- if (test_named_sub_pattern (pattern, string, start_position, sub_name, \
+ if (test_named_sub_pattern (pattern, 0, string, start_position, sub_name, \
expected_sub, expected_start, expected_end)) \
PASS; \
else \
FAIL; \
}
+#define TEST_NAMED_SUB_PATTERN_DUPNAMES(pattern, string, start_position, sub_name, \
+ expected_sub, expected_start, expected_end) { \
+ total++; \
+ if (test_named_sub_pattern (pattern, G_REGEX_DUPNAMES, string, start_position, \
+ sub_name, expected_sub, expected_start, expected_end)) \
+ PASS; \
+ else \
+ FAIL; \
+}
+
static gboolean
test_fetch_all (const gchar *pattern,
const gchar *string,
TEST_NAMED_SUB_PATTERN("(?P<A>a)?(?P<B>b)", "b", 0, "A", "", -1, -1);
TEST_NAMED_SUB_PATTERN("(?P<A>a)?(?P<B>b)", "b", 0, "B", "b", 0, 1);
+ /* TEST_NAMED_SUB_PATTERN_DUPNAMES(pattern, string, start_position, sub_name,
+ * expected_sub, expected_start, expected_end) */
+ TEST_NAMED_SUB_PATTERN_DUPNAMES("(?P<N>a)|(?P<N>b)", "ab", 0, "N", "a", 0, 1);
+ TEST_NAMED_SUB_PATTERN_DUPNAMES("(?P<N>aa)|(?P<N>a)", "aa", 0, "N", "aa", 0, 2);
+ TEST_NAMED_SUB_PATTERN_DUPNAMES("(?P<N>aa)(?P<N>a)", "aaa", 0, "N", "aa", 0, 2);
+ TEST_NAMED_SUB_PATTERN_DUPNAMES("(?P<N>x)|(?P<N>a)", "a", 0, "N", "a", 0, 1);
+ TEST_NAMED_SUB_PATTERN_DUPNAMES("(?P<N>x)y|(?P<N>a)b", "ab", 0, "N", "a", 0, 1);
+
/* TEST_FETCH_ALL#(pattern, string, ...) */
TEST_FETCH_ALL0("a", "");
TEST_FETCH_ALL0("a", "b");