From 38b9f45253f582ab63174376e321092f8a9a7808 Mon Sep 17 00:00:00 2001 From: John Marriott Date: Thu, 25 Apr 2024 21:39:18 +0200 Subject: patch 9.1.0373: ops.c code uses too many strlen() calls Problem: ops.c code uses too many strlen() calls Solution: Refactor code and remove more strlen() calls (John Marriott) closes: #14598 Signed-off-by: John Marriott Signed-off-by: Christian Brabandt --- src/ops.c | 107 ++++++++++++++++++++++++++++++++-------------------------- src/version.c | 2 ++ 2 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/ops.c b/src/ops.c index 0ab0d005db..e3e782756e 100644 --- a/src/ops.c +++ b/src/ops.c @@ -281,6 +281,7 @@ shift_block(oparg_T *oap, int amount) int oldstate = State; int total; char_u *newp, *oldp; + size_t newlen, oldlen; int oldcol = curwin->w_cursor.col; int sw_val = (int)get_sw_value_indent(curbuf); int ts_val = (int)curbuf->b_p_ts; @@ -288,7 +289,7 @@ shift_block(oparg_T *oap, int amount) int incr; colnr_T ws_vcol; int added; - unsigned new_line_len; // the length of the line after the + size_t new_line_len; // the length of the line after the // block shift #ifdef FEAT_RIGHTLEFT int old_p_ri = p_ri; @@ -307,6 +308,7 @@ shift_block(oparg_T *oap, int amount) return; // multiplication overflow oldp = ml_get_curline(); + oldlen = ml_get_curline_len(); if (!left) { @@ -369,15 +371,16 @@ shift_block(oparg_T *oap, int amount) // if we're splitting a TAB, allow for it bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); - new_line_len = bd.textcol + tabs + spaces + (int)STRLEN(bd.textstart); + new_line_len = bd.textcol + tabs + spaces + (oldlen - (bd.textstart - oldp)); newp = alloc(new_line_len + 1); if (newp == NULL) return; mch_memmove(newp, oldp, (size_t)bd.textcol); - vim_memset(newp + bd.textcol, TAB, (size_t)tabs); - vim_memset(newp + bd.textcol + tabs, ' ', (size_t)spaces); - // Note that STRMOVE() copies the trailing NUL. - STRMOVE(newp + bd.textcol + tabs + spaces, bd.textstart); + newlen = bd.textcol; + vim_memset(newp + newlen, TAB, (size_t)tabs); + newlen += tabs; + vim_memset(newp + newlen, ' ', (size_t)spaces); + STRCPY(newp + newlen + spaces, bd.textstart); } else // left { @@ -387,11 +390,13 @@ shift_block(oparg_T *oap, int amount) // copied verbatim colnr_T verbatim_copy_width;// the (displayed) width of this part // of line - unsigned fill; // nr of spaces that replace a TAB + size_t fill; // nr of spaces that replace a TAB size_t block_space_width; size_t shift_amount; char_u *non_white = bd.textstart; colnr_T non_white_col; + size_t fixedlen; // length of string left of the shift + // position (ie the string not being shifted) chartabsize_T cts; /* @@ -463,21 +468,27 @@ shift_block(oparg_T *oap, int amount) // - the beginning of the original line up to "verbatim_copy_end", // - "fill" number of spaces, // - the rest of the line, pointed to by non_white. - new_line_len = (unsigned)(verbatim_copy_end - oldp) - + fill - + (unsigned)STRLEN(non_white); + fixedlen = verbatim_copy_end - oldp; + new_line_len = fixedlen + fill + (oldlen - (non_white - oldp)); newp = alloc(new_line_len + 1); if (newp == NULL) return; - mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); - vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); - // Note that STRMOVE() copies the trailing NUL. - STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); + mch_memmove(newp, oldp, fixedlen); + newlen = fixedlen; + vim_memset(newp + newlen, ' ', (size_t)fill); + STRCPY(newp + newlen + fill, non_white); } // replace the line - added = new_line_len - ml_get_curline_len(); ml_replace(curwin->w_cursor.lnum, newp, FALSE); + + // compute the number of bytes added or subtracted. + // note new_line_len and oldlen are unsigned so we have + // to be careful about how we calculate this. + if (new_line_len >= oldlen) + added = (int)(new_line_len - oldlen); + else + added = 0 - (int)(oldlen - new_line_len); inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added); State = oldstate; curwin->w_cursor.col = oldcol; @@ -494,6 +505,7 @@ shift_block(oparg_T *oap, int amount) block_insert( oparg_T *oap, char_u *s, + size_t slen, int b_insert, struct block_def *bdp) { @@ -502,13 +514,11 @@ block_insert( int spaces = 0; // non-zero if cutting a TAB colnr_T offset; // pointer along new line colnr_T startcol; // column where insert starts - unsigned s_len; // STRLEN(s) char_u *newp, *oldp; // new, old lines linenr_T lnum; // loop var int oldstate = State; State = MODE_INSERT; // don't want MODE_REPLACE for State - s_len = (unsigned)STRLEN(s); for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++) { @@ -554,7 +564,7 @@ block_insert( spaces = 0; // Make sure the allocated size matches what is actually copied below. - newp = alloc(ml_get_len(lnum) + spaces + s_len + newp = alloc(ml_get_len(lnum) + spaces + slen + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0) + count + 1); if (newp == NULL) @@ -569,8 +579,8 @@ block_insert( startcol = offset + spaces; // copy the new text - mch_memmove(newp + startcol, s, (size_t)s_len); - offset += s_len; + mch_memmove(newp + startcol, s, slen); + offset += slen; if (spaces > 0 && !bdp->is_short) { @@ -591,13 +601,13 @@ block_insert( if (spaces > 0) offset += count; - STRMOVE(newp + offset, oldp); + STRCPY(newp + offset, oldp); ml_replace(lnum, newp, FALSE); if (b_insert) // correct any text properties - inserted_bytes(lnum, startcol, s_len); + inserted_bytes(lnum, startcol, slen); if (lnum == oap->end.lnum) { @@ -809,8 +819,8 @@ op_delete(oparg_T *oap) vim_memset(newp + bd.textcol, ' ', (size_t)(bd.startspaces + bd.endspaces)); // copy the part after the deleted part - oldp += bd.textcol + bd.textlen; - STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp); + STRCPY(newp + bd.textcol + bd.startspaces + bd.endspaces, + oldp + bd.textcol + bd.textlen); // replace the line ml_replace(lnum, newp, FALSE); @@ -1030,7 +1040,7 @@ op_replace(oparg_T *oap, int c) int n, numc; int num_chars; char_u *newp, *oldp; - size_t oldlen; + size_t newlen, oldlen; struct block_def bd; char_u *after_p = NULL; int had_ctrl_v_cr = FALSE; @@ -1122,9 +1132,10 @@ op_replace(oparg_T *oap, int c) vim_memset(newp, NUL, (size_t)(oldlen + 1 + n)); // copy up to deleted part mch_memmove(newp, oldp, (size_t)bd.textcol); - oldp += bd.textcol + bd.textlen; + newlen = bd.textcol; // insert pre-spaces - vim_memset(newp + bd.textcol, ' ', (size_t)bd.startspaces); + vim_memset(newp + newlen, ' ', (size_t)bd.startspaces); + newlen += bd.startspaces; // insert replacement chars CHECK FOR ALLOCATED SPACE // REPLACE_CR_NCHAR/REPLACE_NL_NCHAR is used for entering CR // literally. @@ -1132,27 +1143,31 @@ op_replace(oparg_T *oap, int c) { if (has_mbyte) { - n = (int)STRLEN(newp); while (--num_chars >= 0) - n += (*mb_char2bytes)(c, newp + n); + newlen += (*mb_char2bytes)(c, newp + newlen); } else - vim_memset(newp + STRLEN(newp), c, (size_t)numc); + { + vim_memset(newp + newlen, c, (size_t)numc); + newlen += numc; + } if (!bd.is_short) { // insert post-spaces - vim_memset(newp + STRLEN(newp), ' ', (size_t)bd.endspaces); + vim_memset(newp + newlen, ' ', (size_t)bd.endspaces); // copy the part after the changed part - STRMOVE(newp + STRLEN(newp), oldp); + STRCPY(newp + newlen + bd.endspaces, + oldp + bd.textcol + bd.textlen); } } else { // Replacing with \r or \n means splitting the line. - after_p = alloc(oldlen + 1 + n - STRLEN(newp)); + after_p = alloc(oldlen + 1 + n - newlen); if (after_p != NULL) - STRMOVE(after_p, oldp); + STRCPY(after_p, oldp + bd.textcol + bd.textlen); } + // replace the line ml_replace(curwin->w_cursor.lnum, newp, FALSE); if (after_p != NULL) @@ -1715,7 +1730,7 @@ op_insert(oparg_T *oap, long count1) // block handled here if (u_save(oap->start.lnum, (linenr_T)(oap->end.lnum + 1)) == OK) - block_insert(oap, ins_text, (oap->op_type == OP_INSERT), + block_insert(oap, ins_text, ins_len, (oap->op_type == OP_INSERT), &bd); curwin->w_cursor.col = oap->start.col; @@ -1736,9 +1751,7 @@ op_change(oparg_T *oap) { colnr_T l; int retval; - long offset; linenr_T linenr; - long ins_len; long pre_textlen = 0; long pre_indent = 0; char_u *firstline; @@ -1798,6 +1811,8 @@ op_change(oparg_T *oap) */ if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int) { + size_t ins_len; + // Auto-indenting may have changed the indent. If the cursor was past // the indent, exclude that indent change from the inserted text. firstline = ml_get(oap->start.lnum); @@ -1816,7 +1831,7 @@ op_change(oparg_T *oap) // copy of the inserted text. if ((ins_text = alloc(ins_len + 1)) != NULL) { - vim_strncpy(ins_text, firstline + bd.textcol, (size_t)ins_len); + vim_strncpy(ins_text, firstline + bd.textcol, ins_len); for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { @@ -1824,6 +1839,7 @@ op_change(oparg_T *oap) if (!bd.is_short || virtual_op) { pos_T vpos; + size_t newlen; // If the block starts in virtual space, count the // initial coladd offset as part of "startspaces" @@ -1835,19 +1851,16 @@ op_change(oparg_T *oap) else vpos.coladd = 0; oldp = ml_get(linenr); - newp = alloc(ml_get_len(linenr) - + vpos.coladd + ins_len + 1); + newp = alloc(ml_get_len(linenr) + vpos.coladd + ins_len + 1); if (newp == NULL) continue; // copy up to block start mch_memmove(newp, oldp, (size_t)bd.textcol); - offset = bd.textcol; - vim_memset(newp + offset, ' ', (size_t)vpos.coladd); - offset += vpos.coladd; - mch_memmove(newp + offset, ins_text, (size_t)ins_len); - offset += ins_len; - oldp += bd.textcol; - STRMOVE(newp + offset, oldp); + newlen = bd.textcol; + vim_memset(newp + newlen, ' ', (size_t)vpos.coladd); + newlen += vpos.coladd; + mch_memmove(newp + newlen, ins_text, ins_len); + STRCPY(newp + newlen + ins_len, oldp + bd.textcol); ml_replace(linenr, newp, FALSE); #ifdef FEAT_PROP_POPUP // Shift the properties for linenr as edit() would do. diff --git a/src/version.c b/src/version.c index 124fb664c3..11e18ede29 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 373, /**/ 372, /**/ -- cgit v1.2.3