Skip to content

Commit 8df07d0

Browse files
John Marriottchrisbra
authored andcommitted
patch 9.1.0798: too many strlen() calls in cmdhist.c
Problem: too many strlen() calls in cmdhist.c Solution: refactor code and remove strlen() calls (John Marriott) closes: #15888 Signed-off-by: John Marriott <basilisk@internode.on.net> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 6eca04e commit 8df07d0

6 files changed

Lines changed: 112 additions & 54 deletions

File tree

src/cmdhist.c

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ init_history(void)
125125
{
126126
int newlen; // new length of history table
127127
histentry_T *temp;
128-
int i;
129-
int j;
130128
int type;
131129

132130
// If size of history table changed, reallocate it
@@ -159,11 +157,16 @@ init_history(void)
159157

160158
if (hisidx[type] < 0) // there are no entries yet
161159
{
160+
int i;
161+
162162
for (i = 0; i < newlen; ++i)
163163
clear_hist_entry(&temp[i]);
164164
}
165165
else if (newlen > hislen) // array becomes bigger
166166
{
167+
int i;
168+
int j;
169+
167170
for (i = 0; i <= hisidx[type]; ++i)
168171
temp[i] = history[type][i];
169172
j = i;
@@ -174,13 +177,19 @@ init_history(void)
174177
}
175178
else // array becomes smaller or 0
176179
{
180+
int i;
181+
int j;
182+
177183
j = hisidx[type];
178184
for (i = newlen - 1; ; --i)
179185
{
180186
if (i >= 0) // copy newest entries
181187
temp[i] = history[type][j];
182188
else // remove older entries
189+
{
183190
vim_free(history[type][j].hisstr);
191+
history[type][j].hisstrlen = 0;
192+
}
184193
if (--j < 0)
185194
j = hislen - 1;
186195
if (j == hisidx[type])
@@ -200,6 +209,7 @@ clear_hist_entry(histentry_T *hisptr)
200209
hisptr->hisnum = 0;
201210
hisptr->viminfo = FALSE;
202211
hisptr->hisstr = NULL;
212+
hisptr->hisstrlen = 0;
203213
hisptr->time_set = 0;
204214
}
205215

@@ -218,6 +228,7 @@ in_history(
218228
int i;
219229
int last_i = -1;
220230
char_u *p;
231+
size_t len;
221232

222233
if (hisidx[type] < 0)
223234
return FALSE;
@@ -232,7 +243,7 @@ in_history(
232243
p = history[type][i].hisstr;
233244
if (STRCMP(str, p) == 0
234245
&& !(writing && history[type][i].viminfo)
235-
&& (type != HIST_SEARCH || sep == p[STRLEN(p) + 1]))
246+
&& (type != HIST_SEARCH || sep == p[history[type][i].hisstrlen + 1]))
236247
{
237248
if (!move_to_front)
238249
return TRUE;
@@ -247,6 +258,7 @@ in_history(
247258
return FALSE;
248259

249260
str = history[type][i].hisstr;
261+
len = history[type][i].hisstrlen;
250262
while (i != hisidx[type])
251263
{
252264
if (++i >= hislen)
@@ -257,6 +269,7 @@ in_history(
257269
history[type][i].hisnum = ++hisnum[type];
258270
history[type][i].viminfo = FALSE;
259271
history[type][i].hisstr = str;
272+
history[type][i].hisstrlen = len;
260273
history[type][i].time_set = vim_time();
261274
return TRUE;
262275
}
@@ -337,8 +350,13 @@ add_to_history(
337350

338351
// Store the separator after the NUL of the string.
339352
hisptr->hisstr = vim_strnsave(new_entry, new_entrylen + 2);
340-
if (hisptr->hisstr != NULL)
353+
if (hisptr->hisstr == NULL)
354+
hisptr->hisstrlen = 0;
355+
else
356+
{
341357
hisptr->hisstr[new_entrylen + 1] = sep;
358+
hisptr->hisstrlen = new_entrylen;
359+
}
342360

343361
hisptr->hisnum = ++hisnum[histype];
344362
hisptr->viminfo = FALSE;
@@ -405,20 +423,6 @@ calc_hist_idx(int histype, int num)
405423
return -1;
406424
}
407425

408-
/*
409-
* Get a history entry by its index.
410-
* "histype" may be one of the HIST_ values.
411-
*/
412-
static char_u *
413-
get_history_entry(int histype, int idx)
414-
{
415-
idx = calc_hist_idx(histype, idx);
416-
if (idx >= 0)
417-
return history[histype][idx].hisstr;
418-
else
419-
return (char_u *)"";
420-
}
421-
422426
/*
423427
* Clear all entries of a history.
424428
* "histype" may be one of the HIST_ values.
@@ -517,6 +521,7 @@ del_history_idx(int histype, int idx)
517521
return FALSE;
518522
idx = hisidx[histype];
519523
vim_free(history[histype][i].hisstr);
524+
history[histype][i].hisstrlen = 0;
520525

521526
// When deleting the last added search string in a mapping, reset
522527
// last_maptick, so that the last added search string isn't deleted again.
@@ -576,7 +581,6 @@ f_histadd(typval_T *argvars UNUSED, typval_T *rettv)
576581
f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
577582
{
578583
int n;
579-
char_u buf[NUMBUFLEN];
580584
char_u *str;
581585

582586
if (in_vim9script()
@@ -595,9 +599,14 @@ f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
595599
n = del_history_idx(get_histtype(str),
596600
(int)tv_get_number(&argvars[1]));
597601
else
602+
{
603+
char_u buf[NUMBUFLEN];
604+
598605
// string given: remove all matching entries
599606
n = del_history_entry(get_histtype(str),
600607
tv_get_string_buf(&argvars[1], buf));
608+
}
609+
601610
rettv->vval.v_number = n;
602611
}
603612

@@ -607,9 +616,7 @@ f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
607616
void
608617
f_histget(typval_T *argvars UNUSED, typval_T *rettv)
609618
{
610-
int type;
611-
int idx;
612-
char_u *str;
619+
char_u *str;
613620

614621
if (in_vim9script()
615622
&& (check_for_string_arg(argvars, 0) == FAIL
@@ -621,13 +628,21 @@ f_histget(typval_T *argvars UNUSED, typval_T *rettv)
621628
rettv->vval.v_string = NULL;
622629
else
623630
{
631+
int type;
632+
int idx;
633+
624634
type = get_histtype(str);
625635
if (argvars[1].v_type == VAR_UNKNOWN)
626636
idx = get_history_idx(type);
627637
else
628638
idx = (int)tv_get_number_chk(&argvars[1], NULL);
629639
// -1 on type error
630-
rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
640+
641+
idx = calc_hist_idx(type, idx);
642+
if (idx < 0)
643+
rettv->vval.v_string = vim_strnsave((char_u *)"", 0);
644+
else
645+
rettv->vval.v_string = vim_strnsave(history[type][idx].hisstr, history[type][idx].hisstrlen);
631646
}
632647
rettv->v_type = VAR_STRING;
633648
}
@@ -647,10 +662,9 @@ f_histnr(typval_T *argvars UNUSED, typval_T *rettv)
647662
histname = tv_get_string_chk(&argvars[0]);
648663
i = histname == NULL ? HIST_CMD - 1 : get_histtype(histname);
649664
if (i >= HIST_CMD && i < HIST_COUNT)
650-
i = get_history_idx(i);
665+
rettv->vval.v_number = get_history_idx(i);
651666
else
652-
i = -1;
653-
rettv->vval.v_number = i;
667+
rettv->vval.v_number = -1;
654668
}
655669
#endif // FEAT_EVAL
656670

@@ -662,17 +676,21 @@ f_histnr(typval_T *argvars UNUSED, typval_T *rettv)
662676
void
663677
remove_key_from_history(void)
664678
{
679+
char_u *p_start;
680+
char_u *p_end;
665681
char_u *p;
666682
int i;
667683

668684
i = hisidx[HIST_CMD];
669685
if (i < 0)
670686
return;
671-
p = history[HIST_CMD][i].hisstr;
672-
if (p == NULL)
687+
p_start = history[HIST_CMD][i].hisstr;
688+
if (p_start == NULL)
673689
return;
674690

675-
for ( ; *p; ++p)
691+
p_end = p_start + history[HIST_CMD][i].hisstrlen;
692+
for (p = p_start; *p; ++p)
693+
{
676694
if (STRNCMP(p, "key", 3) == 0 && !SAFE_isalpha(p[3]))
677695
{
678696
p = vim_strchr(p + 3, '=');
@@ -682,9 +700,14 @@ remove_key_from_history(void)
682700
for (i = 0; p[i] && !VIM_ISWHITE(p[i]); ++i)
683701
if (p[i] == '\\' && p[i + 1])
684702
++i;
685-
STRMOVE(p, p + i);
703+
704+
mch_memmove(p, p + i, (p_end - (p + i)) + 1); // +1 for the NUL
705+
p_end -= i; // adjust p_end for shortened string
686706
--p;
687707
}
708+
}
709+
710+
history[HIST_CMD][i].hisstrlen = (size_t)(p_end - p_start);
688711
}
689712
#endif
690713

@@ -750,17 +773,16 @@ ex_history(exarg_T *eap)
750773

751774
for (; !got_int && histype1 <= histype2; ++histype1)
752775
{
753-
STRCPY(IObuff, "\n # ");
754-
STRCAT(STRCAT(IObuff, history_names[histype1]), " history");
776+
vim_snprintf((char *)IObuff, IOSIZE, "\n # %s history", history_names[histype1]);
755777
msg_puts_title((char *)IObuff);
756778
idx = hisidx[histype1];
757779
hist = history[histype1];
758780
j = hisidx1;
759781
k = hisidx2;
760782
if (j < 0)
761-
j = (-j > hislen) ? 0 : hist[(hislen+j+idx+1) % hislen].hisnum;
783+
j = (-j > hislen) ? 0 : hist[(hislen + j + idx + 1) % hislen].hisnum;
762784
if (k < 0)
763-
k = (-k > hislen) ? 0 : hist[(hislen+k+idx+1) % hislen].hisnum;
785+
k = (-k > hislen) ? 0 : hist[(hislen + k + idx + 1) % hislen].hisnum;
764786
if (idx >= 0 && j <= k)
765787
for (i = idx + 1; !got_int; ++i)
766788
{
@@ -770,14 +792,16 @@ ex_history(exarg_T *eap)
770792
&& hist[i].hisnum >= j && hist[i].hisnum <= k
771793
&& !message_filtered(hist[i].hisstr))
772794
{
795+
int len;
796+
773797
msg_putchar('\n');
774-
sprintf((char *)IObuff, "%c%6d ", i == idx ? '>' : ' ',
775-
hist[i].hisnum);
798+
len = vim_snprintf((char *)IObuff, IOSIZE,
799+
"%c%6d ", i == idx ? '>' : ' ', hist[i].hisnum);
776800
if (vim_strsize(hist[i].hisstr) > (int)Columns - 10)
777-
trunc_string(hist[i].hisstr, IObuff + STRLEN(IObuff),
778-
(int)Columns - 10, IOSIZE - (int)STRLEN(IObuff));
801+
trunc_string(hist[i].hisstr, IObuff + len,
802+
(int)Columns - 10, IOSIZE - (int)len);
779803
else
780-
STRCAT(IObuff, hist[i].hisstr);
804+
STRCPY(IObuff + len, hist[i].hisstr);
781805
msg_outtrans(IObuff);
782806
out_flush();
783807
}

src/ex_cmds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5192,10 +5192,10 @@ ex_global(exarg_T *eap)
51925192
delim = *cmd; // get the delimiter
51935193
++cmd; // skip delimiter if there is one
51945194
pat = cmd; // remember start of pattern
5195-
patlen = STRLEN(pat);
51965195
cmd = skip_regexp_ex(cmd, delim, magic_isset(), &eap->arg, NULL, NULL);
51975196
if (cmd[0] == delim) // end delimiter found
51985197
*cmd++ = NUL; // replace it with a NUL
5198+
patlen = STRLEN(pat);
51995199
}
52005200

52015201
if (search_regcomp(pat, patlen, &used_pat, RE_BOTH, which_pat, SEARCH_HIS,

src/ex_getln.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@ cmdline_browse_history(
14301430
else
14311431
{
14321432
p = get_histentry(histype)[hiscnt].hisstr;
1433-
plen = STRLEN(p);
1433+
plen = get_histentry(histype)[hiscnt].hisstrlen;
14341434
}
14351435

14361436
if (histype == HIST_SEARCH

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ typedef struct hist_entry
12831283
int hisnum; // identifying number
12841284
int viminfo; // when TRUE hisstr comes from viminfo
12851285
char_u *hisstr; // actual entry, separator char after the NUL
1286+
size_t hisstrlen; // length of hisstr (excluding the NUL)
12861287
time_t time_set; // when it was typed, zero if unknown
12871288
} histentry_T;
12881289

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
798,
707709
/**/
708710
797,
709711
/**/

0 commit comments

Comments
 (0)