]> granicus.if.org Git - vim/commitdiff
patch 8.2.2654: Vim9: getting a character from a string can be slow v8.2.2654
authorBram Moolenaar <Bram@vim.org>
Fri, 26 Mar 2021 12:34:05 +0000 (13:34 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 26 Mar 2021 12:34:05 +0000 (13:34 +0100)
Problem:    Vim9: getting a character from a string can be slow.
Solution:   Avoid a function call to get the character byte size. (#8000)

src/version.c
src/vim9execute.c

index 37da6ab15f8fec7c81b81715673ee84ef043c2df..5e177f09b3e812c22ba3a4adf93a1731a827182b 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2654,
 /**/
     2653,
 /**/
index 1ae17d97bfc4d3f8ae4d8a8ed5aa76523a687de8..2eb0bec13de88a05df99933683127b60a1dc4f86 100644 (file)
@@ -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));