From 01c9d6d306678fcd1737e85bbbc9e2fad2bdc808 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sat, 28 Apr 2018 11:21:14 -0700 Subject: [PATCH] ssub function --- c/dsl/function_manager.c | 3 +++ c/lib/mvfuncs.c | 52 ++++++++++++++++++++++++++++++++++++++++ c/lib/mvfuncs.h | 2 ++ 3 files changed, 57 insertions(+) diff --git a/c/dsl/function_manager.c b/c/dsl/function_manager.c index e0ce8c58b..b4b57b03f 100644 --- a/c/dsl/function_manager.c +++ b/c/dsl/function_manager.c @@ -233,6 +233,7 @@ static function_lookup_t FUNCTION_LOOKUP_TABLE[] = { {FUNC_CLASS_STRING, "gsub", 3,0, "Example: '$name=gsub($name, \"old\", \"new\")'\n(replace all)."}, {FUNC_CLASS_STRING, "strlen", 1,0, "String length."}, {FUNC_CLASS_STRING, "sub", 3,0, "Example: '$name=sub($name, \"old\", \"new\")'\n(replace once)."}, + {FUNC_CLASS_STRING, "ssub", 3,0, "Like sub but does no regexing. No characters are special."}, {FUNC_CLASS_STRING, "substr", 3,0, "substr(s,m,n) gives substring of s from 0-up position m to n \n" "inclusive. Negative indices -len .. -1 alias to 0 .. len-1."}, @@ -1228,6 +1229,8 @@ static rval_evaluator_t* fmgr_alloc_evaluator_from_ternary_func_name(char* fnnm, return rval_evaluator_alloc_from_s_sss_func(sub_no_precomp_func, parg1, parg2, parg3); } else if (streq(fnnm, "gsub")) { return rval_evaluator_alloc_from_s_sss_func(gsub_no_precomp_func, parg1, parg2, parg3); + } else if (streq(fnnm, "ssub")) { + return rval_evaluator_alloc_from_s_sss_func(s_sss_ssub_func, parg1, parg2, parg3); } else if (streq(fnnm, "logifit")) { return rval_evaluator_alloc_from_f_fff_func(f_fff_logifit_func, parg1, parg2, parg3); } else if (streq(fnnm, "madd")) { diff --git a/c/lib/mvfuncs.c b/c/lib/mvfuncs.c index 91166e8c6..2b2082dd6 100644 --- a/c/lib/mvfuncs.c +++ b/c/lib/mvfuncs.c @@ -192,6 +192,58 @@ mv_t gsub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t return mv_from_string(output, free_flags); } +// ---------------------------------------------------------------- +// String-substitution with no regexes or special characters. +// It is assumed that all inputs have already been checked to be strings. +mv_t s_sss_ssub_func(mv_t* pmvinput, mv_t* pmvold, mv_t* pmvnew) { + char* pinput = pmvinput->u.strv; + char* pold = pmvold->u.strv; + char* pnew = pmvnew->u.strv; + + char* pmatch = strstr(pinput, pold); + + if (pmatch == NULL) { + mv_free(pmvold); + mv_free(pmvnew); + return *pmvinput; + } else { + // Example: + // input: aaaaOOObbbbb + // old: OOO + // new: NNNNN + // Output length: strlen(aaaa) + strlen(NNNNN) + strlen(bbbbb) + + // Compute lengths + int input_length = strlen(pinput); + int old_length = strlen(pold); + int new_length = strlen(pnew); + int output_length = input_length - old_length + new_length + 1; + int pre_length = pmatch - pinput; // the "aaaa" part + int post_length = input_length - pre_length - old_length; // the "bbbbb" part + + // Allocate output + char* poutput = mlr_malloc_or_die(output_length); + char* p = poutput; + + // Populate output + strncpy(p, pinput, pre_length); + p += pre_length; + + strcpy(p, pnew); + p += new_length; + + strcpy(p, &pinput[pre_length + old_length]); + p += post_length; + + *p = 0; + + mv_free(pmvinput); + mv_free(pmvold); + mv_free(pmvnew); + return mv_from_string(poutput, FREE_ENTRY_VALUE); + } +} + // ---------------------------------------------------------------- // https://en.wikipedia.org/wiki/Hamming_weight diff --git a/c/lib/mvfuncs.h b/c/lib/mvfuncs.h index cc49478a6..fecae7d27 100644 --- a/c/lib/mvfuncs.h +++ b/c/lib/mvfuncs.h @@ -193,6 +193,8 @@ mv_t sub_no_precomp_func(mv_t* pval1, mv_t* pval2, mv_t* pval3); mv_t sub_precomp_func(mv_t* pval1, regex_t* pregex, string_builder_t* psb, mv_t* pval3); 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); +// String-substitution with no regexes or special characters. +mv_t s_sss_ssub_func(mv_t* pstring, mv_t* pold, mv_t* pnew); // ---------------------------------------------------------------- mv_t s_x_sec2gmt_func(mv_t* pval1);