vim-patch:9.1.0766: too many strlen() calls in ex_getln.c (#30715)

Problem:  too many strlen() calls in ex_getln.c
Solution: refactor the code to reduce the number of strlen() calls
          (John Marriott)

closes: vim/vim#15809

ccf8907570

Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
zeertzjq
2024-10-08 08:43:44 +08:00
committed by GitHub
parent 60e1862ccb
commit f659699a26
2 changed files with 56 additions and 35 deletions

View File

@@ -125,6 +125,7 @@ typedef struct {
bool gotesc; // true when <ESC> just typed
int do_abbr; // when true check for abbr.
char *lookfor; // string to match
int lookforlen;
int hiscnt; // current history line in use
int save_hiscnt; // history line before attempting
// to jump to next match
@@ -385,7 +386,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
if (!use_last_pat) {
char c = *end;
*end = NUL;
bool empty = empty_pattern_magic(p, strlen(p), magic);
bool empty = empty_pattern_magic(p, (size_t)(end - p), magic);
*end = c;
if (empty) {
goto theend;
@@ -538,7 +539,8 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
if (!use_last_pat) {
next_char = ccline.cmdbuff[skiplen + patlen];
ccline.cmdbuff[skiplen + patlen] = NUL;
if (empty_pattern(ccline.cmdbuff + skiplen, search_delim) && !no_hlsearch) {
if (empty_pattern(ccline.cmdbuff + skiplen, (size_t)patlen, search_delim)
&& !no_hlsearch) {
redraw_all_later(UPD_SOME_VALID);
set_no_hlsearch(true);
}
@@ -900,12 +902,11 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
&& ccline.cmdlen
&& s->firstc != NUL
&& (s->some_key_typed || s->histype == HIST_SEARCH)) {
size_t cmdbufflen = strlen(ccline.cmdbuff);
add_to_history(s->histype, ccline.cmdbuff, cmdbufflen, true,
add_to_history(s->histype, ccline.cmdbuff, (size_t)ccline.cmdlen, true,
s->histype == HIST_SEARCH ? s->firstc : NUL);
if (s->firstc == ':') {
xfree(new_last_cmdline);
new_last_cmdline = xstrnsave(ccline.cmdbuff, cmdbufflen);
new_last_cmdline = xstrnsave(ccline.cmdbuff, (size_t)ccline.cmdlen);
}
}
@@ -1262,6 +1263,7 @@ static int command_line_execute(VimState *state, int key)
&& s->c != K_LEFT && s->c != K_RIGHT
&& (s->xpc.xp_numfiles > 0 || (s->c != Ctrl_P && s->c != Ctrl_N))) {
XFREE_CLEAR(s->lookfor);
s->lookforlen = 0;
}
// When there are matching completions to select <S-Tab> works like
@@ -1440,7 +1442,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
return FAIL;
}
skiplen = 0;
patlen = (int)strlen(pat);
patlen = (int)last_search_pattern_len();
} else {
pat = ccline.cmdbuff + skiplen;
}
@@ -1574,7 +1576,8 @@ static int command_line_erase_chars(CommandLineState *s)
return CMDLINE_NOT_CHANGED;
}
XFREE_CLEAR(ccline.cmdbuff); // no commandline to return
dealloc_cmdbuff(); // no commandline to return
if (!cmd_silent && !ui_has(kUICmdline)) {
msg_col = 0;
msg_putchar(' '); // delete ':'
@@ -1702,7 +1705,6 @@ static void command_line_left_right_mouse(CommandLineState *s)
static void command_line_next_histidx(CommandLineState *s, bool next_match)
{
int j = (int)strlen(s->lookfor);
while (true) {
// one step backwards
if (!next_match) {
@@ -1746,7 +1748,7 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match)
if ((s->c != K_UP && s->c != K_DOWN)
|| s->hiscnt == s->save_hiscnt
|| strncmp(get_histentry(s->histype)[s->hiscnt].hisstr,
s->lookfor, (size_t)j) == 0) {
s->lookfor, (size_t)s->lookforlen) == 0) {
break;
}
}
@@ -1765,30 +1767,34 @@ static int command_line_browse_history(CommandLineState *s)
// save current command string so it can be restored later
if (s->lookfor == NULL) {
s->lookfor = xstrdup(ccline.cmdbuff);
s->lookfor = xstrnsave(ccline.cmdbuff, (size_t)ccline.cmdlen);
s->lookfor[ccline.cmdpos] = NUL;
s->lookforlen = ccline.cmdpos;
}
bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N
|| s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN);
command_line_next_histidx(s, next_match);
if (s->hiscnt != s->save_hiscnt) {
// jumped to other entry
if (s->hiscnt != s->save_hiscnt) { // jumped to other entry
char *p;
int plen;
int old_firstc;
XFREE_CLEAR(ccline.cmdbuff);
dealloc_cmdbuff();
s->xpc.xp_context = EXPAND_NOTHING;
if (s->hiscnt == get_hislen()) {
p = s->lookfor; // back to the old one
plen = s->lookforlen;
} else {
p = get_histentry(s->histype)[s->hiscnt].hisstr;
plen = (int)strlen(p);
}
if (s->histype == HIST_SEARCH
&& p != s->lookfor
&& (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->firstc) {
&& (old_firstc = (uint8_t)p[plen + 1]) != s->firstc) {
int len = 0;
// Correct for the separator character used when
// adding the history entry vs the one used now.
@@ -1827,12 +1833,13 @@ static int command_line_browse_history(CommandLineState *s)
}
}
ccline.cmdbuff[len] = NUL;
ccline.cmdpos = ccline.cmdlen = len;
} else {
alloc_cmdbuff((int)strlen(p));
alloc_cmdbuff(plen);
STRCPY(ccline.cmdbuff, p);
ccline.cmdpos = ccline.cmdlen = plen;
}
ccline.cmdpos = ccline.cmdlen = (int)strlen(ccline.cmdbuff);
redrawcmd();
return CMDLINE_CHANGED;
}
@@ -2201,18 +2208,17 @@ static int command_line_not_changed(CommandLineState *s)
/// Guess that the pattern matches everything. Only finds specific cases, such
/// as a trailing \|, which can happen while typing a pattern.
static bool empty_pattern(char *p, int delim)
static bool empty_pattern(char *p, size_t len, int delim)
{
size_t n = strlen(p);
magic_T magic_val = MAGIC_ON;
if (n > 0) {
if (len > 0) {
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 bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
@@ -2225,11 +2231,9 @@ static bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
// 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)));
}
handle_T cmdpreview_get_bufnr(void)
@@ -2710,7 +2714,7 @@ static int command_line_changed(CommandLineState *s)
/// Abandon the command line.
static void abandon_cmdline(void)
{
XFREE_CLEAR(ccline.cmdbuff);
dealloc_cmdbuff();
ccline.redraw_state = kCmdRedrawNone;
if (msg_scrolled == 0) {
compute_cmdrow();
@@ -3000,8 +3004,15 @@ bool cmdline_at_end(void)
return (ccline.cmdpos >= ccline.cmdlen);
}
// Allocate a new command line buffer.
// Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
/// Deallocate a command line buffer, updating the buffer size and length.
static void dealloc_cmdbuff(void)
{
XFREE_CLEAR(ccline.cmdbuff);
ccline.cmdlen = ccline.cmdbufflen = 0;
}
/// Allocate a new command line buffer.
/// Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
static void alloc_cmdbuff(int len)
{
// give some extra space to avoid having to allocate all the time
@@ -3023,6 +3034,7 @@ void realloc_cmdbuff(int len)
}
char *p = ccline.cmdbuff;
alloc_cmdbuff(len); // will get some more
// There isn't always a NUL after the command, but it may need to be
// there, thus copy up to the NUL and add a NUL.
@@ -4509,17 +4521,20 @@ static int open_cmdwin(void)
cmdwin_result = Ctrl_C;
}
// Set the new command line from the cmdline buffer.
xfree(ccline.cmdbuff);
dealloc_cmdbuff();
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
size_t plen = (cmdwin_result == K_XF2) ? 2 : 3;
if (histtype == HIST_CMD) {
// Execute the command directly.
ccline.cmdbuff = xstrdup(p);
ccline.cmdbuff = xmemdupz(p, plen);
ccline.cmdlen = (int)plen;
ccline.cmdbufflen = (int)plen + 1;
cmdwin_result = CAR;
} else {
// First need to cancel what we were doing.
ccline.cmdbuff = NULL;
stuffcharReadbuff(':');
stuffReadbuff(p);
stuffcharReadbuff(CAR);
@@ -4529,17 +4544,18 @@ static int open_cmdwin(void)
// and don't modify the cmd window.
ccline.cmdbuff = NULL;
} else {
ccline.cmdbuff = xstrdup(get_cursor_line_ptr());
ccline.cmdlen = get_cursor_line_len();
ccline.cmdbufflen = ccline.cmdlen + 1;
ccline.cmdbuff = xstrnsave(get_cursor_line_ptr(), (size_t)ccline.cmdlen);
}
if (ccline.cmdbuff == NULL) {
ccline.cmdbuff = xstrdup("");
ccline.cmdbuff = xmemdupz("", 0);
ccline.cmdlen = 0;
ccline.cmdbufflen = 1;
ccline.cmdpos = 0;
cmdwin_result = Ctrl_C;
} 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.
if (ccline.cmdpos == ccline.cmdlen - 1 || ccline.cmdpos > ccline.cmdlen) {