vim-patch:9.1.0798: too many strlen() calls in cmdhist.c (#30895)

Problem:  too many strlen() calls in cmdhist.c
Solution: refactor code and remove strlen() calls
          (John Marriott)

closes: vim/vim#15888

8df07d0ca3

Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
zeertzjq 2024-10-22 13:03:02 +08:00 committed by GitHub
parent 1b9dafa67b
commit ca7855c5ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 30 deletions

View File

@ -221,7 +221,7 @@ static int in_history(int type, const char *str, int move_to_front, int sep)
// well.
char *p = history[type][i].hisstr;
if (strcmp(str, p) == 0
&& (type != HIST_SEARCH || sep == p[strlen(p) + 1])) {
&& (type != HIST_SEARCH || sep == p[history[type][i].hisstrlen + 1])) {
if (!move_to_front) {
return true;
}
@ -239,6 +239,7 @@ static int in_history(int type, const char *str, int move_to_front, int sep)
AdditionalData *ad = history[type][i].additional_data;
char *const save_hisstr = history[type][i].hisstr;
const size_t save_hisstrlen = history[type][i].hisstrlen;
while (i != hisidx[type]) {
if (++i >= hislen) {
i = 0;
@ -249,6 +250,7 @@ static int in_history(int type, const char *str, int move_to_front, int sep)
xfree(ad);
history[type][i].hisnum = ++hisnum[type];
history[type][i].hisstr = save_hisstr;
history[type][i].hisstrlen = save_hisstrlen;
history[type][i].timestamp = os_time();
history[type][i].additional_data = NULL;
return true;
@ -339,6 +341,7 @@ void add_to_history(int histype, const char *new_entry, size_t new_entrylen, boo
hisptr->timestamp = os_time();
hisptr->additional_data = NULL;
hisptr->hisstr[new_entrylen + 1] = (char)sep;
hisptr->hisstrlen = new_entrylen;
hisptr->hisnum = ++hisnum[histype];
if (histype == HIST_SEARCH && in_map) {
@ -400,19 +403,6 @@ static int calc_hist_idx(int histype, int num)
return -1;
}
/// Get a history entry by its index.
///
/// @param histype may be one of the HIST_ values.
static char *get_history_entry(int histype, int idx)
{
idx = calc_hist_idx(histype, idx);
if (idx >= 0) {
return history[histype][idx].hisstr;
} else {
return "";
}
}
/// Clear all entries in a history
///
/// @param[in] histype One of the HIST_ values.
@ -575,10 +565,15 @@ void f_histget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[1].v_type == VAR_UNKNOWN) {
idx = get_history_idx(type);
} else {
idx = (int)tv_get_number_chk(&argvars[1], NULL);
idx = (int)tv_get_number_chk(&argvars[1], NULL); // -1 on type error
}
idx = calc_hist_idx(type, idx);
if (idx < 0) {
rettv->vval.v_string = xstrnsave("", 0);
} else {
rettv->vval.v_string = xstrnsave(history[type][idx].hisstr,
history[type][idx].hisstrlen);
}
// -1 on type error
rettv->vval.v_string = xstrdup(get_history_entry(type, idx));
}
rettv->v_type = VAR_STRING;
}
@ -591,9 +586,10 @@ void f_histnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
? HIST_INVALID
: get_histtype(histname, strlen(histname), false);
if (i != HIST_INVALID) {
i = get_history_idx(i);
rettv->vval.v_number = get_history_idx(i);
} else {
rettv->vval.v_number = HIST_INVALID;
}
rettv->vval.v_number = i;
}
/// :history command - print a history
@ -642,10 +638,8 @@ void ex_history(exarg_T *eap)
}
for (; !got_int && histype1 <= histype2; histype1++) {
xstrlcpy(IObuff, "\n # ", IOSIZE);
assert(history_names[histype1] != NULL);
xstrlcat(IObuff, history_names[histype1], IOSIZE);
xstrlcat(IObuff, " history", IOSIZE);
vim_snprintf(IObuff, IOSIZE, "\n # %s history", history_names[histype1]);
msg_puts_title(IObuff);
int idx = hisidx[histype1];
histentry_T *hist = history[histype1];
@ -666,13 +660,12 @@ void ex_history(exarg_T *eap)
&& hist[i].hisnum >= j && hist[i].hisnum <= k
&& !message_filtered(hist[i].hisstr)) {
msg_putchar('\n');
snprintf(IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ',
hist[i].hisnum);
int len = snprintf(IObuff, IOSIZE,
"%c%6d ", i == idx ? '>' : ' ', hist[i].hisnum);
if (vim_strsize(hist[i].hisstr) > Columns - 10) {
trunc_string(hist[i].hisstr, IObuff + strlen(IObuff),
Columns - 10, IOSIZE - (int)strlen(IObuff));
trunc_string(hist[i].hisstr, IObuff + len, Columns - 10, IOSIZE - len);
} else {
xstrlcat(IObuff, hist[i].hisstr, IOSIZE);
xstrlcpy(IObuff + len, hist[i].hisstr, (size_t)(IOSIZE - len));
}
msg_outtrans(IObuff, 0);
}

View File

@ -23,6 +23,7 @@ enum { HIST_COUNT = HIST_DEBUG + 1, }; ///< Number of history tables
typedef struct {
int hisnum; ///< Entry identifier number.
char *hisstr; ///< Actual entry, separator char after the NUL.
size_t hisstrlen; ///< Length of hisstr (excluding the NUL).
Timestamp timestamp; ///< Time when entry was added.
AdditionalData *additional_data; ///< Additional entries from ShaDa file.
} histentry_T;

View File

@ -4434,11 +4434,11 @@ void ex_global(exarg_T *eap)
delim = *cmd; // get the delimiter
cmd++; // skip delimiter if there is one
pat = cmd; // remember start of pattern
patlen = strlen(pat);
cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delim) { // end delimiter found
*cmd++ = NUL; // replace it with a NUL
}
patlen = strlen(pat);
}
char *used_pat;

View File

@ -1789,7 +1789,7 @@ static int command_line_browse_history(CommandLineState *s)
plen = s->lookforlen;
} else {
p = get_histentry(s->histype)[s->hiscnt].hisstr;
plen = (int)strlen(p);
plen = (int)get_histentry(s->histype)[s->hiscnt].hisstrlen;
}
if (s->histype == HIST_SEARCH

View File

@ -658,7 +658,7 @@ static const void *shada_hist_iter(const void *const iter, const uint8_t history
.histtype = history_type,
.string = hist_he.hisstr,
.sep = (char)(history_type == HIST_SEARCH
? hist_he.hisstr[strlen(hist_he.hisstr) + 1]
? hist_he.hisstr[hist_he.hisstrlen + 1]
: 0),
}
},
@ -784,6 +784,7 @@ static inline void hms_to_he_array(const HistoryMergerState *const hms_p,
hist->timestamp = cur_entry->data.timestamp;
hist->hisnum = (int)(hist - hist_array) + 1;
hist->hisstr = cur_entry->data.data.history_item.string;
hist->hisstrlen = strlen(cur_entry->data.data.history_item.string);
hist->additional_data = cur_entry->data.additional_data;
hist++;
})