changeset 24226:f49f80a0905d v8.2.2654

patch 8.2.2654: Vim9: getting a character from a string can be slow Commit: https://github.com/vim/vim/commit/ff871400461183010d3ab98f3f326e4bb75e221b Author: Bram Moolenaar <Bram@vim.org> Date: Fri Mar 26 13:34:05 2021 +0100 patch 8.2.2654: Vim9: getting a character from a string can be slow Problem: Vim9: getting a character from a string can be slow. Solution: Avoid a function call to get the character byte size. (https://github.com/vim/vim/issues/8000)
author Bram Moolenaar <Bram@vim.org>
date Fri, 26 Mar 2021 13:45:02 +0100
parents b19ab4d458ab
children dc3e9b290b7e
files src/version.c src/vim9execute.c
diffstat 2 files changed, 21 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1067,13 +1067,22 @@ char_from_string(char_u *str, varnumber_
 	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_
     }
 
     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));