Add rz_regex_get_group_idx_by_name()

This commit is contained in:
Rot127 2024-02-15 07:02:33 -05:00 committed by Anton Kochkov
parent 643718d499
commit 18a4d71492
3 changed files with 46 additions and 0 deletions

View file

@ -50,6 +50,7 @@ RZ_API RZ_OWN RzRegex *rz_regex_new(RZ_NONNULL const char *pattern, RzRegexFlags
RZ_API void rz_regex_free(RZ_OWN RzRegex *regex);
RZ_API void rz_regex_error_msg(RzRegexStatus errcode, RZ_OUT char *errbuf, RzRegexSize errbuf_size);
RZ_API const ut8 *rz_regex_get_match_name(RZ_NONNULL const RzRegex *regex, ut32 name_idx);
RZ_API st32 rz_regex_get_group_idx_by_name(RZ_NONNULL const RzRegex *regex, const char *group);
RZ_API RzRegexStatus rz_regex_match(RZ_NONNULL const RzRegex *regex, RZ_NONNULL const char *text,
RzRegexSize text_size,
RzRegexSize text_offset,

View file

@ -177,6 +177,46 @@ RZ_API const ut8 *rz_regex_get_match_name(RZ_NONNULL const RzRegex *regex, ut32
return NULL;
}
/**
* \brief Returns the name of a group.
*
* \param regex The regex expression with named groups.
* \param group_idx The index of the group to get the name for.
*
* \return The index of the group or RZ_REGEX_ERROR_NOMATCH in case of failure or if no name was given.
*/
RZ_API RzRegexStatus rz_regex_get_group_idx_by_name(RZ_NONNULL const RzRegex *regex, const char *group) {
rz_return_val_if_fail(regex, RZ_REGEX_ERROR_NOMATCH);
ut32 namecount;
ut32 name_entry_size;
PCRE2_SPTR nametable_ptr;
pcre2_pattern_info(
regex,
PCRE2_INFO_NAMECOUNT,
&namecount);
pcre2_pattern_info(
regex,
PCRE2_INFO_NAMETABLE,
&nametable_ptr);
pcre2_pattern_info(
regex,
PCRE2_INFO_NAMEENTRYSIZE,
&name_entry_size);
for (size_t i = 0; i < namecount; i++) {
int n = (nametable_ptr[0] << 8) | nametable_ptr[1];
if (RZ_STR_EQ((const char *)nametable_ptr + 2, group)) {
return n;
}
nametable_ptr += name_entry_size;
}
return RZ_REGEX_ERROR_NOMATCH;
}
/**
* \brief Finds the first match in a text and returns it as a pvector.
* First element in the vector is always the whole match, the following possible groups.

View file

@ -173,6 +173,11 @@ bool test_rz_regex_named_matches(void) {
mu_assert_streq((char *)rz_regex_get_match_name(reg, 3), "domain", "domain name not set.");
mu_assert_streq((char *)rz_regex_get_match_name(reg, 4), "tdomain", "tdomain name not set.");
mu_assert_eq(rz_regex_get_group_idx_by_name(reg, "proto"), 1, "proto name not set.");
mu_assert_eq(rz_regex_get_group_idx_by_name(reg, "domain"), 3, "domain name not set.");
mu_assert_eq(rz_regex_get_group_idx_by_name(reg, "tdomain"), 4, "tdomain name not set.");
mu_assert_eq(rz_regex_get_group_idx_by_name(reg, "nonexistent"), -1, "shouldn't exis");
RzPVector *matches = rz_regex_match_all_not_grouped(reg, "https://rizin.re", RZ_REGEX_ZERO_TERMINATED, 0, RZ_REGEX_DEFAULT);
mu_assert_true(matches && !rz_pvector_empty(matches), "Regex match failed");
mu_assert_eq(rz_pvector_len(matches), 5, "Regex match count failed.");