]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1212: too many strlen() calls in edit.c
authorJohn Marriott <basilisk@internode.on.net>
Sun, 16 Mar 2025 19:49:52 +0000 (20:49 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 16 Mar 2025 19:49:52 +0000 (20:49 +0100)
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 <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/change.c
src/edit.c
src/getchar.c
src/proto/edit.pro
src/proto/getchar.pro
src/register.c

index 9d1b23745b52d2d6e7baf04745c9bc9240fe7726..05a6247f3141c517d8e51daaef37718953d744d7 100644 (file)
@@ -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)
index f15a19de2cb3df43b870494fbb35d0464bce09ea..a23f66bad5af280a23ed1fcd8d5a6dc5f6532981 100644 (file)
@@ -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' ? "\026\060\064\070" : "\026^"));
-    }
-    while (--count > 0);
+       switch (last)
+       {
+       case '0':
+#define TEXT_TO_INSERT "\026\060\064\070"
+           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 "\026^"
+           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))
index 05ae373933d59eb7759bb454e1a9a27162dee3a3..39e9e786e9d555e5d2f6904919c4a5277f7e264a 100644 (file)
@@ -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);
index f9185280eb1bb39084a08bca41bbb90970c66851..170ac978cb5faa0d96e221064d5806d9ba7de470 100644 (file)
@@ -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);
index 11a37fb1c52e8fedc6e06da897cd3985f9bc9fc6..d8fcf3fe0d342cc360e2fc2c2c9f6b7ab1fb2861 100644 (file)
@@ -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);
index 7ba69be06841e61d9ee8d69df9cf43cef917f41f..1674a1260e844c6a42b873160b044bd55ba652b5 100644 (file)
@@ -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))
     {