diff src/strings.c @ 26684:2126feddeda6 v8.2.3871

patch 8.2.3871: list.c contains code for dict and blob Commit: https://github.com/vim/vim/commit/f973eeb4911de09258e84cb2248dc0f9392824b4 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Wed Dec 22 18:19:26 2021 +0000 patch 8.2.3871: list.c contains code for dict and blob Problem: List.c contains code for dict and blob. Solution: Refactor to put code where it belongs. (Yegappan Lakshmanan, closes #9386)
author Bram Moolenaar <Bram@vim.org>
date Wed, 22 Dec 2021 19:30:04 +0100
parents ce6490cd6282
children 31c23760d590
line wrap: on
line diff
--- a/src/strings.c
+++ b/src/strings.c
@@ -764,7 +764,6 @@ concat_str(char_u *str1, char_u *str2)
 }
 
 #if defined(FEAT_EVAL) || defined(PROTO)
-
 /*
  * Return string "str" in ' quotes, doubling ' characters.
  * If "str" is NULL an empty string is assumed.
@@ -809,6 +808,185 @@ string_quote(char_u *str, int function)
     return s;
 }
 
+/*
+ * Count the number of times "needle" occurs in string "haystack". Case is
+ * ignored if "ic" is TRUE.
+ */
+    long
+string_count(char_u *haystack, char_u *needle, int ic)
+{
+    long	n = 0;
+    char_u	*p = haystack;
+    char_u	*next;
+
+    if (p == NULL || needle == NULL || *needle == NUL)
+	return 0;
+
+    if (ic)
+    {
+	size_t len = STRLEN(needle);
+
+	while (*p != NUL)
+	{
+	    if (MB_STRNICMP(p, needle, len) == 0)
+	    {
+		++n;
+		p += len;
+	    }
+	    else
+		MB_PTR_ADV(p);
+	}
+    }
+    else
+	while ((next = (char_u *)strstr((char *)p, (char *)needle)) != NULL)
+	{
+	    ++n;
+	    p = next + STRLEN(needle);
+	}
+
+    return n;
+}
+
+/*
+ * Make a typval_T of the first character of "input" and store it in "output".
+ * Return OK or FAIL.
+ */
+    static int
+copy_first_char_to_tv(char_u *input, typval_T *output)
+{
+    char_u	buf[MB_MAXBYTES + 1];
+    int		len;
+
+    if (input == NULL || output == NULL)
+	return FAIL;
+
+    len = has_mbyte ? mb_ptr2len(input) : 1;
+    STRNCPY(buf, input, len);
+    buf[len] = NUL;
+    output->v_type = VAR_STRING;
+    output->vval.v_string = vim_strsave(buf);
+
+    return output->vval.v_string == NULL ? FAIL : OK;
+}
+
+/*
+ * Implementation of map() and filter() for a String. Apply "expr" to every
+ * character in string "str" and return the result in "rettv".
+ */
+    void
+string_filter_map(
+	char_u		*str,
+	filtermap_T	filtermap,
+	typval_T	*expr,
+	typval_T	*rettv)
+{
+    char_u	*p;
+    typval_T	tv;
+    garray_T	ga;
+    int		len = 0;
+    int		idx = 0;
+    int		rem;
+
+    rettv->v_type = VAR_STRING;
+    rettv->vval.v_string = NULL;
+
+    // set_vim_var_nr() doesn't set the type
+    set_vim_var_type(VV_KEY, VAR_NUMBER);
+
+    ga_init2(&ga, (int)sizeof(char), 80);
+    for (p = str; *p != NUL; p += len)
+    {
+	typval_T newtv;
+
+	if (copy_first_char_to_tv(p, &tv) == FAIL)
+	    break;
+	len = (int)STRLEN(tv.vval.v_string);
+
+	set_vim_var_nr(VV_KEY, idx);
+	if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
+		|| did_emsg)
+	    break;
+	if (did_emsg)
+	{
+	    clear_tv(&newtv);
+	    clear_tv(&tv);
+	    break;
+	}
+	else if (filtermap != FILTERMAP_FILTER)
+	{
+	    if (newtv.v_type != VAR_STRING)
+	    {
+		clear_tv(&newtv);
+		clear_tv(&tv);
+		emsg(_(e_stringreq));
+		break;
+	    }
+	    else
+		ga_concat(&ga, newtv.vval.v_string);
+	}
+	else if (!rem)
+	    ga_concat(&ga, tv.vval.v_string);
+
+	clear_tv(&newtv);
+	clear_tv(&tv);
+
+	++idx;
+    }
+    ga_append(&ga, NUL);
+    rettv->vval.v_string = ga.ga_data;
+}
+
+/*
+ * reduce() String argvars[0] using the function 'funcname' with arguments in
+ * 'funcexe' starting with the initial value argvars[2] and return the result
+ * in 'rettv'.
+ */
+    void
+string_reduce(
+	typval_T	*argvars,
+	char_u		*func_name,
+	funcexe_T	*funcexe,
+	typval_T	*rettv)
+{
+    char_u	*p = tv_get_string(&argvars[0]);
+    int		len;
+    typval_T	argv[3];
+    int		r;
+    int		called_emsg_start = called_emsg;
+
+    if (argvars[2].v_type == VAR_UNKNOWN)
+    {
+	if (*p == NUL)
+	{
+	    semsg(_(e_reduceempty), "String");
+	    return;
+	}
+	if (copy_first_char_to_tv(p, rettv) == FAIL)
+	    return;
+	p += STRLEN(rettv->vval.v_string);
+    }
+    else if (argvars[2].v_type != VAR_STRING)
+    {
+	semsg(_(e_string_expected_for_argument_nr), 3);
+	return;
+    }
+    else
+	copy_tv(&argvars[2], rettv);
+
+    for ( ; *p != NUL; p += len)
+    {
+	argv[0] = *rettv;
+	if (copy_first_char_to_tv(p, &argv[1]) == FAIL)
+	    break;
+	len = (int)STRLEN(argv[1].vval.v_string);
+	r = call_func(func_name, -1, rettv, 2, argv, funcexe);
+	clear_tv(&argv[0]);
+	clear_tv(&argv[1]);
+	if (r == FAIL || called_emsg != called_emsg_start)
+	    return;
+    }
+}
+
     static void
 byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED)
 {
@@ -1686,9 +1864,6 @@ f_trim(typval_T *argvars, typval_T *rett
     rettv->vval.v_string = vim_strnsave(head, tail - head);
 }
 
-#endif
-
-#if defined(FEAT_EVAL)
 static char *e_printf = N_("E766: Insufficient arguments for printf()");
 
 /*
@@ -1766,6 +1941,7 @@ tv_float(typval_T *tvs, int *idxp)
     return f;
 }
 # endif
+
 #endif
 
 #ifdef FEAT_FLOAT