vim-patch:partial:9.1.2044: Inefficient use of ga_concat() (#37209)

Problem:  Inefficient use of ga_concat()
Solution: Use ga_concat_len() when the length is already known to avoid
          use of strlen() (John Marriott).

Additionally the following changes are done:
os_unix.c:
- in function `socket_server_list_sockets()` use a `string_T` for the
  strings `buf` and `path` for use in `ga_concat_len()`
  and drop un-needed variable `dir`.

quickfix.c:
- in function `qf_jump_print_msg()` use a `string_T` for the string
  `IObuff` for use in `ga_concat_len()`.
- in function `qf_range_text()` use a `string_T` for the string `buf`
  for use in `ga_concat_len()`.

register.c:
- simplify function `execreg_line_continuation()`.

terminal.c:
- in function `read_dump_file()` use a `string_T` for the
  string `prev_char` for use in `ga_concat_len()`.

tuple.c:
- in function `tuple_join_inner()` use a `string_T` for the
  string `s` for use in `ga_concat_len()`. Also, change local struct
  `join_T` to use `string_T`.

vim9type.c:
- in functions `type_name_tuple()` and `type_name_func()`
  use a `string_T` for the string `arg_type` for use in
  `ga_concat_len()`.

closes: vim/vim#19038

a7e671fbb9

Skip tuple.

Co-authored-by: John Marriott <basilisk@internode.on.net>
This commit is contained in:
zeertzjq
2026-01-03 09:54:12 +08:00
committed by GitHub
parent ca731d2e55
commit 147190d8e7
4 changed files with 37 additions and 35 deletions

View File

@@ -333,9 +333,9 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
if (i_ > 0 && (i_ & 3) == 0) { \ if (i_ > 0 && (i_ & 3) == 0) { \
ga_append(gap, '.'); \ ga_append(gap, '.'); \
} \ } \
vim_snprintf((char *)numbuf, ARRAY_SIZE(numbuf), "%02X", \ size_t numbuflen = vim_snprintf_safelen(numbuf, ARRAY_SIZE(numbuf), "%02X", \
(int)tv_blob_get(blob_, i_)); \ (int)tv_blob_get(blob_, i_)); \
ga_concat(gap, numbuf); \ ga_concat_len(gap, numbuf, numbuflen); \
} \ } \
} \ } \
} while (0) } while (0)

View File

@@ -29,6 +29,7 @@
#include "nvim/option_vars.h" #include "nvim/option_vars.h"
#include "nvim/os/fs.h" #include "nvim/os/fs.h"
#include "nvim/pos_defs.h" #include "nvim/pos_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h" #include "nvim/types_defs.h"
#include "nvim/vim_defs.h" #include "nvim/vim_defs.h"
#include "nvim/window.h" #include "nvim/window.h"
@@ -854,12 +855,12 @@ void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (!win_has_winnr(wp, curtab)) { if (!win_has_winnr(wp, curtab)) {
continue; continue;
} }
snprintf(buf, sizeof(buf), "%dresize %d|", winnr, size_t buflen = vim_snprintf_safelen(buf, sizeof(buf),
wp->w_height); "%dresize %d|", winnr, wp->w_height);
ga_concat(&ga, buf); ga_concat_len(&ga, buf, buflen);
snprintf(buf, sizeof(buf), "vert %dresize %d|", winnr, buflen = vim_snprintf_safelen(buf, sizeof(buf),
wp->w_width); "vert %dresize %d|", winnr, wp->w_width);
ga_concat(&ga, buf); ga_concat_len(&ga, buf, buflen);
winnr++; winnr++;
} }
} }

View File

@@ -3077,12 +3077,13 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf
update_screen(); update_screen();
} }
} }
vim_snprintf(IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index, size_t IObufflen = vim_snprintf_safelen(IObuff, IOSIZE,
qf_get_curlist(qi)->qf_count, _("(%d of %d)%s%s: "), qf_index,
qf_ptr->qf_cleared ? _(" (line deleted)") : "", qf_get_curlist(qi)->qf_count,
qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); qf_ptr->qf_cleared ? _(" (line deleted)") : "",
qf_types(qf_ptr->qf_type, qf_ptr->qf_nr));
// Add the message, skipping leading whitespace and newlines. // Add the message, skipping leading whitespace and newlines.
ga_concat(gap, IObuff); ga_concat_len(gap, IObuff, IObufflen);
qf_fmt_text(gap, skipwhite(qf_ptr->qf_text)); qf_fmt_text(gap, skipwhite(qf_ptr->qf_text));
ga_append(gap, NUL); ga_append(gap, NUL);
@@ -3486,26 +3487,24 @@ static void qf_fmt_text(garray_T *gap, const char *restrict text)
/// of a quickfix entry to the grow array "gap". /// of a quickfix entry to the grow array "gap".
static void qf_range_text(garray_T *gap, const qfline_T *qfp) static void qf_range_text(garray_T *gap, const qfline_T *qfp)
{ {
char *const buf = IObuff; String buf = cbuf_as_string(IObuff, 0);
const size_t bufsize = IOSIZE;
vim_snprintf(buf, bufsize, "%" PRIdLINENR, qfp->qf_lnum); buf.size = vim_snprintf_safelen(buf.data, IOSIZE, "%" PRIdLINENR, qfp->qf_lnum);
size_t len = strlen(buf);
if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) { if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) {
vim_snprintf(buf + len, bufsize - len, "-%" PRIdLINENR, qfp->qf_end_lnum); buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
len += strlen(buf + len); "-%" PRIdLINENR, qfp->qf_end_lnum);
} }
if (qfp->qf_col > 0) { if (qfp->qf_col > 0) {
vim_snprintf(buf + len, bufsize - len, " col %d", qfp->qf_col); buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
len += strlen(buf + len); " col %d", qfp->qf_col);
if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col) { if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col) {
vim_snprintf(buf + len, bufsize - len, "-%d", qfp->qf_end_col); buf.size += vim_snprintf_safelen(buf.data + buf.size, IOSIZE - buf.size,
len += strlen(buf + len); "-%d", qfp->qf_end_col);
} }
} }
ga_concat_len(gap, buf, len); ga_concat_len(gap, buf.data, buf.size);
} }
/// Display information (list number, list size and the title) about a /// Display information (list number, list size and the title) about a

View File

@@ -570,9 +570,9 @@ static void put_reedit_in_typebuf(int silent)
/// processed next is returned in idx. /// processed next is returned in idx.
static char *execreg_line_continuation(String *lines, size_t *idx) static char *execreg_line_continuation(String *lines, size_t *idx)
{ {
size_t i = *idx; size_t cmd_start = *idx;
assert(i > 0); assert(cmd_start > 0);
const size_t cmd_end = i; const size_t cmd_end = cmd_start;
garray_T ga; garray_T ga;
ga_init(&ga, (int)sizeof(char), 400); ga_init(&ga, (int)sizeof(char), 400);
@@ -580,32 +580,34 @@ static char *execreg_line_continuation(String *lines, size_t *idx)
// search backwards to find the first line of this command. // search backwards to find the first line of this command.
// Any line not starting with \ or "\ is the start of the // Any line not starting with \ or "\ is the start of the
// command. // command.
while (--i > 0) { while (--cmd_start > 0) {
char *p = skipwhite(lines[i].data); char *p = skipwhite(lines[cmd_start].data);
if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) { if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) {
break; break;
} }
} }
const size_t cmd_start = i;
// join all the lines // join all the lines
ga_concat(&ga, lines[cmd_start].data); String *tmp = &lines[cmd_start];
ga_concat_len(&ga, tmp->data, tmp->size);
for (size_t j = cmd_start + 1; j <= cmd_end; j++) { for (size_t j = cmd_start + 1; j <= cmd_end; j++) {
char *p = skipwhite(lines[j].data); tmp = &lines[j];
char *p = skipwhite(tmp->data);
if (*p == '\\') { if (*p == '\\') {
// Adjust the growsize to the current length to // Adjust the growsize to the current length to
// speed up concatenating many lines. // speed up concatenating many lines.
if (ga.ga_len > 400) { if (ga.ga_len > 400) {
ga_set_growsize(&ga, MIN(ga.ga_len, 8000)); ga_set_growsize(&ga, MIN(ga.ga_len, 8000));
} }
ga_concat(&ga, p + 1); p++;
ga_concat_len(&ga, p, (size_t)(tmp->data + tmp->size - p));
} }
} }
ga_append(&ga, NUL); ga_append(&ga, NUL);
char *str = xmemdupz(ga.ga_data, (size_t)ga.ga_len); char *str = xmemdupz(ga.ga_data, (size_t)ga.ga_len);
ga_clear(&ga); ga_clear(&ga);
*idx = i; *idx = cmd_start;
return str; return str;
} }