diff --git a/c/lib/mlrutil.c b/c/lib/mlrutil.c index 61b950e15..026ec9051 100644 --- a/c/lib/mlrutil.c +++ b/c/lib/mlrutil.c @@ -513,3 +513,38 @@ char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* repla return sb_finish(psb); } } + +char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement) { + const size_t nmatch = 1; // xxx temp: parameterize after adding capture-group support + regmatch_t pmatch[nmatch]; + + int match_start = 0; + char* current_input = input; + + while (TRUE) { + int matched = regmatch_or_die(pregex, ¤t_input[match_start], nmatch, pmatch); + if (!matched) { + return current_input; + } + + int so = pmatch[0].rm_so; + int eo = pmatch[0].rm_eo; + + int len1 = match_start + so; + int olen2 = eo - so; + int nlen2 = strlen(replacement); + int len3 = strlen(¤t_input[len1 + olen2]); + int len4 = len1 + nlen2 + len3; + + char* current_output = mlr_malloc_or_die(len4 + 1); + strncpy(¤t_output[0], current_input, len1); + strncpy(¤t_output[len1], replacement, nlen2); + strncpy(¤t_output[len1+nlen2], ¤t_input[len1+olen2], len3); + current_output[len4] = 0; + + free(current_input); + current_input = current_output; + + match_start = len1 + nlen2; + } +} diff --git a/c/lib/mlrutil.h b/c/lib/mlrutil.h index e43a910dd..60ee9359d 100644 --- a/c/lib/mlrutil.h +++ b/c/lib/mlrutil.h @@ -135,6 +135,7 @@ int regmatch_or_die(const regex_t* pregex, const char* restrict match_string, // allocated. If not, input is returned. So in either case, the caller should // free the return value, and it is assumed that the input has been dynamically // allocated. -char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement); +char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement); +char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement); #endif // MLRUTIL_H diff --git a/c/mapping/mlr_val.c b/c/mapping/mlr_val.c index 38fa74046..3ba7144aa 100644 --- a/c/mapping/mlr_val.c +++ b/c/mapping/mlr_val.c @@ -203,7 +203,6 @@ mv_t sub_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3) { // * len4 = 6 = 2+3+1 mv_t sub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t* pval3) { - char* input = pval1->u.strv; char* output = regex_sub(input, pregex, psb, pval3->u.strv); @@ -238,39 +237,11 @@ 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) { - const size_t nmatch = 1; // xxx temp: parameterize after adding capture-group support - regmatch_t pmatch[nmatch]; + char* input = pval1->u.strv; + char* output = regex_gsub(input, pregex, psb, pval3->u.strv); - int match_start = 0; - char* current_input = pval1->u.strv; - - while (TRUE) { - int matched = regmatch_or_die(pregex, ¤t_input[match_start], nmatch, pmatch); - if (!matched) { - free(pval3->u.strv); - return (mv_t) {.type = MT_STRING, .u.strv = current_input}; - } - - int so = pmatch[0].rm_so; - int eo = pmatch[0].rm_eo; - - int len1 = match_start + so; - int olen2 = eo - so; - int nlen2 = strlen(pval3->u.strv); - int len3 = strlen(¤t_input[len1 + olen2]); - int len4 = len1 + nlen2 + len3; - - char* current_output = mlr_malloc_or_die(len4 + 1); - strncpy(¤t_output[0], current_input, len1); - strncpy(¤t_output[len1], pval3->u.strv, nlen2); - strncpy(¤t_output[len1+nlen2], ¤t_input[len1+olen2], len3); - current_output[len4] = 0; - - free(current_input); - current_input = current_output; - - match_start = len1 + nlen2; - } + free(pval3->u.strv); + return (mv_t) {.type = MT_STRING, .u.strv = output}; } // ----------------------------------------------------------------