summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-26 13:34:05 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-26 13:34:05 +0100
commitff871400461183010d3ab98f3f326e4bb75e221b (patch)
tree553f27a2cc111081ed9cde957396441e95dbde02
parent3a0f092ac0dbdd4ce71f9c4abe020e89f13df36c (diff)
patch 8.2.2654: Vim9: getting a character from a string can be slowv8.2.2654
Problem: Vim9: getting a character from a string can be slow. Solution: Avoid a function call to get the character byte size. (#8000)
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c22
2 files changed, 21 insertions, 3 deletions
diff --git a/src/version.c b/src/version.c
index 37da6ab15f..5e177f09b3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2654,
+/**/
2653,
/**/
2652,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 1ae17d97bf..2eb0bec13d 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1067,13 +1067,22 @@ char_from_string(char_u *str, varnumber_T index)
return NULL;
slen = STRLEN(str);
- // do the same as for a list: a negative index counts from the end
+ // Do the same as for a list: a negative index counts from the end.
+ // Optimization to check the first byte to be below 0x80 (and no composing
+ // character follows) makes this a lot faster.
if (index < 0)
{
int clen = 0;
for (nbyte = 0; nbyte < slen; ++clen)
- nbyte += mb_ptr2len(str + nbyte);
+ {
+ if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
+ ++nbyte;
+ else if (enc_utf8)
+ nbyte += utfc_ptr2len(str + nbyte);
+ else
+ nbyte += mb_ptr2len(str + nbyte);
+ }
nchar = clen + index;
if (nchar < 0)
// unlike list: index out of range results in empty string
@@ -1081,7 +1090,14 @@ char_from_string(char_u *str, varnumber_T index)
}
for (nbyte = 0; nchar > 0 && nbyte < slen; --nchar)
- nbyte += mb_ptr2len(str + nbyte);
+ {
+ if (str[nbyte] < 0x80 && str[nbyte + 1] < 0x80)
+ ++nbyte;
+ else if (enc_utf8)
+ nbyte += utfc_ptr2len(str + nbyte);
+ else
+ nbyte += mb_ptr2len(str + nbyte);
+ }
if (nbyte >= slen)
return NULL;
return vim_strnsave(str + nbyte, mb_ptr2len(str + nbyte));