Mercurial > vim
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