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 <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/edit.c b/src/edit.c
index f15a19d..a23f66b 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -78,7 +78,7 @@
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 @@
* 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 @@
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 @@
{
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 @@
void
free_last_insert(void)
{
- VIM_CLEAR(last_insert);
+ VIM_CLEAR_STRING(last_insert);
}
#endif
@@ -2911,13 +2915,11 @@
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,36 +2928,57 @@
// 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' ? "\026\060\064\070" : "\026^"));
+ switch (last)
+ {
+ case '0':
+#define TEXT_TO_INSERT "\026\060\064\070"
+ stuffReadbuffLen((char_u *)TEXT_TO_INSERT, STRLEN_LITERAL(TEXT_TO_INSERT));
+#undef TEXT_TO_INSERT
+ break;
+
+ case '^':
+#define TEXT_TO_INSERT "\026^"
+ stuffReadbuffLen((char_u *)TEXT_TO_INSERT, STRLEN_LITERAL(TEXT_TO_INSERT));
+#undef TEXT_TO_INSERT
+ break;
+
+ default:
+ break;
+ }
}
while (--count > 0);
- if (last)
- *last_ptr = last;
-
- if (esc_ptr != NULL)
- *esc_ptr = ESC; // put the ESC back
-
// may want to stuff a trailing ESC, to get out of Insert mode
if (!no_esc)
stuffcharReadbuff(ESC);
@@ -2963,12 +2986,23 @@
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 @@
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 @@
buf[1] = KS_MODIFIER;
buf[2] = mod_mask;
buf[3] = NUL;
- stuffReadbuff(buf);
+ stuffReadbuffLen(buf, 3L);
}
stuffcharReadbuff(c);
return TRUE;
@@ -5414,6 +5452,7 @@
{
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 @@
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))