mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
vim-patch:partial:9.1.0851: too many strlen() calls in getchar.c (#31230)
Problem: too many strlen() calls in getchar.c
Solution: refactor code and reduce strlen() calls
(John Marriott)
closes: vim/vim#16017
e7a1bbf210
Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
@@ -95,15 +95,15 @@ static FileDescriptor scriptin[NSCRIPT] = { 0 };
|
|||||||
|
|
||||||
#define MINIMAL_SIZE 20 // minimal size for b_str
|
#define MINIMAL_SIZE 20 // minimal size for b_str
|
||||||
|
|
||||||
static buffheader_T redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
static buffheader_T redobuff = { { NULL, 0, { NUL } }, NULL, 0, 0, false };
|
||||||
static buffheader_T old_redobuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
static buffheader_T old_redobuff = { { NULL, 0, { NUL } }, NULL, 0, 0, false };
|
||||||
static buffheader_T recordbuff = { { NULL, { NUL } }, NULL, 0, 0 };
|
static buffheader_T recordbuff = { { NULL, 0, { NUL } }, NULL, 0, 0, false };
|
||||||
|
|
||||||
/// First read ahead buffer. Used for translated commands.
|
/// First read ahead buffer. Used for translated commands.
|
||||||
static buffheader_T readbuf1 = { { NULL, { NUL } }, NULL, 0, 0 };
|
static buffheader_T readbuf1 = { { NULL, 0, { NUL } }, NULL, 0, 0, false };
|
||||||
|
|
||||||
/// Second read ahead buffer. Used for redo.
|
/// Second read ahead buffer. Used for redo.
|
||||||
static buffheader_T readbuf2 = { { NULL, { NUL } }, NULL, 0, 0 };
|
static buffheader_T readbuf2 = { { NULL, 0, { NUL } }, NULL, 0, 0, false };
|
||||||
|
|
||||||
/// Buffer used to store typed characters for vim.on_key().
|
/// Buffer used to store typed characters for vim.on_key().
|
||||||
static kvec_withinit_t(char, MAXMAPLEN + 1) on_key_buf = KVI_INITIAL_VALUE(on_key_buf);
|
static kvec_withinit_t(char, MAXMAPLEN + 1) on_key_buf = KVI_INITIAL_VALUE(on_key_buf);
|
||||||
@@ -183,15 +183,17 @@ static void free_buff(buffheader_T *buf)
|
|||||||
/// K_SPECIAL in the returned string is escaped.
|
/// K_SPECIAL in the returned string is escaped.
|
||||||
///
|
///
|
||||||
/// @param dozero count == zero is not an error
|
/// @param dozero count == zero is not an error
|
||||||
static char *get_buffcont(buffheader_T *buffer, int dozero)
|
/// @param len the length of the returned buffer
|
||||||
|
static char *get_buffcont(buffheader_T *buffer, int dozero, size_t *len)
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
// compute the total length of the string
|
// compute the total length of the string
|
||||||
for (const buffblock_T *bp = buffer->bh_first.b_next;
|
for (const buffblock_T *bp = buffer->bh_first.b_next;
|
||||||
bp != NULL; bp = bp->b_next) {
|
bp != NULL; bp = bp->b_next) {
|
||||||
count += strlen(bp->b_str);
|
count += bp->b_strlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 0 || dozero) {
|
if (count > 0 || dozero) {
|
||||||
@@ -204,7 +206,13 @@ static char *get_buffcont(buffheader_T *buffer, int dozero)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p2 = NUL;
|
*p2 = NUL;
|
||||||
|
i = (size_t)(p2 - p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (len != NULL) {
|
||||||
|
*len = i;
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,12 +221,12 @@ static char *get_buffcont(buffheader_T *buffer, int dozero)
|
|||||||
/// K_SPECIAL in the returned string is escaped.
|
/// K_SPECIAL in the returned string is escaped.
|
||||||
char *get_recorded(void)
|
char *get_recorded(void)
|
||||||
{
|
{
|
||||||
char *p = get_buffcont(&recordbuff, true);
|
size_t len;
|
||||||
|
char *p = get_buffcont(&recordbuff, true, &len);
|
||||||
free_buff(&recordbuff);
|
free_buff(&recordbuff);
|
||||||
|
|
||||||
// Remove the characters that were added the last time, these must be the
|
// Remove the characters that were added the last time, these must be the
|
||||||
// (possibly mapped) characters that stopped the recording.
|
// (possibly mapped) characters that stopped the recording.
|
||||||
size_t len = strlen(p);
|
|
||||||
if (len >= last_recorded_len) {
|
if (len >= last_recorded_len) {
|
||||||
len -= last_recorded_len;
|
len -= last_recorded_len;
|
||||||
p[len] = NUL;
|
p[len] = NUL;
|
||||||
@@ -237,7 +245,7 @@ char *get_recorded(void)
|
|||||||
/// K_SPECIAL in the returned string is escaped.
|
/// K_SPECIAL in the returned string is escaped.
|
||||||
char *get_inserted(void)
|
char *get_inserted(void)
|
||||||
{
|
{
|
||||||
return get_buffcont(&redobuff, false);
|
return get_buffcont(&redobuff, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add string after the current block of the given buffer
|
/// Add string after the current block of the given buffer
|
||||||
@@ -257,27 +265,31 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buf->bh_first.b_next == NULL) { // first add to list
|
if (buf->bh_first.b_next == NULL) { // first add to list
|
||||||
buf->bh_space = 0;
|
|
||||||
buf->bh_curr = &(buf->bh_first);
|
buf->bh_curr = &(buf->bh_first);
|
||||||
|
buf->bh_create_newblock = true;
|
||||||
} else if (buf->bh_curr == NULL) { // buffer has already been read
|
} else if (buf->bh_curr == NULL) { // buffer has already been read
|
||||||
iemsg(_("E222: Add to read buffer"));
|
iemsg(_("E222: Add to read buffer"));
|
||||||
return;
|
return;
|
||||||
} else if (buf->bh_index != 0) {
|
} else if (buf->bh_index != 0) {
|
||||||
memmove(buf->bh_first.b_next->b_str,
|
memmove(buf->bh_first.b_next->b_str,
|
||||||
buf->bh_first.b_next->b_str + buf->bh_index,
|
buf->bh_first.b_next->b_str + buf->bh_index,
|
||||||
strlen(buf->bh_first.b_next->b_str + buf->bh_index) + 1);
|
(buf->bh_first.b_next->b_strlen - buf->bh_index) + 1);
|
||||||
|
buf->bh_first.b_next->b_strlen -= buf->bh_index;
|
||||||
|
buf->bh_space += buf->bh_index;
|
||||||
}
|
}
|
||||||
buf->bh_index = 0;
|
buf->bh_index = 0;
|
||||||
|
|
||||||
if (buf->bh_space >= (size_t)slen) {
|
if (!buf->bh_create_newblock && buf->bh_space >= (size_t)slen) {
|
||||||
size_t len = strlen(buf->bh_curr->b_str);
|
xmemcpyz(buf->bh_curr->b_str + buf->bh_curr->b_strlen, s, (size_t)slen);
|
||||||
xmemcpyz(buf->bh_curr->b_str + len, s, (size_t)slen);
|
buf->bh_curr->b_strlen += (size_t)slen;
|
||||||
buf->bh_space -= (size_t)slen;
|
buf->bh_space -= (size_t)slen;
|
||||||
} else {
|
} else {
|
||||||
size_t len = MAX(MINIMAL_SIZE, (size_t)slen);
|
size_t len = MAX(MINIMAL_SIZE, (size_t)slen);
|
||||||
buffblock_T *p = xmalloc(offsetof(buffblock_T, b_str) + len + 1);
|
buffblock_T *p = xmalloc(offsetof(buffblock_T, b_str) + len + 1);
|
||||||
buf->bh_space = len - (size_t)slen;
|
|
||||||
xmemcpyz(p->b_str, s, (size_t)slen);
|
xmemcpyz(p->b_str, s, (size_t)slen);
|
||||||
|
p->b_strlen = (size_t)slen;
|
||||||
|
buf->bh_space = len - (size_t)slen;
|
||||||
|
buf->bh_create_newblock = false;
|
||||||
|
|
||||||
p->b_next = buf->bh_curr->b_next;
|
p->b_next = buf->bh_curr->b_next;
|
||||||
buf->bh_curr->b_next = p;
|
buf->bh_curr->b_next = p;
|
||||||
@@ -292,12 +304,12 @@ static void delete_buff_tail(buffheader_T *buf, int slen)
|
|||||||
if (buf->bh_curr == NULL) {
|
if (buf->bh_curr == NULL) {
|
||||||
return; // nothing to delete
|
return; // nothing to delete
|
||||||
}
|
}
|
||||||
int len = (int)strlen(buf->bh_curr->b_str);
|
if (buf->bh_curr->b_strlen < (size_t)slen) {
|
||||||
if (len < slen) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->bh_curr->b_str[len - slen] = NUL;
|
buf->bh_curr->b_str[buf->bh_curr->b_strlen - (size_t)slen] = NUL;
|
||||||
|
buf->bh_curr->b_strlen -= (size_t)slen;
|
||||||
buf->bh_space += (size_t)slen;
|
buf->bh_space += (size_t)slen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,8 +317,8 @@ static void delete_buff_tail(buffheader_T *buf, int slen)
|
|||||||
static void add_num_buff(buffheader_T *buf, int n)
|
static void add_num_buff(buffheader_T *buf, int n)
|
||||||
{
|
{
|
||||||
char number[32];
|
char number[32];
|
||||||
snprintf(number, sizeof(number), "%d", n);
|
int numberlen = snprintf(number, sizeof(number), "%d", n);
|
||||||
add_buff(buf, number, -1);
|
add_buff(buf, number, numberlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add byte or special key 'c' to buffer "buf".
|
/// Add byte or special key 'c' to buffer "buf".
|
||||||
@@ -314,17 +326,20 @@ static void add_num_buff(buffheader_T *buf, int n)
|
|||||||
static void add_byte_buff(buffheader_T *buf, int c)
|
static void add_byte_buff(buffheader_T *buf, int c)
|
||||||
{
|
{
|
||||||
char temp[4];
|
char temp[4];
|
||||||
|
ptrdiff_t templen;
|
||||||
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
|
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
|
||||||
// Translate special key code into three byte sequence.
|
// Translate special key code into three byte sequence.
|
||||||
temp[0] = (char)K_SPECIAL;
|
temp[0] = (char)K_SPECIAL;
|
||||||
temp[1] = (char)K_SECOND(c);
|
temp[1] = (char)K_SECOND(c);
|
||||||
temp[2] = (char)K_THIRD(c);
|
temp[2] = (char)K_THIRD(c);
|
||||||
temp[3] = NUL;
|
temp[3] = NUL;
|
||||||
|
templen = 3;
|
||||||
} else {
|
} else {
|
||||||
temp[0] = (char)c;
|
temp[0] = (char)c;
|
||||||
temp[1] = NUL;
|
temp[1] = NUL;
|
||||||
|
templen = 1;
|
||||||
}
|
}
|
||||||
add_buff(buf, temp, -1);
|
add_buff(buf, temp, templen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add character 'c' to buffer "buf".
|
/// Add character 'c' to buffer "buf".
|
||||||
@@ -385,11 +400,11 @@ static void start_stuff(void)
|
|||||||
{
|
{
|
||||||
if (readbuf1.bh_first.b_next != NULL) {
|
if (readbuf1.bh_first.b_next != NULL) {
|
||||||
readbuf1.bh_curr = &(readbuf1.bh_first);
|
readbuf1.bh_curr = &(readbuf1.bh_first);
|
||||||
readbuf1.bh_space = 0;
|
readbuf1.bh_create_newblock = true; // force a new block to be created (see add_buff())
|
||||||
}
|
}
|
||||||
if (readbuf2.bh_first.b_next != NULL) {
|
if (readbuf2.bh_first.b_next != NULL) {
|
||||||
readbuf2.bh_curr = &(readbuf2.bh_first);
|
readbuf2.bh_curr = &(readbuf2.bh_first);
|
||||||
readbuf2.bh_space = 0;
|
readbuf2.bh_create_newblock = true; // force a new block to be created (see add_buff())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,12 +513,13 @@ void saveRedobuff(save_redo_T *save_redo)
|
|||||||
old_redobuff.bh_first.b_next = NULL;
|
old_redobuff.bh_first.b_next = NULL;
|
||||||
|
|
||||||
// Make a copy, so that ":normal ." in a function works.
|
// Make a copy, so that ":normal ." in a function works.
|
||||||
char *const s = get_buffcont(&save_redo->sr_redobuff, false);
|
size_t slen;
|
||||||
|
char *const s = get_buffcont(&save_redo->sr_redobuff, false, &slen);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_buff(&redobuff, s, -1);
|
add_buff(&redobuff, s, (ptrdiff_t)slen);
|
||||||
xfree(s);
|
xfree(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1921,9 +1937,9 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
|
|||||||
i += utf_char2bytes((int)n, temp + i);
|
i += utf_char2bytes((int)n, temp + i);
|
||||||
}
|
}
|
||||||
assert(i < 10);
|
assert(i < 10);
|
||||||
temp[i++] = NUL;
|
temp[i] = NUL;
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = xstrdup(temp);
|
rettv->vval.v_string = xmemdupz(temp, (size_t)i);
|
||||||
|
|
||||||
if (is_mouse_key((int)n)) {
|
if (is_mouse_key((int)n)) {
|
||||||
int row = mouse_row;
|
int row = mouse_row;
|
||||||
@@ -1976,9 +1992,9 @@ void f_getcharstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
i += utf_char2bytes((int)n, temp);
|
i += utf_char2bytes((int)n, temp);
|
||||||
}
|
}
|
||||||
assert(i < 7);
|
assert(i < 7);
|
||||||
temp[i++] = NUL;
|
temp[i] = NUL;
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = xstrdup(temp);
|
rettv->vval.v_string = xmemdupz(temp, (size_t)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "getcharmod()" function
|
/// "getcharmod()" function
|
||||||
@@ -2373,7 +2389,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
|
|||||||
buf[1] = (char)KS_EXTRA;
|
buf[1] = (char)KS_EXTRA;
|
||||||
buf[2] = KE_IGNORE;
|
buf[2] = KE_IGNORE;
|
||||||
buf[3] = NUL;
|
buf[3] = NUL;
|
||||||
map_str = xstrdup(buf);
|
map_str = xmemdupz(buf, 3);
|
||||||
if (State & MODE_CMDLINE) {
|
if (State & MODE_CMDLINE) {
|
||||||
// redraw the command below the error
|
// redraw the command below the error
|
||||||
msg_didout = true;
|
msg_didout = true;
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
/// structure used to store one block of the stuff/redo/recording buffers
|
/// structure used to store one block of the stuff/redo/recording buffers
|
||||||
typedef struct buffblock {
|
typedef struct buffblock {
|
||||||
struct buffblock *b_next; ///< pointer to next buffblock
|
struct buffblock *b_next; ///< pointer to next buffblock
|
||||||
|
size_t b_strlen; ///< length of b_str, excluding the NUL
|
||||||
char b_str[1]; ///< contents (actually longer)
|
char b_str[1]; ///< contents (actually longer)
|
||||||
} buffblock_T;
|
} buffblock_T;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ typedef struct {
|
|||||||
buffblock_T *bh_curr; ///< buffblock for appending
|
buffblock_T *bh_curr; ///< buffblock for appending
|
||||||
size_t bh_index; ///< index for reading
|
size_t bh_index; ///< index for reading
|
||||||
size_t bh_space; ///< space in bh_curr for appending
|
size_t bh_space; ///< space in bh_curr for appending
|
||||||
|
bool bh_create_newblock; ///< create a new block?
|
||||||
} buffheader_T;
|
} buffheader_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Reference in New Issue
Block a user