Mercurial > vim
changeset 36267:ffffb4aaddb7 draft v9.1.0766
patch 9.1.0766: too many strlen() calls in ex_getln.c
Commit: https://github.com/vim/vim/commit/ccf8907570e14396e265b742e51f5089fdf97bf5
Author: John Marriott <basilisk@internode.on.net>
Date: Mon Oct 7 21:40:39 2024 +0200
patch 9.1.0766: too many strlen() calls in ex_getln.c
Problem: too many strlen() calls in ex_getln.c
Solution: refactor the code to reduce the number of strlen() calls
(John Marriott)
closes: #15809
Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 07 Oct 2024 21:45:03 +0200 |
parents | 0ca47b69259d |
children | 7e6a92a69df8 |
files | src/ex_getln.c src/proto/search.pro src/search.c src/version.c |
diffstat | 4 files changed, 119 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -45,6 +45,7 @@ static int cmdline_charsize(int idx); static void set_cmdspos(void); static void set_cmdspos_cursor(void); static void correct_cmdspos(int idx, int cells); +static void dealloc_cmdbuff(void); static void alloc_cmdbuff(int len); static void draw_cmdline(int start, int len); static void save_cmdline(cmdline_info_T *ccp); @@ -75,7 +76,7 @@ trigger_cmd_autocmd(int typechar, int ev static void abandon_cmdline(void) { - VIM_CLEAR(ccline.cmdbuff); + dealloc_cmdbuff(); if (msg_scrolled == 0) compute_cmdrow(); msg(""); @@ -88,17 +89,16 @@ abandon_cmdline(void) * as a trailing \|, which can happen while typing a pattern. */ static int -empty_pattern(char_u *p, int delim) +empty_pattern(char_u *p, size_t len, int delim) { - size_t n = STRLEN(p); magic_T magic_val = MAGIC_ON; - if (n > 0) + if (len > 0) (void) skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val); else return TRUE; - return empty_pattern_magic(p, n, magic_val); + return empty_pattern_magic(p, len, magic_val); } static int @@ -111,11 +111,14 @@ empty_pattern_magic(char_u *p, size_t le // true, if the pattern is empty, or the pattern ends with \| and magic is // set (or it ends with '|' and very magic is set) - return len == 0 || (len > 1 - && ((p[len - 2] == '\\' - && p[len - 1] == '|' && magic_val == MAGIC_ON) - || (p[len - 2] != '\\' - && p[len - 1] == '|' && magic_val == MAGIC_ALL))); + return len == 0 + || ( + len > 1 && p[len - 1] == '|' + && ( + (p[len - 2] == '\\' && magic_val == MAGIC_ON) || + (p[len - 2] != '\\' && magic_val == MAGIC_ALL) + ) + ); } // Struct to store the viewstate during 'incsearch' highlighting. @@ -323,7 +326,7 @@ do_incsearch_highlighting( int empty; *end = NUL; - empty = empty_pattern_magic(p, STRLEN(p), magic); + empty = empty_pattern_magic(p, (size_t)(end - p), magic); *end = c; if (empty) goto theend; @@ -553,7 +556,7 @@ may_do_incsearch_highlighting( { next_char = ccline.cmdbuff[skiplen + patlen]; ccline.cmdbuff[skiplen + patlen] = NUL; - if (empty_pattern(ccline.cmdbuff + skiplen, search_delim) + if (empty_pattern(ccline.cmdbuff + skiplen, (size_t)patlen, search_delim) && !no_hlsearch) { redraw_all_later(UPD_SOME_VALID); @@ -629,7 +632,7 @@ may_adjust_incsearch_highlighting( return FAIL; } skiplen = 0; - patlen = (int)STRLEN(pat); + patlen = last_search_pattern_len(); } else pat = ccline.cmdbuff + skiplen; @@ -831,9 +834,6 @@ cmdline_handle_ctrl_bsl(int c, int *gote #ifdef FEAT_EVAL if (c == 'e') { - char_u *p = NULL; - int len; - /* * Replace the command line with the result of an expression. * This will call getcmdline() recursively in get_expr_register(). @@ -846,6 +846,8 @@ cmdline_handle_ctrl_bsl(int c, int *gote c = get_expr_register(); if (c == '=') { + char_u *p = NULL; + // Evaluate the expression. Set "textlock" to avoid nasty things // like going to another buffer. ++textlock; @@ -854,7 +856,8 @@ cmdline_handle_ctrl_bsl(int c, int *gote if (p != NULL) { - len = (int)STRLEN(p); + int len = (int)STRLEN(p); + if (realloc_cmdbuff(len + 1) == OK) { ccline.cmdlen = len; @@ -1089,6 +1092,10 @@ cmdline_erase_chars( else if (ccline.cmdlen == 0 && c != Ctrl_W && ccline.cmdprompt == NULL && indent == 0) { +#ifdef FEAT_SEARCH_EXTRA + int cmdlen; +#endif + // In ex and debug mode it doesn't make sense to return. if (exmode_active #ifdef FEAT_EVAL @@ -1097,7 +1104,11 @@ cmdline_erase_chars( ) return CMDLINE_NOT_CHANGED; - VIM_CLEAR(ccline.cmdbuff); // no commandline to return +#ifdef FEAT_SEARCH_EXTRA + cmdlen = ccline.cmdlen; +#endif + dealloc_cmdbuff(); // no commandline to return + if (!cmd_silent) { #ifdef FEAT_RIGHTLEFT @@ -1109,7 +1120,7 @@ cmdline_erase_chars( msg_putchar(' '); // delete ':' } #ifdef FEAT_SEARCH_EXTRA - if (ccline.cmdlen == 0) + if (cmdlen == 0) isp->search_start = isp->save_cursor; #endif redraw_cmdline = TRUE; @@ -1338,30 +1349,29 @@ cmdline_browse_history( int c, int firstc, char_u **curcmdstr, + size_t *curcmdstrlen, int histype, int *hiscnt_p, expand_T *xp) { - int i; - int j; + int orig_hiscnt; + int hiscnt = orig_hiscnt = *hiscnt_p; char_u *lookfor = *curcmdstr; - int hiscnt = *hiscnt_p; + size_t lookforlen = *curcmdstrlen; int res; if (get_hislen() == 0 || firstc == NUL) // no history return CMDLINE_NOT_CHANGED; - i = hiscnt; - // save current command string so it can be restored later if (lookfor == NULL) { - if ((lookfor = vim_strsave(ccline.cmdbuff)) == NULL) + if ((lookfor = vim_strnsave(ccline.cmdbuff, ccline.cmdlen)) == NULL) return CMDLINE_NOT_CHANGED; lookfor[ccline.cmdpos] = NUL; + lookforlen = ccline.cmdpos; } - j = (int)STRLEN(lookfor); for (;;) { // one step backwards @@ -1377,7 +1387,7 @@ cmdline_browse_history( --hiscnt; else // at top of list { - hiscnt = i; + hiscnt = orig_hiscnt; break; } } @@ -1401,33 +1411,44 @@ cmdline_browse_history( if (hiscnt < 0 || get_histentry(histype)[hiscnt].hisstr == NULL) { - hiscnt = i; + hiscnt = orig_hiscnt; break; } if ((c != K_UP && c != K_DOWN) - || hiscnt == i + || hiscnt == orig_hiscnt || STRNCMP(get_histentry(histype)[hiscnt].hisstr, - lookfor, (size_t)j) == 0) + lookfor, lookforlen) == 0) break; } - if (hiscnt != i) // jumped to other entry + if (hiscnt != orig_hiscnt) // jumped to other entry { char_u *p; - int len; - int old_firstc; - - VIM_CLEAR(ccline.cmdbuff); + size_t plen; + int old_firstc; + + dealloc_cmdbuff(); + xp->xp_context = EXPAND_NOTHING; if (hiscnt == get_hislen()) + { p = lookfor; // back to the old one + plen = lookforlen; + } else + { p = get_histentry(histype)[hiscnt].hisstr; + plen = STRLEN(p); + } if (histype == HIST_SEARCH && p != lookfor - && (old_firstc = p[STRLEN(p) + 1]) != firstc) + && (old_firstc = p[plen + 1]) != firstc) { + int i; + int j; + size_t len; + // Correct for the separator character used when // adding the history entry vs the one used now. // First loop: count length. @@ -1472,19 +1493,20 @@ cmdline_browse_history( } } ccline.cmdbuff[len] = NUL; + ccline.cmdpos = ccline.cmdlen = len; } else { - alloc_cmdbuff((int)STRLEN(p)); + alloc_cmdbuff(plen); if (ccline.cmdbuff == NULL) { res = GOTO_NORMAL_MODE; goto done; } STRCPY(ccline.cmdbuff, p); + ccline.cmdpos = ccline.cmdlen = plen; } - ccline.cmdpos = ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); redrawcmd(); res = CMDLINE_CHANGED; goto done; @@ -1494,6 +1516,7 @@ cmdline_browse_history( done: *curcmdstr = lookfor; + *curcmdstrlen = lookforlen; *hiscnt_p = hiscnt; return res; } @@ -1514,9 +1537,12 @@ init_ccline(int firstc, int indent) // alloc initial ccline.cmdbuff alloc_cmdbuff(indent + 50); + ccline.cmdlen = ccline.cmdpos = 0; if (ccline.cmdbuff == NULL) + { + ccline.cmdbufflen = 0; return FAIL; - ccline.cmdlen = ccline.cmdpos = 0; + } ccline.cmdbuff[0] = NUL; sb_text_start_cmdline(); @@ -1576,6 +1602,7 @@ getcmdline_int( int gotesc = FALSE; // TRUE when <ESC> just typed int do_abbr; // when TRUE check for abbr. char_u *lookfor = NULL; // string to match + size_t lookforlen = 0; int hiscnt; // current history line in use int histype; // history type to be used #ifdef FEAT_SEARCH_EXTRA @@ -1866,7 +1893,10 @@ getcmdline_int( && c != K_KPAGEDOWN && c != K_KPAGEUP && c != K_LEFT && c != K_RIGHT && (xpc.xp_numfiles > 0 || (c != Ctrl_P && c != Ctrl_N))) + { VIM_CLEAR(lookfor); + lookforlen = 0; + } /* * When there are matching completions to select <S-Tab> works like @@ -2342,7 +2372,7 @@ getcmdline_int( } else { - res = cmdline_browse_history(c, firstc, &lookfor, histype, + res = cmdline_browse_history(c, firstc, &lookfor, &lookforlen, histype, &hiscnt, &xpc); if (res == CMDLINE_CHANGED) goto cmdline_changed; @@ -2554,14 +2584,12 @@ returncmd: if (ccline.cmdlen && firstc != NUL && (some_key_typed || histype == HIST_SEARCH)) { - size_t cmdbufflen = STRLEN(ccline.cmdbuff); - - add_to_history(histype, ccline.cmdbuff, cmdbufflen, TRUE, + add_to_history(histype, ccline.cmdbuff, ccline.cmdlen, TRUE, histype == HIST_SEARCH ? firstc : NUL); if (firstc == ':') { vim_free(new_last_cmdline); - new_last_cmdline = vim_strnsave(ccline.cmdbuff, cmdbufflen); + new_last_cmdline = vim_strnsave(ccline.cmdbuff, ccline.cmdlen); } } @@ -3289,6 +3317,16 @@ redrawcmd_preedit(void) #endif // FEAT_XIM && FEAT_GUI_GTK /* + * Deallocate a command line buffer, updating the buffer size and length. + */ + static void +dealloc_cmdbuff(void) +{ + VIM_CLEAR(ccline.cmdbuff); + ccline.cmdlen = ccline.cmdbufflen = 0; +} + +/* * Allocate a new command line buffer. * Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen. */ @@ -3315,15 +3353,21 @@ alloc_cmdbuff(int len) realloc_cmdbuff(int len) { char_u *p; + int plen; if (len < ccline.cmdbufflen) return OK; // no need to resize + // Keep a copy of the original cmdbuff and it's size so + // they can be restored/used later. p = ccline.cmdbuff; + plen = ccline.cmdbufflen; + alloc_cmdbuff(len); // will get some more if (ccline.cmdbuff == NULL) // out of memory { ccline.cmdbuff = p; // keep the old one + ccline.cmdbufflen = plen; return FAIL; } // There isn't always a NUL after the command, but it may need to be @@ -4292,7 +4336,8 @@ set_cmdline_str(char_u *str, int pos) return 1; len = (int)STRLEN(str); - realloc_cmdbuff(len + 1); + if (realloc_cmdbuff(len + 1) != OK) + return 1; p->cmdlen = len; STRCPY(p->cmdbuff, str); @@ -4684,21 +4729,30 @@ open_cmdwin(void) cmdwin_result = Ctrl_C; # endif // Set the new command line from the cmdline buffer. - vim_free(ccline.cmdbuff); + dealloc_cmdbuff(); + if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) // :qa[!] typed { - char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!"; + char_u *p = (char_u *)"qa"; // assume cmdwin_result == K_XF2 + size_t plen = 2; + + if (cmdwin_result == K_XF1) + { + p = (char_u *)"qa!"; + plen = 3; + } if (histtype == HIST_CMD) { // Execute the command directly. - ccline.cmdbuff = vim_strsave((char_u *)p); + ccline.cmdbuff = vim_strnsave(p, plen); + ccline.cmdlen = plen; + ccline.cmdbufflen = plen + 1; cmdwin_result = CAR; } else { // First need to cancel what we were doing. - ccline.cmdbuff = NULL; stuffcharReadbuff(':'); stuffReadbuff((char_u *)p); stuffcharReadbuff(CAR); @@ -4711,10 +4765,15 @@ open_cmdwin(void) ccline.cmdbuff = NULL; } else - ccline.cmdbuff = vim_strsave(ml_get_curline()); + { + ccline.cmdlen = ml_get_curline_len(); + ccline.cmdbufflen = ccline.cmdlen + 1; + ccline.cmdbuff = vim_strnsave(ml_get_curline(), ccline.cmdlen); + } + if (ccline.cmdbuff == NULL) { - ccline.cmdbuff = vim_strsave((char_u *)""); + ccline.cmdbuff = vim_strnsave((char_u *)"", 0); ccline.cmdlen = 0; ccline.cmdbufflen = 1; ccline.cmdpos = 0; @@ -4722,8 +4781,6 @@ open_cmdwin(void) } else { - ccline.cmdlen = (int)STRLEN(ccline.cmdbuff); - ccline.cmdbufflen = ccline.cmdlen + 1; ccline.cmdpos = curwin->w_cursor.col; // If the cursor is on the last character, it probably should be // after it.
--- a/src/proto/search.pro +++ b/src/proto/search.pro @@ -8,6 +8,7 @@ void free_search_patterns(void); void save_last_search_pattern(void); void restore_last_search_pattern(void); char_u *last_search_pattern(void); +size_t last_search_pattern_len(void); int ignorecase(char_u *pat); int ignorecase_opt(char_u *pat, int ic_in, int scs); int pat_has_uppercase(char_u *pat);