patch 9.2.0068: Inefficient use of list_append_string()

Commit: 
https://github.com/vim/vim/commit/455d62e38a75572bccc43e42d20b5db3c4b22ec3
Author: John Marriott <[email protected]>
Date:   Thu Feb 26 21:20:59 2026 +0000

    patch 9.2.0068: Inefficient use of list_append_string()
    
    Problem:  Inefficient use of list_append_string()
    Solution: Pass string length to list_append_string() where it is known
              (John Marriott).
    
    closes: #19491
    
    Signed-off-by: John Marriott <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/clipboard.c b/src/clipboard.c
index 9223e8101..e4650c1b7 100644
--- a/src/clipboard.c
+++ b/src/clipboard.c
@@ -3838,7 +3838,8 @@ clip_provider_copy(char_u *reg, char_u *provider)
     }
 
     for (int i = 0; i < y_ptr->y_size; i++)
-       if (list_append_string(list, y_ptr->y_array[i].string, -1) == FAIL)
+       if (list_append_string(list, y_ptr->y_array[i].string,
+           (int)y_ptr->y_array[i].length) == FAIL)
        {
            free_callback(&callback);
            list_unref(list);
diff --git a/src/evalbuffer.c b/src/evalbuffer.c
index 03d946a0f..29d0f92f8 100644
--- a/src/evalbuffer.c
+++ b/src/evalbuffer.c
@@ -785,8 +785,6 @@ get_buffer_lines(
     int                retlist,
     typval_T   *rettv)
 {
-    char_u     *p;
-
     if (retlist)
     {
        if (rettv_list_alloc(rettv) == FAIL)
@@ -804,10 +802,11 @@ get_buffer_lines(
     if (!retlist)
     {
        if (start >= 1 && start <= buf->b_ml.ml_line_count)
-           p = ml_get_buf(buf, start, FALSE);
+           rettv->vval.v_string =
+               vim_strnsave(ml_get_buf(buf, start, FALSE),
+                   ml_get_buf_len(buf, start));
        else
-           p = (char_u *)"";
-       rettv->vval.v_string = vim_strsave(p);
+           rettv->vval.v_string = vim_strnsave((char_u *)"", 0);
     }
     else
     {
@@ -819,9 +818,13 @@ get_buffer_lines(
        if (end > buf->b_ml.ml_line_count)
            end = buf->b_ml.ml_line_count;
        while (start <= end)
+       {
            if (list_append_string(rettv->vval.v_list,
-                                ml_get_buf(buf, start++, FALSE), -1) == FAIL)
+               ml_get_buf(buf, start, FALSE),
+               (int)ml_get_buf_len(buf, start)) == FAIL)
                break;
+           ++start;
+       }
     }
 }
 
diff --git a/src/evalfunc.c b/src/evalfunc.c
index b4dd971f4..139d940cc 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -6023,24 +6023,25 @@ f_getpos(typval_T *argvars, typval_T *rettv)
 /*
  * Convert from block_def to string
  */
-    static char_u *
-block_def2str(struct block_def *bd)
+    static int
+block_def2str(struct block_def *bd, string_T *ret)
 {
-    char_u *p, *ret;
-    size_t size = bd->startspaces + bd->endspaces + bd->textlen;
-
-    ret = alloc(size + 1);
-    if (ret != NULL)
+    ret->string = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1);
+    if (ret->string == NULL)
     {
-       p = ret;
-       vim_memset(p, ' ', bd->startspaces);
-       p += bd->startspaces;
-       mch_memmove(p, bd->textstart, bd->textlen);
-       p += bd->textlen;
-       vim_memset(p, ' ', bd->endspaces);
-       *(p + bd->endspaces) = NUL;
+       ret->length = 0;
+       return FAIL;
     }
-    return ret;
+
+    vim_memset(ret->string, ' ', bd->startspaces);
+    ret->length = bd->startspaces;
+    mch_memmove(ret->string + ret->length, bd->textstart, bd->textlen);
+    ret->length += bd->textlen;
+    vim_memset(ret->string + ret->length, ' ', bd->endspaces);
+    ret->length += bd->endspaces;
+    ret->string[ret->length] = NUL;
+
+    return OK;
 }
 
     static int
@@ -6221,7 +6222,7 @@ f_getregion(typval_T *argvars, typval_T *rettv)
 
     buf_T              *save_curbuf;
     int                        save_virtual;
-    char_u             *akt = NULL;
+    string_T           akt = {NULL, 0};
     linenr_T           lnum;
 
     save_curbuf = curbuf;
@@ -6233,31 +6234,47 @@ f_getregion(typval_T *argvars, typval_T *rettv)
 
     for (lnum = p1.lnum; lnum <= p2.lnum; lnum++)
     {
-       int ret = 0;
-       struct block_def        bd;
+       int ret = OK;
 
-       if (region_type == MLINE)
-           akt = vim_strsave(ml_get(lnum));
-       else if (region_type == MBLOCK)
+       if (region_type == MBLOCK)
        {
+           struct block_def    bd;
+
            block_prep(&oa, &bd, lnum, FALSE);
-           akt = block_def2str(&bd);
+           block_def2str(&bd, &akt);
+       }
+       else if (region_type == MLINE
+           || (p1.lnum < lnum && lnum < p2.lnum))
+       {
+           string_T    s;
+
+           s.string = ml_get(lnum);
+           s.length = ml_get_len(lnum);
+           akt.string = vim_strnsave(s.string, s.length);
+           if (akt.string == NULL)
+               akt.length = 0;
+           else
+               akt.length = s.length;
        }
-       else if (p1.lnum < lnum && lnum < p2.lnum)
-           akt = vim_strsave(ml_get(lnum));
        else
        {
+           struct block_def    bd;
+
            charwise_block_prep(p1, p2, &bd, lnum, inclusive);
-           akt = block_def2str(&bd);
+           block_def2str(&bd, &akt);
        }
 
-       if (akt)
+       if (akt.string == NULL)
        {
-           ret = list_append_string(rettv->vval.v_list, akt, -1);
-           vim_free(akt);
+           clear_tv(rettv);
+           (void)rettv_list_alloc(rettv);
+           break;
        }
 
-       if (akt == NULL || ret == FAIL)
+       ret = list_append_string(rettv->vval.v_list, akt.string, 
(int)akt.length);
+       vim_free(akt.string);
+
+       if (ret == FAIL)
        {
            clear_tv(rettv);
            (void)rettv_list_alloc(rettv);
@@ -11954,12 +11971,28 @@ f_spellbadword(typval_T *argvars UNUSED, typval_T 
*rettv)
 #endif
 
     list_append_string(rettv->vval.v_list, word, len);
-    list_append_string(rettv->vval.v_list, (char_u *)(
-                       attr == HLF_SPB ? "bad" :
-                       attr == HLF_SPR ? "rare" :
-                       attr == HLF_SPL ? "local" :
-                       attr == HLF_SPC ? "caps" :
-                       ""), -1);
+    switch (attr)
+    {
+    case HLF_SPB:
+       list_append_string(rettv->vval.v_list, (char_u *)"bad", 
STRLEN_LITERAL("bad"));
+       break;
+
+    case HLF_SPR:
+       list_append_string(rettv->vval.v_list, (char_u *)"rare", 
STRLEN_LITERAL("rare"));
+       break;
+
+    case HLF_SPL:
+       list_append_string(rettv->vval.v_list, (char_u *)"local", 
STRLEN_LITERAL("local"));
+       break;
+
+    case HLF_SPC:
+       list_append_string(rettv->vval.v_list, (char_u *)"caps", 
STRLEN_LITERAL("caps"));
+       break;
+
+    default:
+       list_append_string(rettv->vval.v_list, (char_u *)"", 0);
+       break;
+    }
 }
 
 /*
diff --git a/src/evalwindow.c b/src/evalwindow.c
index a08cbf717..53116c7a1 100644
--- a/src/evalwindow.c
+++ b/src/evalwindow.c
@@ -293,14 +293,16 @@ get_framelayout(frame_T *fr, list_T *l, int outer)
     {
        if (fr->fr_win != NULL)
        {
-           list_append_string(fr_list, (char_u *)"leaf", -1);
+           list_append_string(fr_list, (char_u *)"leaf", 
STRLEN_LITERAL("leaf"));
            list_append_number(fr_list, fr->fr_win->w_id);
        }
     }
     else
     {
-       list_append_string(fr_list,
-            fr->fr_layout == FR_ROW ?  (char_u *)"row" : (char_u *)"col", -1);
+       if (fr->fr_layout == FR_ROW)
+           list_append_string(fr_list, (char_u *)"row", STRLEN_LITERAL("row"));
+       else
+           list_append_string(fr_list, (char_u *)"col", STRLEN_LITERAL("col"));
 
        win_list = list_alloc();
        if (win_list == NULL)
diff --git a/src/register.c b/src/register.c
index 1f1739160..1fdebce95 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1097,7 +1097,7 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
 
     // yanked text contents
     for (n = 0; n < reg->y_size; n++)
-       list_append_string(list, reg->y_array[n].string, -1);
+       list_append_string(list, reg->y_array[n].string, 
(int)reg->y_array[n].length);
     list->lv_lock = VAR_FIXED;
     (void)dict_add_list(v_event, "regcontents", list);
 
@@ -2793,17 +2793,17 @@ get_reg_contents(int regname, int flags)
     if (flags & GREG_LIST)
     {
        list_T  *list = list_alloc();
-       int     error = FALSE;
 
        if (list == NULL)
            return NULL;
        for (i = 0; i < y_current->y_size; ++i)
-           if (list_append_string(list, y_current->y_array[i].string, -1) == 
FAIL)
-               error = TRUE;
-       if (error)
        {
-           list_free(list);
-           return NULL;
+           if (list_append_string(list, y_current->y_array[i].string,
+               (int)y_current->y_array[i].length) == FAIL)
+           {
+               list_free(list);
+               return NULL;
+           }
        }
        return (char_u *)list;
     }
diff --git a/src/strings.c b/src/strings.c
index 8b44a2d2b..587085099 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -1197,22 +1197,31 @@ f_charidx(typval_T *argvars, typval_T *rettv)
 /*
  * Convert the string "str", from encoding "from" to encoding "to".
  */
-    static char_u *
-convert_string(char_u *str, char_u *from, char_u *to)
+    static int
+convert_string(string_T *str, char_u *from, char_u *to, string_T *ret)
 {
     vimconv_T  vimconv;
 
     vimconv.vc_type = CONV_NONE;
     if (convert_setup(&vimconv, from, to) == FAIL)
-       return NULL;
+       return FAIL;
     vimconv.vc_fail = TRUE;
     if (vimconv.vc_type == CONV_NONE)
-       str = vim_strsave(str);
+    {
+       ret->string = vim_strnsave(str->string, str->length);
+       if (ret->string == NULL)
+           ret->length = 0;
+       else
+           ret->length = str->length;
+    }
     else
-       str = string_convert(&vimconv, str, NULL);
+    {
+       ret->length = str->length;
+       ret->string = string_convert(&vimconv, str->string, (int 
*)&ret->length);
+    }
     convert_setup(&vimconv, NULL, NULL);
 
-    return str;
+    return (ret->string == NULL) ? FAIL : OK;
 }
 
 /*
@@ -1238,13 +1247,12 @@ blob_from_string(char_u *str, blob_T *blob)
  * allocated string is returned and "start_idx" is moved forward by one byte.
  * On return, "start_idx" points to next byte to process in blob.
  */
-    static char_u *
-string_from_blob(blob_T *blob, long *start_idx)
+    static int
+string_from_blob(blob_T *blob, long *start_idx, string_T *ret)
 {
     garray_T   str_ga;
     long       blen;
     int                idx;
-    char_u     *ret_str = NULL;
 
     ga_init2(&str_ga, sizeof(char), 80);
 
@@ -1266,13 +1274,19 @@ string_from_blob(blob_T *blob, long *start_idx)
     }
 
     if (str_ga.ga_data != NULL)
-       ret_str = vim_strnsave(str_ga.ga_data, str_ga.ga_len);
+    {
+       ret->string = vim_strnsave(str_ga.ga_data, str_ga.ga_len);
+       ret->length = str_ga.ga_len;
+    }
     else
-       ret_str = vim_strsave((char_u *)"");
+    {
+       ret->string = vim_strsave((char_u *)"");
+       ret->length = 0;
+    }
     *start_idx = idx;
 
     ga_clear(&str_ga);
-    return ret_str;
+    return (ret->string == NULL) ? FAIL : OK;
 }
 
 /*
@@ -1320,56 +1334,57 @@ normalize_encoding_name(char_u *enc_skipped)
  */
     static void
 append_converted_string_to_list(
-       char_u *converted,
+       string_T *converted,
        int validate_utf8,
        list_T *list,
        char_u *from_encoding)
 {
-    if (converted != NULL)
+    if (converted->string != NULL)
     {
        // After conversion, the output is a valid UTF-8 string (NUL-terminated)
-       int converted_len = (int)STRLEN(converted);
-
        // Split by newlines and add to list
-       char_u *p = converted;
-       char_u *end = converted + converted_len;
+       char_u *p = converted->string;
+       char_u *end = converted->string + converted->length;
        while (p < end)
        {
-           char_u *line_start = p;
+           string_T    line;
+           char_u      *line_start = p;
+
            while (p < end && *p != NL)
                p++;
 
            // Add this line to the result list
-           char_u *line = vim_strnsave(line_start, p - line_start);
-           if (line != NULL)
+           line.length = (size_t)(p - line_start);
+           line.string = vim_strnsave(line_start, line.length);
+           if (line.string != NULL)
            {
-               if (validate_utf8 && !utf_valid_string(line, NULL))
+               if (validate_utf8 && !utf_valid_string(line.string, NULL))
                {
-                   vim_free(line);
+                   vim_free(line.string);
                    semsg(_(e_str_encoding_from_failed), p_enc);
-                   vim_free(converted);
+                   vim_free(converted->string);
                    return; // Stop processing
                }
-               if (list_append_string(list, line, -1) == FAIL)
+               if (list_append_string(list, line.string, (int)line.length) == 
FAIL)
                {
-                   vim_free(line);
-                   vim_free(converted);
+                   vim_free(line.string);
+                   vim_free(converted->string);
                    return; // Stop processing on append failure
                }
-               vim_free(line);
+               vim_free(line.string);
            }
            else
            {
                // Allocation failure: report error and stop processing
                emsg(_(e_out_of_memory));
-               vim_free(converted);
+               vim_free(converted->string);
                return;
            }
 
            if (*p == NL)
                p++;
        }
-       vim_free(converted);
+       vim_free(converted->string);
     }
     else
     {
@@ -1378,17 +1393,17 @@ append_converted_string_to_list(
 }
 
     static int
-append_validated_line_to_list(char_u *line, int validate_utf8, list_T *list)
+append_validated_line_to_list(string_T *line, int validate_utf8, list_T *list)
 {
-    if (validate_utf8 && !utf_valid_string(line, NULL))
+    if (validate_utf8 && !utf_valid_string(line->string, NULL))
     {
        semsg(_(e_str_encoding_from_failed), p_enc);
-       vim_free(line);
+       vim_free(line->string);
        return FAIL;
     }
 
-    int ret = list_append_string(list, line, -1);
-    vim_free(line);
+    int ret = list_append_string(list, line->string, (int)line->length);
+    vim_free(line->string);
     return ret;
 }
 
@@ -1477,12 +1492,16 @@ f_blob2str(typval_T *argvars, typval_T *rettv)
            goto done;
        }
        vimconv.vc_fail = TRUE;
+
        // Use string_convert_ext with explicit input length
-       int inlen = blen;
-       char_u *converted = string_convert_ext(&vimconv, (char_u 
*)blob_ga.ga_data, &inlen, NULL);
+       string_T    converted;
+
+       converted.length = blen;
+       converted.string =
+           string_convert_ext(&vimconv, (char_u *)blob_ga.ga_data, (int 
*)&converted.length, NULL);
        convert_setup(&vimconv, NULL, NULL);
        ga_clear(&blob_ga);
-       append_converted_string_to_list(converted, validate_utf8, 
rettv->vval.v_list, from_encoding);
+       append_converted_string_to_list(&converted, validate_utf8, 
rettv->vval.v_list, from_encoding);
     }
     else
     {
@@ -1490,27 +1509,29 @@ f_blob2str(typval_T *argvars, typval_T *rettv)
        idx = 0;
        while (idx < blen)
        {
-           char_u      *str;
+           string_T    str;
 
-           str = string_from_blob(blob, &idx);
-           if (str == NULL)
+           if (string_from_blob(blob, &idx, &str) != OK)
                break;
 
            if (from_encoding != NULL)
            {
                // from_encoding_raw is guaranteed non-NULL whenever 
from_encoding != NULL
-               char_u *converted = convert_string(str, from_encoding_raw, 
p_enc);
-               vim_free(str);
-               str = converted;
-           }
+               int         res;
+               string_T    converted;
 
-           if (str == NULL)
-           {
-               semsg(_(e_str_encoding_from_failed), from_encoding);
-               goto done;
+               res = convert_string(&str, from_encoding_raw, p_enc, 
&converted);
+               vim_free(str.string);
+               if (res != OK)
+               {
+                   semsg(_(e_str_encoding_from_failed), from_encoding);
+                   goto done;
+               }
+               str.string = converted.string;
+               str.length = converted.length;
            }
 
-           if (append_validated_line_to_list(str, validate_utf8, 
rettv->vval.v_list) == FAIL)
+           if (append_validated_line_to_list(&str, validate_utf8, 
rettv->vval.v_list) == FAIL)
                goto done;
        }
     }
@@ -1564,29 +1585,39 @@ f_str2blob(typval_T *argvars, typval_T *rettv)
        if (li->li_tv.v_type != VAR_STRING)
            continue;
 
-       char_u  *str = li->li_tv.vval.v_string;
+       string_T    str = {li->li_tv.vval.v_string, 0};
 
-       if (str == NULL)
-           str = (char_u *)"";
+       if (str.string == NULL)
+       {
+           str.string = (char_u *)"";
+           str.length = 0;
+       }
+       else
+           str.length = STRLEN(str.string);
 
        if (to_encoding != NULL)
        {
-           str = convert_string(str, p_enc, to_encoding);
-           if (str == NULL)
+           int         res;
+           string_T    converted;
+
+           res = convert_string(&str, p_enc, to_encoding, &converted);
+           if (res != OK)
            {
                semsg(_(e_str_encoding_to_failed), to_encoding);
                goto done;
            }
+           str.string = converted.string;
+           str.length = converted.length;
        }
 
        if (li != list->lv_first)
            // Each list string item is separated by a newline in the blob
            ga_append(&blob->bv_ga, NL);
 
-       blob_from_string(str, blob);
+       blob_from_string(str.string, blob);
 
        if (to_encoding != NULL)
-           vim_free(str);
+           vim_free(str.string);
     }
 
 done:
diff --git a/src/terminal.c b/src/terminal.c
index 8a479f71d..0753c2892 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -6704,10 +6704,12 @@ f_term_getansicolors(typval_T *argvars, typval_T *rettv)
     state = vterm_obtain_state(term->tl_vterm);
     for (index = 0; index < 16; index++)
     {
+       size_t  hexbuflen;
+
        vterm_state_get_palette_color(state, index, &color);
-       sprintf((char *)hexbuf, "#%02x%02x%02x",
-               color.red, color.green, color.blue);
-       if (list_append_string(list, hexbuf, 7) == FAIL)
+       hexbuflen = vim_snprintf_safelen((char *)hexbuf, sizeof(hexbuf),
+           "#%02x%02x%02x", color.red, color.green, color.blue);
+       if (list_append_string(list, hexbuf, (int)hexbuflen) == FAIL)
            return;
     }
 }
diff --git a/src/version.c b/src/version.c
index d6194a980..c93ea19fb 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    68,
 /**/
     67,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1vvivu-00Ed1x-76%40256bit.org.

Raspunde prin e-mail lui