From da6aca54439f00aaf17e3cc2b6bfb2aa1d99df25 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Thu, 14 Jan 2016 23:17:53 -0500 Subject: [PATCH] regex-capture iterate --- c/Makefile.no-autoconfig | 1 + c/lib/mlrutil.c | 38 ++++++++++++++++++++++- c/lib/mlrutil.h | 3 ++ c/mapping/lrec_evaluators.c | 34 --------------------- c/unit_test/test_mlrutil.c | 60 +++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 35 deletions(-) diff --git a/c/Makefile.no-autoconfig b/c/Makefile.no-autoconfig index b4f6de86d..6db3077bf 100644 --- a/c/Makefile.no-autoconfig +++ b/c/Makefile.no-autoconfig @@ -117,6 +117,7 @@ TEST_MLRUTIL_SRCS = \ lib/mlr_globals.c \ lib/mlrutil.c \ lib/string_builder.c \ + lib/string_array.c \ unit_test/test_mlrutil.c TEST_STRING_BUILDER_SRCS = \ diff --git a/c/lib/mlrutil.c b/c/lib/mlrutil.c index 1461b1edf..8ed8d89af 100644 --- a/c/lib/mlrutil.c +++ b/c/lib/mlrutil.c @@ -546,7 +546,7 @@ char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* repl char* p = replacement; int len1 = psb->used_length; while (*p) { - if (p[0] == '\\' && isdigit(p[1])) { + if (p[0] == '\\' && isdigit(p[1]) && p[1] != '0') { int idx = p[1] - '0'; regmatch_t* pmatch = &matches[idx]; if (pmatch->rm_so == -1) { @@ -574,3 +574,39 @@ char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* repl match_start += matches[0].rm_so + replen; } } + +// ---------------------------------------------------------------- +char* interpolate_regex_captures(char* input, string_array_t* pregex_captures, int* pwas_allocated) { + *pwas_allocated = FALSE; + if (pregex_captures == NULL || pregex_captures->length == 0) + return input; + + string_builder_t* psb = sb_alloc(32); + + char* p = input; + while (*p) { + if (p[0] == '\\' && isdigit(p[1]) && p[1] != '0') { + int idx = p[1] - '0' - 1; + if (idx < pregex_captures->length) { + *pwas_allocated = TRUE; + sb_append_string(psb, pregex_captures->strings[idx]); + } else { + sb_append_char(psb, p[0]); + sb_append_char(psb, p[1]); + } + p += 2; + } else { + sb_append_char(psb, *p); + p++; + } + } + + if (*pwas_allocated) { + char* output = sb_finish(psb); + sb_free(psb); + return output; + } else { + sb_free(psb); + return input; + } +} diff --git a/c/lib/mlrutil.h b/c/lib/mlrutil.h index 5779dd15f..ce56c34c9 100644 --- a/c/lib/mlrutil.h +++ b/c/lib/mlrutil.h @@ -7,6 +7,7 @@ #include #include #include "string_builder.h" +#include "string_array.h" #define TRUE 1 #define FALSE 0 @@ -148,4 +149,6 @@ char* regex_sub(char* input, regex_t* pregex, string_builder_t* psb, char* repla char* regex_gsub(char* input, regex_t* pregex, string_builder_t* psb, char* replacement, int* pmatched, int* pall_captured, unsigned char *pfree_flags); +char* interpolate_regex_captures(char* input, string_array_t* pregex_captures, int* pwas_allocated); + #endif // MLRUTIL_H diff --git a/c/mapping/lrec_evaluators.c b/c/mapping/lrec_evaluators.c index cdadc77ab..7a093ea58 100644 --- a/c/mapping/lrec_evaluators.c +++ b/c/mapping/lrec_evaluators.c @@ -1288,40 +1288,6 @@ typedef struct _lrec_evaluator_literal_state_t { // xxx put this in lib dir -//char* interpolate_regex_captures(char* input, string_array_t* pregex_captures, int* pwas_allocated) { -// *pwas_allocated = FALSE; -// if (pregex_captures == NULL || pregex_captures->length == 0) -// return input; -// string_builder_t* psb = sb_alloc(MV_SB_ALLOC_LENGTH); -// -// char* p = input; -// while (*p) { -// if (p[0] == '\\' && isdigit(p[1])) { -// int idx = p[1] - '0'; -// if (idx < pregex_captures->length) { -// *pwas_allocated = TRUE; -// sb_append_string(psb, pregex_captures->strings[i]); -// } else { -// sb_append_char(psb, p[0]); -// sb_append_char(psb, p[1]); -// } -// p += 2; -// } else { -// sb_append_char(psb, *p); -// p++; -// } -// } -// -// if (*pwas_allocated) { -// char* output = sb_finish(psb); -// sb_free(psb); -// return output; -// } else { -// sb_free(psb); -// return input; -// } -//} - mv_t lrec_evaluator_non_string_literal_func(lrec_t* prec, lhmsv_t* ptyped_overlay, string_array_t* pregex_captures, context_t* pctx, void* pvstate) { diff --git a/c/unit_test/test_mlrutil.c b/c/unit_test/test_mlrutil.c index a5f7143e9..b6a297c0e 100644 --- a/c/unit_test/test_mlrutil.c +++ b/c/unit_test/test_mlrutil.c @@ -142,6 +142,65 @@ static char * test_unbackslash() { return 0; } +// ---------------------------------------------------------------- +static char * test_interpolate_regex_captures() { + int was_allocated = FALSE; + + char* output = interpolate_regex_captures("hello", NULL, &was_allocated); + mu_assert_lf(streq(output, "hello")); + mu_assert_lf(was_allocated == FALSE); + + string_array_t* psa = string_array_alloc(0); + output = interpolate_regex_captures("hello", psa, &was_allocated); + mu_assert_lf(streq(output, "hello")); + mu_assert_lf(was_allocated == FALSE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("hello", psa, &was_allocated); + mu_assert_lf(streq(output, "hello")); + mu_assert_lf(was_allocated == FALSE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("h\\3ello", psa, &was_allocated); + printf("output=[%s]\n", output); + mu_assert_lf(streq(output, "hcello")); + mu_assert_lf(was_allocated == TRUE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("h\\1ello", psa, &was_allocated); + printf("output=[%s]\n", output); + mu_assert_lf(streq(output, "haello")); + mu_assert_lf(was_allocated == TRUE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("h\\4ello", psa, &was_allocated); + printf("output=[%s]\n", output); + mu_assert_lf(streq(output, "h\\4ello")); + mu_assert_lf(was_allocated == FALSE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("h\\0ello", psa, &was_allocated); + printf("output=[%s]\n", output); + mu_assert_lf(streq(output, "h\\0ello")); + mu_assert_lf(was_allocated == FALSE); + string_array_free(psa); + + psa = string_array_from_line(mlr_strdup_or_die("a,b,c"), ','); + output = interpolate_regex_captures("h\\3e\\1l\\2l\\4o", psa, &was_allocated); + printf("output=[%s]\n", output); + mu_assert_lf(streq(output, "hcealbl\\4o")); + mu_assert_lf(was_allocated == TRUE); + string_array_free(psa); + + return 0; +} + + // ================================================================ static char * all_tests() { mu_run_test(test_canonical_mod); @@ -151,6 +210,7 @@ static char * all_tests() { mu_run_test(test_scanners); mu_run_test(test_paste); mu_run_test(test_unbackslash); + mu_run_test(test_interpolate_regex_captures); return 0; }