changeset 35048:f59010300ceb v9.1.0373

patch 9.1.0373: ops.c code uses too many strlen() calls Commit: https://github.com/vim/vim/commit/38b9f45253f582ab63174376e321092f8a9a7808 Author: John Marriott <basilisk@internode.on.net> Date: Thu Apr 25 21:39:18 2024 +0200 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 <basilisk@internode.on.net> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 25 Apr 2024 21:45:06 +0200
parents 6f7c02ee79f5
children 7d7fbe6c25e7
files src/ops.c src/version.c
diffstat 2 files changed, 62 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    373,
+/**/
     372,
 /**/
     371,