forked from aniani/vim
patch 8.2.3139: functions for string manipulation are spread out
Problem: Functions for string manipulation are spread out.
Solution: Move string related functions to a new source file. (Yegappan
Lakshmanan, closes #8470)
This commit is contained in:
committed by
Bram Moolenaar
parent
31e21766d6
commit
a2438132a6
825
src/evalfunc.c
825
src/evalfunc.c
@@ -29,14 +29,10 @@ static void f_balloon_split(typval_T *argvars, typval_T *rettv);
|
||||
# endif
|
||||
#endif
|
||||
static void f_byte2line(typval_T *argvars, typval_T *rettv);
|
||||
static void byteidx(typval_T *argvars, typval_T *rettv, int comp);
|
||||
static void f_byteidx(typval_T *argvars, typval_T *rettv);
|
||||
static void f_byteidxcomp(typval_T *argvars, typval_T *rettv);
|
||||
static void f_call(typval_T *argvars, typval_T *rettv);
|
||||
static void f_changenr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_char2nr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_charcol(typval_T *argvars, typval_T *rettv);
|
||||
static void f_charidx(typval_T *argvars, typval_T *rettv);
|
||||
static void f_col(typval_T *argvars, typval_T *rettv);
|
||||
static void f_confirm(typval_T *argvars, typval_T *rettv);
|
||||
static void f_copy(typval_T *argvars, typval_T *rettv);
|
||||
@@ -83,7 +79,6 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv);
|
||||
static void f_hlID(typval_T *argvars, typval_T *rettv);
|
||||
static void f_hlexists(typval_T *argvars, typval_T *rettv);
|
||||
static void f_hostname(typval_T *argvars, typval_T *rettv);
|
||||
static void f_iconv(typval_T *argvars, typval_T *rettv);
|
||||
static void f_index(typval_T *argvars, typval_T *rettv);
|
||||
static void f_input(typval_T *argvars, typval_T *rettv);
|
||||
static void f_inputdialog(typval_T *argvars, typval_T *rettv);
|
||||
@@ -173,19 +168,6 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv);
|
||||
static void f_spellsuggest(typval_T *argvars, typval_T *rettv);
|
||||
static void f_split(typval_T *argvars, typval_T *rettv);
|
||||
static void f_srand(typval_T *argvars, typval_T *rettv);
|
||||
static void f_str2list(typval_T *argvars, typval_T *rettv);
|
||||
static void f_str2nr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strcharlen(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strchars(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strgetchar(typval_T *argvars, typval_T *rettv);
|
||||
static void f_stridx(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strlen(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strcharpart(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strpart(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strridx(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strtrans(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv);
|
||||
static void f_strwidth(typval_T *argvars, typval_T *rettv);
|
||||
static void f_submatch(typval_T *argvars, typval_T *rettv);
|
||||
static void f_substitute(typval_T *argvars, typval_T *rettv);
|
||||
static void f_swapinfo(typval_T *argvars, typval_T *rettv);
|
||||
@@ -198,10 +180,6 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv);
|
||||
static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_taglist(typval_T *argvars, typval_T *rettv);
|
||||
static void f_tagfiles(typval_T *argvars, typval_T *rettv);
|
||||
static void f_tolower(typval_T *argvars, typval_T *rettv);
|
||||
static void f_toupper(typval_T *argvars, typval_T *rettv);
|
||||
static void f_tr(typval_T *argvars, typval_T *rettv);
|
||||
static void f_trim(typval_T *argvars, typval_T *rettv);
|
||||
static void f_type(typval_T *argvars, typval_T *rettv);
|
||||
static void f_virtcol(typval_T *argvars, typval_T *rettv);
|
||||
static void f_visualmode(typval_T *argvars, typval_T *rettv);
|
||||
@@ -2377,50 +2355,6 @@ f_byte2line(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED)
|
||||
{
|
||||
char_u *t;
|
||||
char_u *str;
|
||||
varnumber_T idx;
|
||||
|
||||
str = tv_get_string_chk(&argvars[0]);
|
||||
idx = tv_get_number_chk(&argvars[1], NULL);
|
||||
rettv->vval.v_number = -1;
|
||||
if (str == NULL || idx < 0)
|
||||
return;
|
||||
|
||||
t = str;
|
||||
for ( ; idx > 0; idx--)
|
||||
{
|
||||
if (*t == NUL) // EOL reached
|
||||
return;
|
||||
if (enc_utf8 && comp)
|
||||
t += utf_ptr2len(t);
|
||||
else
|
||||
t += (*mb_ptr2len)(t);
|
||||
}
|
||||
rettv->vval.v_number = (varnumber_T)(t - str);
|
||||
}
|
||||
|
||||
/*
|
||||
* "byteidx()" function
|
||||
*/
|
||||
static void
|
||||
f_byteidx(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
byteidx(argvars, rettv, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "byteidxcomp()" function
|
||||
*/
|
||||
static void
|
||||
f_byteidxcomp(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
byteidx(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "call(func, arglist [, dict])" function
|
||||
*/
|
||||
@@ -2552,58 +2486,6 @@ f_charcol(typval_T *argvars, typval_T *rettv)
|
||||
get_col(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "charidx()" function
|
||||
*/
|
||||
static void
|
||||
f_charidx(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *str;
|
||||
varnumber_T idx;
|
||||
varnumber_T countcc = FALSE;
|
||||
char_u *p;
|
||||
int len;
|
||||
int (*ptr2len)(char_u *);
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
|
||||
if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER
|
||||
|| (argvars[2].v_type != VAR_UNKNOWN
|
||||
&& argvars[2].v_type != VAR_NUMBER
|
||||
&& argvars[2].v_type != VAR_BOOL))
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
|
||||
str = tv_get_string_chk(&argvars[0]);
|
||||
idx = tv_get_number_chk(&argvars[1], NULL);
|
||||
if (str == NULL || idx < 0)
|
||||
return;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
countcc = tv_get_bool(&argvars[2]);
|
||||
if (countcc < 0 || countcc > 1)
|
||||
{
|
||||
semsg(_(e_using_number_as_bool_nr), countcc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (enc_utf8 && countcc)
|
||||
ptr2len = utf_ptr2len;
|
||||
else
|
||||
ptr2len = mb_ptr2len;
|
||||
|
||||
for (p = str, len = 0; p <= str + idx; len++)
|
||||
{
|
||||
if (*p == NUL)
|
||||
return;
|
||||
p += ptr2len(p);
|
||||
}
|
||||
|
||||
rettv->vval.v_number = len > 0 ? len - 1 : 0;
|
||||
}
|
||||
|
||||
win_T *
|
||||
get_optional_window(typval_T *argvars, int idx)
|
||||
{
|
||||
@@ -5780,37 +5662,6 @@ f_hostname(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
rettv->vval.v_string = vim_strsave(hostname);
|
||||
}
|
||||
|
||||
/*
|
||||
* iconv() function
|
||||
*/
|
||||
static void
|
||||
f_iconv(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
char_u buf1[NUMBUFLEN];
|
||||
char_u buf2[NUMBUFLEN];
|
||||
char_u *from, *to, *str;
|
||||
vimconv_T vimconv;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
str = tv_get_string(&argvars[0]);
|
||||
from = enc_canonize(enc_skip(tv_get_string_buf(&argvars[1], buf1)));
|
||||
to = enc_canonize(enc_skip(tv_get_string_buf(&argvars[2], buf2)));
|
||||
vimconv.vc_type = CONV_NONE;
|
||||
convert_setup(&vimconv, from, to);
|
||||
|
||||
// If the encodings are equal, no conversion needed.
|
||||
if (vimconv.vc_type == CONV_NONE)
|
||||
rettv->vval.v_string = vim_strsave(str);
|
||||
else
|
||||
rettv->vval.v_string = string_convert(&vimconv, str, NULL);
|
||||
|
||||
convert_setup(&vimconv, NULL, NULL);
|
||||
vim_free(from);
|
||||
vim_free(to);
|
||||
}
|
||||
|
||||
/*
|
||||
* "index()" function
|
||||
*/
|
||||
@@ -8786,452 +8637,6 @@ theend:
|
||||
p_cpo = save_cpo;
|
||||
}
|
||||
|
||||
/*
|
||||
* "str2list()" function
|
||||
*/
|
||||
static void
|
||||
f_str2list(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *p;
|
||||
int utf8 = FALSE;
|
||||
|
||||
if (rettv_list_alloc(rettv) == FAIL)
|
||||
return;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
utf8 = (int)tv_get_bool_chk(&argvars[1], NULL);
|
||||
|
||||
p = tv_get_string(&argvars[0]);
|
||||
|
||||
if (has_mbyte || utf8)
|
||||
{
|
||||
int (*ptr2len)(char_u *);
|
||||
int (*ptr2char)(char_u *);
|
||||
|
||||
if (utf8 || enc_utf8)
|
||||
{
|
||||
ptr2len = utf_ptr2len;
|
||||
ptr2char = utf_ptr2char;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr2len = mb_ptr2len;
|
||||
ptr2char = mb_ptr2char;
|
||||
}
|
||||
|
||||
for ( ; *p != NUL; p += (*ptr2len)(p))
|
||||
list_append_number(rettv->vval.v_list, (*ptr2char)(p));
|
||||
}
|
||||
else
|
||||
for ( ; *p != NUL; ++p)
|
||||
list_append_number(rettv->vval.v_list, *p);
|
||||
}
|
||||
|
||||
/*
|
||||
* "str2nr()" function
|
||||
*/
|
||||
static void
|
||||
f_str2nr(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
int base = 10;
|
||||
char_u *p;
|
||||
varnumber_T n;
|
||||
int what = 0;
|
||||
int isneg;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
base = (int)tv_get_number(&argvars[1]);
|
||||
if (base != 2 && base != 8 && base != 10 && base != 16)
|
||||
{
|
||||
emsg(_(e_invarg));
|
||||
return;
|
||||
}
|
||||
if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2]))
|
||||
what |= STR2NR_QUOTE;
|
||||
}
|
||||
|
||||
p = skipwhite(tv_get_string_strict(&argvars[0]));
|
||||
isneg = (*p == '-');
|
||||
if (*p == '+' || *p == '-')
|
||||
p = skipwhite(p + 1);
|
||||
switch (base)
|
||||
{
|
||||
case 2: what |= STR2NR_BIN + STR2NR_FORCE; break;
|
||||
case 8: what |= STR2NR_OCT + STR2NR_OOCT + STR2NR_FORCE; break;
|
||||
case 16: what |= STR2NR_HEX + STR2NR_FORCE; break;
|
||||
}
|
||||
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
|
||||
// Text after the number is silently ignored.
|
||||
if (isneg)
|
||||
rettv->vval.v_number = -n;
|
||||
else
|
||||
rettv->vval.v_number = n;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* "strgetchar()" function
|
||||
*/
|
||||
static void
|
||||
f_strgetchar(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *str;
|
||||
int len;
|
||||
int error = FALSE;
|
||||
int charidx;
|
||||
int byteidx = 0;
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
str = tv_get_string_chk(&argvars[0]);
|
||||
if (str == NULL)
|
||||
return;
|
||||
len = (int)STRLEN(str);
|
||||
charidx = (int)tv_get_number_chk(&argvars[1], &error);
|
||||
if (error)
|
||||
return;
|
||||
|
||||
while (charidx >= 0 && byteidx < len)
|
||||
{
|
||||
if (charidx == 0)
|
||||
{
|
||||
rettv->vval.v_number = mb_ptr2char(str + byteidx);
|
||||
break;
|
||||
}
|
||||
--charidx;
|
||||
byteidx += MB_CPTR2LEN(str + byteidx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "stridx()" function
|
||||
*/
|
||||
static void
|
||||
f_stridx(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u buf[NUMBUFLEN];
|
||||
char_u *needle;
|
||||
char_u *haystack;
|
||||
char_u *save_haystack;
|
||||
char_u *pos;
|
||||
int start_idx;
|
||||
|
||||
needle = tv_get_string_chk(&argvars[1]);
|
||||
save_haystack = haystack = tv_get_string_buf_chk(&argvars[0], buf);
|
||||
rettv->vval.v_number = -1;
|
||||
if (needle == NULL || haystack == NULL)
|
||||
return; // type error; errmsg already given
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
int error = FALSE;
|
||||
|
||||
start_idx = (int)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error || start_idx >= (int)STRLEN(haystack))
|
||||
return;
|
||||
if (start_idx >= 0)
|
||||
haystack += start_idx;
|
||||
}
|
||||
|
||||
pos = (char_u *)strstr((char *)haystack, (char *)needle);
|
||||
if (pos != NULL)
|
||||
rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
|
||||
}
|
||||
|
||||
/*
|
||||
* "string()" function
|
||||
*/
|
||||
void
|
||||
f_string(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *tofree;
|
||||
char_u numbuf[NUMBUFLEN];
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf,
|
||||
get_copyID());
|
||||
// Make a copy if we have a value but it's not in allocated memory.
|
||||
if (rettv->vval.v_string != NULL && tofree == NULL)
|
||||
rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strlen()" function
|
||||
*/
|
||||
static void
|
||||
f_strlen(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->vval.v_number = (varnumber_T)(STRLEN(
|
||||
tv_get_string(&argvars[0])));
|
||||
}
|
||||
|
||||
static void
|
||||
strchar_common(typval_T *argvars, typval_T *rettv, int skipcc)
|
||||
{
|
||||
char_u *s = tv_get_string(&argvars[0]);
|
||||
varnumber_T len = 0;
|
||||
int (*func_mb_ptr2char_adv)(char_u **pp);
|
||||
|
||||
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
|
||||
while (*s != NUL)
|
||||
{
|
||||
func_mb_ptr2char_adv(&s);
|
||||
++len;
|
||||
}
|
||||
rettv->vval.v_number = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* "strcharlen()" function
|
||||
*/
|
||||
static void
|
||||
f_strcharlen(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
strchar_common(argvars, rettv, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strchars()" function
|
||||
*/
|
||||
static void
|
||||
f_strchars(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
varnumber_T skipcc = FALSE;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
skipcc = tv_get_bool(&argvars[1]);
|
||||
if (skipcc < 0 || skipcc > 1)
|
||||
semsg(_(e_using_number_as_bool_nr), skipcc);
|
||||
else
|
||||
strchar_common(argvars, rettv, skipcc);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strdisplaywidth()" function
|
||||
*/
|
||||
static void
|
||||
f_strdisplaywidth(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *s = tv_get_string(&argvars[0]);
|
||||
int col = 0;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
col = (int)tv_get_number(&argvars[1]);
|
||||
|
||||
rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strwidth()" function
|
||||
*/
|
||||
static void
|
||||
f_strwidth(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *s = tv_get_string_strict(&argvars[0]);
|
||||
|
||||
rettv->vval.v_number = (varnumber_T)(mb_string2cells(s, -1));
|
||||
}
|
||||
|
||||
/*
|
||||
* "strcharpart()" function
|
||||
*/
|
||||
static void
|
||||
f_strcharpart(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *p;
|
||||
int nchar;
|
||||
int nbyte = 0;
|
||||
int charlen;
|
||||
int skipcc = FALSE;
|
||||
int len = 0;
|
||||
int slen;
|
||||
int error = FALSE;
|
||||
|
||||
p = tv_get_string(&argvars[0]);
|
||||
slen = (int)STRLEN(p);
|
||||
|
||||
nchar = (int)tv_get_number_chk(&argvars[1], &error);
|
||||
if (!error)
|
||||
{
|
||||
if (argvars[2].v_type != VAR_UNKNOWN
|
||||
&& argvars[3].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
skipcc = tv_get_bool(&argvars[3]);
|
||||
if (skipcc < 0 || skipcc > 1)
|
||||
{
|
||||
semsg(_(e_using_number_as_bool_nr), skipcc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (nchar > 0)
|
||||
while (nchar > 0 && nbyte < slen)
|
||||
{
|
||||
if (skipcc)
|
||||
nbyte += mb_ptr2len(p + nbyte);
|
||||
else
|
||||
nbyte += MB_CPTR2LEN(p + nbyte);
|
||||
--nchar;
|
||||
}
|
||||
else
|
||||
nbyte = nchar;
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
charlen = (int)tv_get_number(&argvars[2]);
|
||||
while (charlen > 0 && nbyte + len < slen)
|
||||
{
|
||||
int off = nbyte + len;
|
||||
|
||||
if (off < 0)
|
||||
len += 1;
|
||||
else
|
||||
{
|
||||
if (skipcc)
|
||||
len += mb_ptr2len(p + off);
|
||||
else
|
||||
len += MB_CPTR2LEN(p + off);
|
||||
}
|
||||
--charlen;
|
||||
}
|
||||
}
|
||||
else
|
||||
len = slen - nbyte; // default: all bytes that are available.
|
||||
}
|
||||
|
||||
/*
|
||||
* Only return the overlap between the specified part and the actual
|
||||
* string.
|
||||
*/
|
||||
if (nbyte < 0)
|
||||
{
|
||||
len += nbyte;
|
||||
nbyte = 0;
|
||||
}
|
||||
else if (nbyte > slen)
|
||||
nbyte = slen;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
else if (nbyte + len > slen)
|
||||
len = slen - nbyte;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = vim_strnsave(p + nbyte, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strpart()" function
|
||||
*/
|
||||
static void
|
||||
f_strpart(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *p;
|
||||
int n;
|
||||
int len;
|
||||
int slen;
|
||||
int error = FALSE;
|
||||
|
||||
p = tv_get_string(&argvars[0]);
|
||||
slen = (int)STRLEN(p);
|
||||
|
||||
n = (int)tv_get_number_chk(&argvars[1], &error);
|
||||
if (error)
|
||||
len = 0;
|
||||
else if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
len = (int)tv_get_number(&argvars[2]);
|
||||
else
|
||||
len = slen - n; // default len: all bytes that are available.
|
||||
|
||||
// Only return the overlap between the specified part and the actual
|
||||
// string.
|
||||
if (n < 0)
|
||||
{
|
||||
len += n;
|
||||
n = 0;
|
||||
}
|
||||
else if (n > slen)
|
||||
n = slen;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
else if (n + len > slen)
|
||||
len = slen - n;
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
int off;
|
||||
|
||||
// length in characters
|
||||
for (off = n; off < slen && len > 0; --len)
|
||||
off += mb_ptr2len(p + off);
|
||||
len = off - n;
|
||||
}
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = vim_strnsave(p + n, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strridx()" function
|
||||
*/
|
||||
static void
|
||||
f_strridx(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u buf[NUMBUFLEN];
|
||||
char_u *needle;
|
||||
char_u *haystack;
|
||||
char_u *rest;
|
||||
char_u *lastmatch = NULL;
|
||||
int haystack_len, end_idx;
|
||||
|
||||
needle = tv_get_string_chk(&argvars[1]);
|
||||
haystack = tv_get_string_buf_chk(&argvars[0], buf);
|
||||
|
||||
rettv->vval.v_number = -1;
|
||||
if (needle == NULL || haystack == NULL)
|
||||
return; // type error; errmsg already given
|
||||
|
||||
haystack_len = (int)STRLEN(haystack);
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
// Third argument: upper limit for index
|
||||
end_idx = (int)tv_get_number_chk(&argvars[2], NULL);
|
||||
if (end_idx < 0)
|
||||
return; // can never find a match
|
||||
}
|
||||
else
|
||||
end_idx = haystack_len;
|
||||
|
||||
if (*needle == NUL)
|
||||
{
|
||||
// Empty string matches past the end.
|
||||
lastmatch = haystack + end_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (rest = haystack; *rest != '\0'; ++rest)
|
||||
{
|
||||
rest = (char_u *)strstr((char *)rest, (char *)needle);
|
||||
if (rest == NULL || rest > haystack + end_idx)
|
||||
break;
|
||||
lastmatch = rest;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastmatch == NULL)
|
||||
rettv->vval.v_number = -1;
|
||||
else
|
||||
rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
|
||||
}
|
||||
|
||||
/*
|
||||
* "strtrans()" function
|
||||
*/
|
||||
static void
|
||||
f_strtrans(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = transstr(tv_get_string(&argvars[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
* "submatch()" function
|
||||
*/
|
||||
@@ -9627,236 +9032,6 @@ f_taglist(typval_T *argvars, typval_T *rettv)
|
||||
(void)get_tags(rettv->vval.v_list, tag_pattern, fname);
|
||||
}
|
||||
|
||||
/*
|
||||
* "tolower(string)" function
|
||||
*/
|
||||
static void
|
||||
f_tolower(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = strlow_save(tv_get_string(&argvars[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
* "toupper(string)" function
|
||||
*/
|
||||
static void
|
||||
f_toupper(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = strup_save(tv_get_string(&argvars[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
* "tr(string, fromstr, tostr)" function
|
||||
*/
|
||||
static void
|
||||
f_tr(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u *in_str;
|
||||
char_u *fromstr;
|
||||
char_u *tostr;
|
||||
char_u *p;
|
||||
int inlen;
|
||||
int fromlen;
|
||||
int tolen;
|
||||
int idx;
|
||||
char_u *cpstr;
|
||||
int cplen;
|
||||
int first = TRUE;
|
||||
char_u buf[NUMBUFLEN];
|
||||
char_u buf2[NUMBUFLEN];
|
||||
garray_T ga;
|
||||
|
||||
in_str = tv_get_string(&argvars[0]);
|
||||
fromstr = tv_get_string_buf_chk(&argvars[1], buf);
|
||||
tostr = tv_get_string_buf_chk(&argvars[2], buf2);
|
||||
|
||||
// Default return value: empty string.
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
if (fromstr == NULL || tostr == NULL)
|
||||
return; // type error; errmsg already given
|
||||
ga_init2(&ga, (int)sizeof(char), 80);
|
||||
|
||||
if (!has_mbyte)
|
||||
// not multi-byte: fromstr and tostr must be the same length
|
||||
if (STRLEN(fromstr) != STRLEN(tostr))
|
||||
{
|
||||
error:
|
||||
semsg(_(e_invarg2), fromstr);
|
||||
ga_clear(&ga);
|
||||
return;
|
||||
}
|
||||
|
||||
// fromstr and tostr have to contain the same number of chars
|
||||
while (*in_str != NUL)
|
||||
{
|
||||
if (has_mbyte)
|
||||
{
|
||||
inlen = (*mb_ptr2len)(in_str);
|
||||
cpstr = in_str;
|
||||
cplen = inlen;
|
||||
idx = 0;
|
||||
for (p = fromstr; *p != NUL; p += fromlen)
|
||||
{
|
||||
fromlen = (*mb_ptr2len)(p);
|
||||
if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0)
|
||||
{
|
||||
for (p = tostr; *p != NUL; p += tolen)
|
||||
{
|
||||
tolen = (*mb_ptr2len)(p);
|
||||
if (idx-- == 0)
|
||||
{
|
||||
cplen = tolen;
|
||||
cpstr = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == NUL) // tostr is shorter than fromstr
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
if (first && cpstr == in_str)
|
||||
{
|
||||
// Check that fromstr and tostr have the same number of
|
||||
// (multi-byte) characters. Done only once when a character
|
||||
// of in_str doesn't appear in fromstr.
|
||||
first = FALSE;
|
||||
for (p = tostr; *p != NUL; p += tolen)
|
||||
{
|
||||
tolen = (*mb_ptr2len)(p);
|
||||
--idx;
|
||||
}
|
||||
if (idx != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
(void)ga_grow(&ga, cplen);
|
||||
mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
|
||||
ga.ga_len += cplen;
|
||||
|
||||
in_str += inlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When not using multi-byte chars we can do it faster.
|
||||
p = vim_strchr(fromstr, *in_str);
|
||||
if (p != NULL)
|
||||
ga_append(&ga, tostr[p - fromstr]);
|
||||
else
|
||||
ga_append(&ga, *in_str);
|
||||
++in_str;
|
||||
}
|
||||
}
|
||||
|
||||
// add a terminating NUL
|
||||
(void)ga_grow(&ga, 1);
|
||||
ga_append(&ga, NUL);
|
||||
|
||||
rettv->vval.v_string = ga.ga_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* "trim({expr})" function
|
||||
*/
|
||||
static void
|
||||
f_trim(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
char_u buf1[NUMBUFLEN];
|
||||
char_u buf2[NUMBUFLEN];
|
||||
char_u *head = tv_get_string_buf_chk(&argvars[0], buf1);
|
||||
char_u *mask = NULL;
|
||||
char_u *tail;
|
||||
char_u *prev;
|
||||
char_u *p;
|
||||
int c1;
|
||||
int dir = 0;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
if (head == NULL)
|
||||
return;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (argvars[1].v_type == VAR_STRING)
|
||||
{
|
||||
mask = tv_get_string_buf_chk(&argvars[1], buf2);
|
||||
|
||||
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
// leading or trailing characters to trim
|
||||
dir = (int)tv_get_number_chk(&argvars[2], &error);
|
||||
if (error)
|
||||
return;
|
||||
if (dir < 0 || dir > 2)
|
||||
{
|
||||
semsg(_(e_invarg2), tv_get_string(&argvars[2]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dir == 0 || dir == 1)
|
||||
{
|
||||
// Trim leading characters
|
||||
while (*head != NUL)
|
||||
{
|
||||
c1 = PTR2CHAR(head);
|
||||
if (mask == NULL)
|
||||
{
|
||||
if (c1 > ' ' && c1 != 0xa0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (p = mask; *p != NUL; MB_PTR_ADV(p))
|
||||
if (c1 == PTR2CHAR(p))
|
||||
break;
|
||||
if (*p == NUL)
|
||||
break;
|
||||
}
|
||||
MB_PTR_ADV(head);
|
||||
}
|
||||
}
|
||||
|
||||
tail = head + STRLEN(head);
|
||||
if (dir == 0 || dir == 2)
|
||||
{
|
||||
// Trim trailing characters
|
||||
for (; tail > head; tail = prev)
|
||||
{
|
||||
prev = tail;
|
||||
MB_PTR_BACK(head, prev);
|
||||
c1 = PTR2CHAR(prev);
|
||||
if (mask == NULL)
|
||||
{
|
||||
if (c1 > ' ' && c1 != 0xa0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (p = mask; *p != NUL; MB_PTR_ADV(p))
|
||||
if (c1 == PTR2CHAR(p))
|
||||
break;
|
||||
if (*p == NUL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rettv->vval.v_string = vim_strnsave(head, tail - head);
|
||||
}
|
||||
|
||||
/*
|
||||
* "type(expr)" function
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user