diff --git a/c/lib/mlrregex.c b/c/lib/mlrregex.c index dfd384e89..3050b8af3 100644 --- a/c/lib/mlrregex.c +++ b/c/lib/mlrregex.c @@ -215,6 +215,20 @@ char* regextract(char* input, regex_t* pregex) { return mlr_alloc_string_from_char_range(&input[pmatch->rm_so], len); } +// ---------------------------------------------------------------- +char* regextract_or_else(char* input, regex_t* pregex, char* default_value) { + const size_t nmatchmax = 1; + regmatch_t matches[nmatchmax]; + + int matched = regmatch_or_die(pregex, input, nmatchmax, matches); + if (!matched) { + return mlr_strdup_or_die(default_value); + } + regmatch_t* pmatch = &matches[0]; + int len = pmatch->rm_eo - pmatch->rm_so; + return mlr_alloc_string_from_char_range(&input[pmatch->rm_so], len); +} + // ---------------------------------------------------------------- // Slot 0 is the entire matched input string. // Slots 1 and up are substring matches for parenthesized capture expressions (if any). diff --git a/c/lib/mlrregex.h b/c/lib/mlrregex.h index 9f9d37583..24137158c 100644 --- a/c/lib/mlrregex.h +++ b/c/lib/mlrregex.h @@ -35,6 +35,7 @@ char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* repl // The return value is dynamically allocated if there is a match, else it returns null. char* regextract(char* input, regex_t* pregex); +char* regextract_or_else(char* input, regex_t* pregex, char* default_value); // The regex library gives us an array of match pointers into the input string. This function strdups them // out into separate storage, to implement "\0", "\1", "\2", etc. regex-captures for the =~ and !=~ operators. diff --git a/c/lib/mvfuncs.c b/c/lib/mvfuncs.c index daeb4e09a..5dd7c640b 100644 --- a/c/lib/mvfuncs.c +++ b/c/lib/mvfuncs.c @@ -214,6 +214,26 @@ mv_t regextract_precomp_func(mv_t* pval1, regex_t* pregex) { } } +// ---------------------------------------------------------------- +mv_t regextract_or_else_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3) { + regex_t regex; + mv_t rv = regextract_or_else_precomp_func(pval1, regcomp_or_die(®ex, pval2->u.strv, 0), pval3); + regfree(®ex); + mv_free(pval2); + return rv; +} + +// ---------------------------------------------------------------- +mv_t regextract_or_else_precomp_func(mv_t* pval1, regex_t* pregex, mv_t* pval3) { + char* input = pval1->u.strv; + char* default_value = pval3->u.strv; + char* output = regextract_or_else(input, pregex, default_value); + + mv_free(pval1); + mv_free(pval3); + return mv_from_string_with_free(output); +} + // ---------------------------------------------------------------- // String-substitution with no regexes or special characters. // It is assumed that all inputs have already been checked to be strings. diff --git a/c/lib/mvfuncs.h b/c/lib/mvfuncs.h index 13cd7b1f3..b486cb4ba 100644 --- a/c/lib/mvfuncs.h +++ b/c/lib/mvfuncs.h @@ -207,6 +207,8 @@ mv_t gsub_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t gsub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t* pval3); mv_t regextract_no_precomp_func(mv_t* pval1, mv_t* pval2); mv_t regextract_precomp_func(mv_t* pval1, regex_t* pregex); +mv_t regextract_or_else_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); +mv_t regextract_or_else_precomp_func(mv_t* pval1, regex_t* pregex, mv_t* pval3); // String-substitution with no regexes or special characters. mv_t s_sss_ssub_func(mv_t* pstring, mv_t* pold, mv_t* pnew);