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.