patch 9.1.1212: too many strlen() calls in edit.c

Commit: 
https://github.com/vim/vim/commit/34954972c27244a4a1fb4eeeae2aa4e021efd100
Author: John Marriott <basil...@internode.on.net>
Date:   Sun Mar 16 20:49:52 2025 +0100

    patch 9.1.1212: too many strlen() calls in edit.c
    
    Problem:  too many strlen() calls in edit.c
    Solution: refactor edit.c and remove strlen() calls
              (John Marriott)
    
    This commit attempts to make edit.c more efficient by:
    
    - in truncate_spaces() pass in the length of the string.
    - return a string_T from get_last_insert(), so that the length of the
      string is available to the caller.
    - refactor stuff_insert():
    
      - replace calls to stuffReadbuff() (which calls STRLEN() on it's
        string argument) with stuffReadbuffLen() (which gets the length of
        it's string argument passed in).
      - replace call to vim_strrchr() which searches from the start of the
        string with a loop which searches from end of the string to find the
        last ESC character.
    
    - change get_last_insert_save() to call get_last_insert() to get the
      last_insert string (the logic is in one place).
    
    closes: #16863
    
    Signed-off-by: John Marriott <basil...@internode.on.net>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/change.c b/src/change.c
index 9d1b23745..05a6247f3 100644
--- a/src/change.c
+++ b/src/change.c
@@ -2235,7 +2235,7 @@ open_line(
            saved_line[curwin->w_cursor.col] = NUL;
            // Remove trailing white space, unless OPENLINE_KEEPTRAIL used.
            if (trunc_line && !(flags & OPENLINE_KEEPTRAIL))
-               truncate_spaces(saved_line);
+               truncate_spaces(saved_line, curwin->w_cursor.col);
            ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
            saved_line = NULL;
            if (did_append)
diff --git a/src/edit.c b/src/edit.c
index f15a19de2..a23f66bad 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -78,7 +78,7 @@ static colnr_T        Insstart_textlen;       // length of 
line when insert started
 static colnr_T Insstart_blank_vcol;    // vcol for first inserted blank
 static int     update_Insstart_orig = TRUE; // set Insstart_orig to Insstart
 
-static char_u  *last_insert = NULL;    // the text of the previous insert,
+static string_T        last_insert = {NULL, 0};    // the text of the previous 
insert,
                                        // K_SPECIAL and CSI are escaped
 static int     last_insert_skip; // nr of chars in front of previous insert
 static int     new_insert_skip;  // nr of chars in front of current insert
@@ -1809,12 +1809,12 @@ undisplay_dollar(void)
  * MODE_VREPLACE modes.
  */
     void
-truncate_spaces(char_u *line)
+truncate_spaces(char_u *line, size_t len)
 {
     int            i;
 
     // find start of trailing white space
-    for (i = (int)STRLEN(line) - 1; i >= 0 && VIM_ISWHITE(line[i]); i--)
+    for (i = (int)len - 1; i >= 0 && VIM_ISWHITE(line[i]); i--)
     {
        if (State & REPLACE_FLAG)
            replace_join(0);        // remove a NUL from the replace stack
@@ -2455,8 +2455,8 @@ stop_insert(
     int added = inserted.string == NULL ? 0 : (int)inserted.length - 
new_insert_skip;
     if (did_restart_edit == 0 || added > 0)
     {
-       vim_free(last_insert);
-       last_insert = inserted.string;
+       vim_free(last_insert.string);
+       last_insert = inserted;                     // structure copy
        last_insert_skip = added < 0 ? 0 : new_insert_skip;
     }
     else
@@ -2566,18 +2566,22 @@ set_last_insert(int c)
 {
     char_u     *s;
 
-    vim_free(last_insert);
-    last_insert = alloc(MB_MAXBYTES * 3 + 5);
-    if (last_insert == NULL)
+    vim_free(last_insert.string);
+    last_insert.string = alloc(MB_MAXBYTES * 3 + 5);
+    if (last_insert.string == NULL)
+    {
+       last_insert.length = 0;
        return;
+    }
 
-    s = last_insert;
+    s = last_insert.string;
     // Use the CTRL-V only when entering a special char
     if (c < ' ' || c == DEL)
        *s++ = Ctrl_V;
     s = add_char2buf(c, s);
     *s++ = ESC;
-    *s++ = NUL;
+    *s = NUL;
+    last_insert.length = (size_t)(s - last_insert.string);
     last_insert_skip = 0;
 }
 
@@ -2585,7 +2589,7 @@ set_last_insert(int c)
     void
 free_last_insert(void)
 {
-    VIM_CLEAR(last_insert);
+    VIM_CLEAR_STRING(last_insert);
 }
 #endif
 
@@ -2911,13 +2915,11 @@ stuff_inserted(
     long    count,     // Repeat this many times
     int            no_esc)     // Don't add an ESC at the end
 {
-    char_u     *esc_ptr;
-    char_u     *ptr;
-    char_u     *last_ptr;
-    char_u     last = NUL;
+    string_T   *insert;                                    // text to be 
inserted
+    char_u     last = ' ';
 
-    ptr = get_last_insert();
-    if (ptr == NULL)
+    insert = get_last_insert();
+    if (insert->string == NULL)
     {
        emsg(_(e_no_inserted_text_yet));
        return FAIL;
@@ -2926,35 +2928,56 @@ stuff_inserted(
     // may want to stuff the command character, to start Insert mode
     if (c != NUL)
        stuffcharReadbuff(c);
-    if ((esc_ptr = vim_strrchr(ptr, ESC)) != NULL)
-       *esc_ptr = NUL;     // remove the ESC
-
-    // when the last char is either "0" or "^" it will be quoted if no ESC
-    // comes after it OR if it will inserted more than once and "ptr"
-    // starts with ^D. -- Acevedo
-    last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
-    if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
-           && (no_esc || (*ptr == Ctrl_D && count > 1)))
+
+    if (insert->length > 0)
     {
-       last = *last_ptr;
-       *last_ptr = NUL;
+       char_u  *p;
+
+       // look for the last ESC in 'insert'
+       for (p = insert->string + (insert->length - 1); p >= insert->string; 
--p)
+       {
+           if (*p == ESC)
+           {
+               insert->length = (size_t)(p - insert->string);
+               break;
+           }
+       }
+
+       // when the last char is either "0" or "^" it will be quoted if no ESC
+       // comes after it OR if it will insert more than once and "ptr"
+       // starts with ^D.      -- Acevedo
+       if (p >= insert->string
+           && (*p == '0' || *p == '^')
+           && (no_esc || (*insert->string == Ctrl_D && count > 1)))
+       {
+           last = *p;
+           --insert->length;
+       }
     }
 
     do
     {
-       stuffReadbuff(ptr);
+       stuffReadbuffLen(insert->string, insert->length);
        // a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^"
-       if (last)
-           stuffReadbuff(
-                      (char_u *)(last == '0' ? " 048" : " ^"));
-    }
-    while (--count > 0);
+       switch (last)
+       {
+       case '0':
+#define TEXT_TO_INSERT " 048"
+           stuffReadbuffLen((char_u *)TEXT_TO_INSERT, 
STRLEN_LITERAL(TEXT_TO_INSERT));
+#undef TEXT_TO_INSERT
+           break;
 
-    if (last)
-       *last_ptr = last;
+       case '^':
+#define TEXT_TO_INSERT " ^"
+           stuffReadbuffLen((char_u *)TEXT_TO_INSERT, 
STRLEN_LITERAL(TEXT_TO_INSERT));
+#undef TEXT_TO_INSERT
+           break;
 
-    if (esc_ptr != NULL)
-       *esc_ptr = ESC;     // put the ESC back
+       default:
+           break;
+       }
+    }
+    while (--count > 0);
 
     // may want to stuff a trailing ESC, to get out of Insert mode
     if (!no_esc)
@@ -2963,12 +2986,23 @@ stuff_inserted(
     return OK;
 }
 
-    char_u *
+    string_T *
 get_last_insert(void)
 {
-    if (last_insert == NULL)
-       return NULL;
-    return last_insert + last_insert_skip;
+    static string_T insert = {NULL, 0};
+
+    if (last_insert.string == NULL)
+    {
+       insert.string = NULL;
+       insert.length = 0;
+    }
+    else
+    {
+       insert.string = last_insert.string + last_insert_skip;
+       insert.length = (size_t)(last_insert.length - last_insert_skip);
+    }
+
+    return &insert;
 }
 
 /*
@@ -2978,18 +3012,22 @@ get_last_insert(void)
     char_u *
 get_last_insert_save(void)
 {
+    string_T   *insert = get_last_insert();
     char_u     *s;
-    int                len;
 
-    if (last_insert == NULL)
+    if (insert->string == NULL)
        return NULL;
-    len = (int)STRLEN(last_insert + last_insert_skip);
-    s = vim_strnsave(last_insert + last_insert_skip, len);
+    s = vim_strnsave(insert->string, insert->length);
     if (s == NULL)
        return NULL;
 
-    if (len > 0 && s[len - 1] == ESC)  // remove trailing ESC
-       s[len - 1] = NUL;
+    if (insert->length > 0)
+    {
+       // remove trailing ESC
+       --insert->length;
+       if (s[insert->length] == ESC)
+           s[insert->length] = NUL;
+    }
     return s;
 }
 
@@ -3837,7 +3875,7 @@ ins_start_select(int c)
                buf[1] = KS_MODIFIER;
                buf[2] = mod_mask;
                buf[3] = NUL;
-               stuffReadbuff(buf);
+               stuffReadbuffLen(buf, 3L);
            }
            stuffcharReadbuff(c);
            return TRUE;
@@ -5414,6 +5452,7 @@ do_insert_char_pre(int c)
 {
     char_u     *res;
     char_u     buf[MB_MAXBYTES + 1];
+    size_t     buflen;
     int                save_State = State;
 
     // Return quickly when there is nothing to do.
@@ -5424,16 +5463,17 @@ do_insert_char_pre(int c)
        return NULL;
 
     if (has_mbyte)
-       buf[(*mb_char2bytes)(c, buf)] = NUL;
+       buflen = (*mb_char2bytes)(c, buf);
     else
     {
        buf[0] = c;
-       buf[1] = NUL;
+       buflen = 1;
     }
+    buf[buflen] = NUL;
 
     // Lock the text to avoid weird things from happening.
     ++textlock;
-    set_vim_var_string(VV_CHAR, buf, -1);  // set v:char
+    set_vim_var_string(VV_CHAR, buf, buflen);  // set v:char
 
     res = NULL;
     if (ins_apply_autocmds(EVENT_INSERTCHARPRE))
diff --git a/src/getchar.c b/src/getchar.c
index 05ae37393..39e9e786e 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -705,7 +705,7 @@ stuffRedoReadbuff(char_u *s)
     add_buff(&readbuf2, s, -1L);
 }
 
-    static void
+    void
 stuffReadbuffLen(char_u *s, long len)
 {
     add_buff(&readbuf1, s, len);
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
index f9185280e..170ac978c 100644
--- a/src/proto/edit.pro
+++ b/src/proto/edit.pro
@@ -7,7 +7,7 @@ void set_insstart(linenr_T lnum, int col);
 void edit_unputchar(void);
 void display_dollar(colnr_T col_arg);
 void undisplay_dollar(void);
-void truncate_spaces(char_u *line);
+void truncate_spaces(char_u *line, size_t len);
 void backspace_until_column(int col);
 int get_literal(int noReduceKeys);
 void insertchar(int c, int flags, int second_indent);
@@ -24,7 +24,7 @@ int cursor_up(long n, int upd_topline);
 void cursor_down_inner(win_T *wp, long n);
 int cursor_down(long n, int upd_topline);
 int stuff_inserted(int c, long count, int no_esc);
-char_u *get_last_insert(void);
+string_T *get_last_insert(void);
 char_u *get_last_insert_save(void);
 void replace_push(int c);
 int replace_push_mb(char_u *p);
diff --git a/src/proto/getchar.pro b/src/proto/getchar.pro
index 11a37fb1c..d8fcf3fe0 100644
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -15,6 +15,7 @@ void AppendToRedobuffSpec(char_u *s);
 void AppendCharToRedobuff(int c);
 void AppendNumberToRedobuff(long n);
 void stuffReadbuff(char_u *s);
+void stuffReadbuffLen(char_u *s, long len);
 void stuffRedoReadbuff(char_u *s);
 void stuffReadbuffSpec(char_u *s);
 void stuffcharReadbuff(int c);
diff --git a/src/register.c b/src/register.c
index 7ba69be06..1674a1260 100644
--- a/src/register.c
+++ b/src/register.c
@@ -2471,7 +2471,7 @@ ex_display(exarg_T *eap)
     }
 
     // display last inserted text
-    if ((p = get_last_insert()) != NULL
+    if ((p = get_last_insert()->string) != NULL
                  && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
                                                      && !message_filtered(p))
     {

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1ttu9T-00EaXy-MD%40256bit.org.

Raspunde prin e-mail lui