aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-11-01 17:34:19 +0800
committerGitHub <noreply@github.com>2024-11-01 09:34:19 +0000
commitcbd8b2c1622e0c1cb4d38b65730e259eb6c100df (patch)
tree3300c416bd92aa912fcb2084853130d1f758331e
parent9b357e30fdd0a575480182872331fdb87e9cc331 (diff)
downloadrneovim-cbd8b2c1622e0c1cb4d38b65730e259eb6c100df.tar.gz
rneovim-cbd8b2c1622e0c1cb4d38b65730e259eb6c100df.tar.bz2
rneovim-cbd8b2c1622e0c1cb4d38b65730e259eb6c100df.zip
vim-patch:9.1.0824: too many strlen() calls in register.c (#31022)
Problem: too many strlen() calls in register.c Solution: refactor code, add string_T struct to keep track of string lengths (John Marriott) closes: vim/vim#15952 https://github.com/vim/vim/commit/79f6ffd388299ef3b1c95cbe658785e6e66df144 Co-authored-by: John Marriott <basilisk@internode.on.net>
-rw-r--r--src/nvim/api/private/helpers.h6
-rw-r--r--src/nvim/api/vim.c6
-rw-r--r--src/nvim/ops.c246
-rw-r--r--src/nvim/ops.h2
-rw-r--r--src/nvim/shada.c10
-rw-r--r--src/nvim/terminal.c8
6 files changed, 152 insertions, 126 deletions
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 57932e067e..d06f5c9c65 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -111,6 +111,12 @@ typedef kvec_withinit_t(Object, 16) ArrayBuilder;
#define STATIC_CSTR_AS_OBJ(s) STRING_OBJ(STATIC_CSTR_AS_STRING(s))
#define STATIC_CSTR_TO_OBJ(s) STRING_OBJ(STATIC_CSTR_TO_STRING(s))
+#define API_CLEAR_STRING(s) \
+ do { \
+ XFREE_CLEAR(s.data); \
+ s.size = 0; \
+ } while (0)
+
// Helpers used by the generated msgpack-rpc api wrappers
#define api_init_boolean
#define api_init_integer
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 8c88a19147..943c67ac8e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1317,15 +1317,15 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
return; // Nothing to do.
}
- reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
+ reg->y_array = arena_alloc(arena, lines.size * sizeof(String), true);
reg->y_size = lines.size;
for (size_t i = 0; i < lines.size; i++) {
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
return;
});
String line = lines.items[i].data.string;
- reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
- memchrsub(reg->y_array[i], NUL, NL, line.size);
+ reg->y_array[i] = copy_string(line, arena);
+ memchrsub(reg->y_array[i].data, NUL, NL, line.size);
}
finish_yankreg_from_object(reg, false);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 8faf0a6b47..1705c8b648 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -12,6 +12,7 @@
#include <uv.h>
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
@@ -841,9 +842,9 @@ yankreg_T *copy_register(int name)
if (copy->y_size == 0) {
copy->y_array = NULL;
} else {
- copy->y_array = xcalloc(copy->y_size, sizeof(char *));
+ copy->y_array = xcalloc(copy->y_size, sizeof(String));
for (size_t i = 0; i < copy->y_size; i++) {
- copy->y_array[i] = xstrdup(reg->y_array[i]);
+ copy->y_array[i] = copy_string(reg->y_array[i], NULL);
}
}
return copy;
@@ -946,23 +947,24 @@ static int stuff_yank(int regname, char *p)
xfree(p);
return OK;
}
+
+ const size_t plen = strlen(p);
yankreg_T *reg = get_yank_register(regname, YREG_YANK);
if (is_append_register(regname) && reg->y_array != NULL) {
- char **pp = &(reg->y_array[reg->y_size - 1]);
- const size_t ppl = strlen(*pp);
- const size_t pl = strlen(p);
- char *lp = xmalloc(ppl + pl + 1);
- memcpy(lp, *pp, ppl);
- memcpy(lp + ppl, p, pl);
- *(lp + ppl + pl) = NUL;
+ String *pp = &(reg->y_array[reg->y_size - 1]);
+ const size_t tmplen = pp->size + plen;
+ char *tmp = xmalloc(tmplen + 1);
+ memcpy(tmp, pp->data, pp->size);
+ memcpy(tmp + pp->size, p, plen);
+ *(tmp + tmplen) = NUL;
xfree(p);
- xfree(*pp);
- *pp = lp;
+ xfree(pp->data);
+ *pp = cbuf_as_string(tmp, tmplen);
} else {
free_register(reg);
reg->additional_data = NULL;
- reg->y_array = xmalloc(sizeof(char *));
- reg->y_array[0] = p;
+ reg->y_array = xmalloc(sizeof(String));
+ reg->y_array[0] = cbuf_as_string(p, plen);
reg->y_size = 1;
reg->y_type = kMTCharWise;
}
@@ -983,7 +985,7 @@ static int execreg_lastc = NUL;
/// with a \. Lines that start with a comment "\ character are ignored.
/// @returns the concatenated line. The index of the line that should be
/// processed next is returned in idx.
-static char *execreg_line_continuation(char **lines, size_t *idx)
+static char *execreg_line_continuation(String *lines, size_t *idx)
{
size_t i = *idx;
assert(i > 0);
@@ -996,7 +998,7 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
// Any line not starting with \ or "\ is the start of the
// command.
while (--i > 0) {
- char *p = skipwhite(lines[i]);
+ char *p = skipwhite(lines[i].data);
if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) {
break;
}
@@ -1004,9 +1006,9 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
const size_t cmd_start = i;
// join all the lines
- ga_concat(&ga, lines[cmd_start]);
+ ga_concat(&ga, lines[cmd_start].data);
for (size_t j = cmd_start + 1; j <= cmd_end; j++) {
- char *p = skipwhite(lines[j]);
+ char *p = skipwhite(lines[j].data);
if (*p == '\\') {
// Adjust the growsize to the current length to
// speed up concatenating many lines.
@@ -1017,7 +1019,7 @@ static char *execreg_line_continuation(char **lines, size_t *idx)
}
}
ga_append(&ga, NUL);
- char *str = xstrdup(ga.ga_data);
+ char *str = xmemdupz(ga.ga_data, (size_t)ga.ga_len);
ga_clear(&ga);
*idx = i;
@@ -1110,7 +1112,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
}
// Handle line-continuation for :@<register>
- char *str = reg->y_array[i];
+ char *str = reg->y_array[i].data;
bool free_str = false;
if (colon && i > 0) {
char *p = skipwhite(str);
@@ -1248,7 +1250,7 @@ int insert_reg(int regname, bool literally_arg)
if (u_save_cursor() == FAIL) {
return FAIL;
}
- del_chars(mb_charlen(reg->y_array[0]), true);
+ del_chars(mb_charlen(reg->y_array[0].data), true);
curpos = curwin->w_cursor;
if (oneright() == FAIL) {
// hit end of line, need to put forward (after the current position)
@@ -1261,7 +1263,7 @@ int insert_reg(int regname, bool literally_arg)
AppendCharToRedobuff(regname);
do_put(regname, NULL, dir, 1, PUT_CURSEND);
} else {
- stuffescaped(reg->y_array[i], literally);
+ stuffescaped(reg->y_array[i].data, literally);
}
// Insert a newline between lines and after last line if
// y_type is kMTLineWise.
@@ -1384,7 +1386,7 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
}
for (size_t i = 0; i < reg->y_size; i++) {
- cmdline_paste_str(reg->y_array[i], literally);
+ cmdline_paste_str(reg->y_array[i].data, literally);
// Insert ^M between lines, unless `remcr` is true.
if (i < reg->y_size - 1 && !remcr) {
@@ -2504,7 +2506,7 @@ void free_register(yankreg_T *reg)
}
for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
- xfree(reg->y_array[i]);
+ API_CLEAR_STRING(reg->y_array[i]);
}
XFREE_CLEAR(reg->y_array);
}
@@ -2533,7 +2535,6 @@ bool op_yank(oparg_T *oap, bool message)
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
set_clipboard(oap->regname, reg);
do_autocmd_textyankpost(oap, reg);
-
return true;
}
@@ -2569,7 +2570,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
reg->y_size = yanklines;
reg->y_type = yank_type; // set the yank register type
reg->y_width = 0;
- reg->y_array = xcalloc(yanklines, sizeof(char *));
+ reg->y_array = xcalloc(yanklines, sizeof(String));
reg->additional_data = NULL;
reg->timestamp = os_time();
@@ -2593,11 +2594,16 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
break;
case kMTLineWise:
- reg->y_array[y_idx] = xstrdup(ml_get(lnum));
+ reg->y_array[y_idx] = cbuf_to_string(ml_get(lnum), (size_t)ml_get_len(lnum));
break;
case kMTCharWise:
charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive);
+ // make sure bd.textlen is not longer than the text
+ int tmp = (int)strlen(bd.textstart);
+ if (tmp < bd.textlen) {
+ bd.textlen = tmp;
+ }
yank_copy_line(reg, &bd, y_idx, false);
break;
@@ -2609,7 +2615,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
if (curr != reg) { // append the new block to the old block
size_t j;
- char **new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size));
+ String *new_ptr = xmalloc(sizeof(String) * (curr->y_size + reg->y_size));
for (j = 0; j < curr->y_size; j++) {
new_ptr[j] = curr->y_array[j];
}
@@ -2625,13 +2631,16 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
// the new block, unless being Vi compatible.
if (curr->y_type == kMTCharWise
&& vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) {
- char *pnew = xmalloc(strlen(curr->y_array[curr->y_size - 1])
- + strlen(reg->y_array[0]) + 1);
- STRCPY(pnew, curr->y_array[--j]);
- strcat(pnew, reg->y_array[0]);
- xfree(curr->y_array[j]);
- xfree(reg->y_array[0]);
- curr->y_array[j++] = pnew;
+ char *pnew = xmalloc(curr->y_array[curr->y_size - 1].size
+ + reg->y_array[0].size + 1);
+ j--;
+ STRCPY(pnew, curr->y_array[j].data);
+ STRCPY(pnew + curr->y_array[j].size, reg->y_array[0].data);
+ xfree(curr->y_array[j].data);
+ curr->y_array[j] = cbuf_as_string(pnew,
+ curr->y_array[j].size + reg->y_array[0].size);
+ j++;
+ API_CLEAR_STRING(reg->y_array[0]);
y_idx = 1;
} else {
y_idx = 0;
@@ -2698,7 +2707,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
int size = bd->startspaces + bd->endspaces + bd->textlen;
assert(size >= 0);
char *pnew = xmallocz((size_t)size);
- reg->y_array[y_idx] = pnew;
+ reg->y_array[y_idx].data = pnew;
memset(pnew, ' ', (size_t)bd->startspaces);
pnew += bd->startspaces;
memmove(pnew, bd->textstart, (size_t)bd->textlen);
@@ -2714,6 +2723,7 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx,
}
}
*pnew = NUL;
+ reg->y_array[y_idx].size = (size_t)(pnew - reg->y_array[y_idx].data);
}
/// Execute autocommands for TextYankPost.
@@ -2739,7 +2749,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
// The yanked text contents.
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
for (size_t i = 0; i < reg->y_size; i++) {
- tv_list_append_string(list, reg->y_array[i], -1);
+ tv_list_append_string(list, reg->y_array[i].data, -1);
}
tv_list_set_lock(list, VAR_FIXED);
tv_dict_add_list(dict, S_LEN("regcontents"), list);
@@ -2792,25 +2802,13 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
size_t y_size;
int y_width = 0;
colnr_T vcol = 0;
- int incr = 0;
- struct block_def bd;
- char **y_array = NULL;
+ String *y_array = NULL;
linenr_T nr_lines = 0;
- int indent;
- int orig_indent = 0; // init for gcc
- int indent_diff = 0; // init for gcc
- bool first_indent = true;
- int lendiff = 0;
- char *insert_string = NULL;
bool allocated = false;
const pos_T orig_start = curbuf->b_op_start;
const pos_T orig_end = curbuf->b_op_end;
unsigned cur_ve_flags = get_ve_flags(curwin);
- if (flags & PUT_FIXINDENT) {
- orig_indent = get_indent();
- }
-
curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
curbuf->b_op_end = curwin->w_cursor; // default for '] mark
@@ -2898,8 +2896,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// For special registers '%' (file name), '#' (alternate file name) and
// ':' (last command line), etc. we have to create a fake yank register.
- if (!reg && get_spec_reg(regname, &insert_string, &allocated, true)) {
- if (insert_string == NULL) {
+ String insert_string = STRING_INIT;
+ if (!reg && get_spec_reg(regname, &insert_string.data, &allocated, true)) {
+ if (insert_string.data == NULL) {
return;
}
}
@@ -2912,7 +2911,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
}
- if (insert_string != NULL) {
+ if (insert_string.data != NULL) {
+ insert_string.size = strlen(insert_string.data);
y_type = kMTCharWise;
if (regname == '=') {
// For the = register we need to split the string at NL
@@ -2920,29 +2920,37 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// Loop twice: count the number of lines and save them.
while (true) {
y_size = 0;
- char *ptr = insert_string;
+ char *ptr = insert_string.data;
+ size_t ptrlen = insert_string.size;
while (ptr != NULL) {
if (y_array != NULL) {
- y_array[y_size] = ptr;
+ y_array[y_size].data = ptr;
}
y_size++;
- ptr = vim_strchr(ptr, '\n');
- if (ptr != NULL) {
+ char *tmp = vim_strchr(ptr, '\n');
+ if (tmp == NULL) {
if (y_array != NULL) {
- *ptr = NUL;
+ y_array[y_size - 1].size = ptrlen;
}
- ptr++;
+ } else {
+ if (y_array != NULL) {
+ *tmp = NUL;
+ y_array[y_size - 1].size = (size_t)(tmp - ptr);
+ ptrlen -= y_array[y_size - 1].size + 1;
+ }
+ tmp++;
// A trailing '\n' makes the register linewise.
- if (*ptr == NUL) {
+ if (*tmp == NUL) {
y_type = kMTLineWise;
break;
}
}
+ ptr = tmp;
}
if (y_array != NULL) {
break;
}
- y_array = xmalloc(y_size * sizeof(char *));
+ y_array = xmalloc(y_size * sizeof(String));
}
} else {
y_size = 1; // use fake one-line yank register
@@ -2976,14 +2984,16 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
goto end;
}
char *curline = get_cursor_line_ptr();
- char *p = curline + curwin->w_cursor.col;
+ char *p = get_cursor_pos_ptr();
+ char *const p_orig = p;
+ const size_t plen = (size_t)get_cursor_pos_len();
if (dir == FORWARD && *p != NUL) {
MB_PTR_ADV(p);
}
// we need this later for the correct extmark_splice() event
split_pos = (colnr_T)(p - curline);
- char *ptr = xstrdup(p);
+ char *ptr = xmemdupz(p, plen - (size_t)(p - p_orig));
ml_append(curwin->w_cursor.lnum, ptr, 0, false);
xfree(ptr);
@@ -3047,8 +3057,6 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
goto end;
}
- int yanklen = (int)strlen(y_array[0]);
-
if (cur_ve_flags == VE_ALL && y_type == kMTCharWise) {
if (gchar_cursor() == TAB) {
int viscol = getviscol();
@@ -3072,6 +3080,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// Block mode
if (y_type == kMTBlockWise) {
+ int incr = 0;
+ struct block_def bd;
int c = gchar_cursor();
colnr_T endcol2 = 0;
@@ -3164,14 +3174,14 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
}
- yanklen = (int)strlen(y_array[i]);
+ const int yanklen = (int)y_array[i].size;
if ((flags & PUT_BLOCK_INNER) == 0) {
// calculate number of spaces required to fill right side of block
spaces = y_width + 1;
- cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i]);
- ci = utf_ptr2StrCharInfo(y_array[i]);
+ cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i].data);
+ ci = utf_ptr2StrCharInfo(y_array[i].data);
while (*ci.ptr != NUL) {
spaces -= win_charsize(cstype, 0, ci.ptr, ci.chr.value, &csarg).width;
ci = utfc_next(ci);
@@ -3202,7 +3212,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// insert the new text
for (int j = 0; j < count; j++) {
- memmove(ptr, y_array[i], (size_t)yanklen);
+ memmove(ptr, y_array[i].data, (size_t)yanklen);
ptr += yanklen;
// insert block's trailing spaces only if there's text behind
@@ -3254,6 +3264,8 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
curwin->w_cursor.lnum = lnum;
}
} else {
+ const int yanklen = (int)y_array[0].size;
+
// Character or Line mode
if (y_type == kMTCharWise) {
// if type is kMTCharWise, FORWARD is the same as BACKWARD on the next
@@ -3326,10 +3338,10 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
memmove(newp, oldp, (size_t)col);
char *ptr = newp + col;
for (size_t i = 0; i < (size_t)count; i++) {
- memmove(ptr, y_array[0], (size_t)yanklen);
+ memmove(ptr, y_array[0].data, (size_t)yanklen);
ptr += yanklen;
}
- STRMOVE(ptr, oldp + col);
+ memmove(ptr, oldp + col, (size_t)(oldlen - col) + 1); // +1 for NUL
ml_replace(lnum, newp, false);
// compute the byte offset for the last character
@@ -3367,6 +3379,15 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
} else {
linenr_T new_lnum = new_cursor.lnum;
+ int indent;
+ int orig_indent = 0;
+ int indent_diff = 0; // init for gcc
+ bool first_indent = true;
+ int lendiff = 0;
+
+ if (flags & PUT_FIXINDENT) {
+ orig_indent = get_indent();
+ }
// Insert at least one line. When y_type is kMTCharWise, break the first
// line in two.
@@ -3378,10 +3399,11 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// Then append y_array[0] to first line.
lnum = new_cursor.lnum;
char *ptr = ml_get(lnum) + col;
- totlen = strlen(y_array[y_size - 1]);
- char *newp = xmalloc((size_t)ml_get_len(lnum) - (size_t)col + totlen + 1);
- STRCPY(newp, y_array[y_size - 1]);
- strcat(newp, ptr);
+ size_t ptrlen = (size_t)ml_get_len(lnum) - (size_t)col;
+ totlen = y_array[y_size - 1].size;
+ char *newp = xmalloc(ptrlen + totlen + 1);
+ STRCPY(newp, y_array[y_size - 1].data);
+ STRCPY(newp + totlen, ptr);
// insert second line
ml_append(lnum, newp, 0, false);
new_lnum++;
@@ -3392,7 +3414,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// copy first part of line
memmove(newp, oldp, (size_t)col);
// append to first line
- memmove(newp + col, y_array[0], (size_t)yanklen + 1);
+ memmove(newp + col, y_array[0].data, (size_t)yanklen + 1);
ml_replace(lnum, newp, false);
curwin->w_cursor.lnum = lnum;
@@ -3401,7 +3423,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
for (; i < y_size; i++) {
if ((y_type != kMTCharWise || i < y_size - 1)) {
- if (ml_append(lnum, y_array[i], 0, false) == FAIL) {
+ if (ml_append(lnum, y_array[i].data, 0, false) == FAIL) {
goto error;
}
new_lnum++;
@@ -3440,9 +3462,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
if (y_type == kMTCharWise
|| (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT))) {
for (i = 0; i < y_size - 1; i++) {
- totsize += (bcount_t)strlen(y_array[i]) + 1;
+ totsize += (bcount_t)y_array[i].size + 1;
}
- lastsize = (int)strlen(y_array[y_size - 1]);
+ lastsize = (int)y_array[y_size - 1].size;
totsize += lastsize;
}
if (y_type == kMTCharWise) {
@@ -3486,13 +3508,13 @@ error:
// Put the '] mark on the first byte of the last inserted character.
// Correct the length for change in indent.
curbuf->b_op_end.lnum = new_lnum;
- size_t len = strlen(y_array[y_size - 1]);
- col = (colnr_T)len - lendiff;
+ col = (colnr_T)y_array[y_size - 1].size - lendiff;
if (col > 1) {
curbuf->b_op_end.col = col - 1;
- if (len > 0) {
- curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1],
- y_array[y_size - 1] + len - 1);
+ if (y_array[y_size - 1].size > 0) {
+ curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1].data,
+ y_array[y_size - 1].data
+ + y_array[y_size - 1].size - 1);
}
} else {
curbuf->b_op_end.col = 0;
@@ -3550,7 +3572,7 @@ end:
curbuf->b_op_end = orig_end;
}
if (allocated) {
- xfree(insert_string);
+ xfree(insert_string.data);
}
if (regname == '=') {
xfree(y_array);
@@ -3672,7 +3694,7 @@ void ex_display(exarg_T *eap)
bool do_show = false;
for (size_t j = 0; !do_show && j < yb->y_size; j++) {
- do_show = !message_filtered(yb->y_array[j]);
+ do_show = !message_filtered(yb->y_array[j].data);
}
if (do_show || yb->y_size == 0) {
@@ -3690,7 +3712,7 @@ void ex_display(exarg_T *eap)
msg_puts_attr("^J", attr);
n -= 2;
}
- for (p = yb->y_array[j];
+ for (p = yb->y_array[j].data;
*p != NUL && (n -= ptr2cells(p)) >= 0; p++) {
int clen = utfc_ptr2len(p);
msg_outtrans_len(p, clen, 0);
@@ -4849,7 +4871,7 @@ void *get_reg_contents(int regname, int flags)
if (flags & kGRegList) {
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
for (size_t i = 0; i < reg->y_size; i++) {
- tv_list_append_string(list, reg->y_array[i], -1);
+ tv_list_append_string(list, reg->y_array[i].data, -1);
}
return list;
@@ -4858,9 +4880,8 @@ void *get_reg_contents(int regname, int flags)
// Compute length of resulting string.
size_t len = 0;
for (size_t i = 0; i < reg->y_size; i++) {
- len += strlen(reg->y_array[i]);
- // Insert a newline between lines and after last line if
- // y_type is kMTLineWise.
+ len += reg->y_array[i].size;
+ // Insert a newline between lines and after last line if y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
len++;
}
@@ -4871,11 +4892,10 @@ void *get_reg_contents(int regname, int flags)
// Copy the lines of the yank register into the string.
len = 0;
for (size_t i = 0; i < reg->y_size; i++) {
- STRCPY(retval + len, reg->y_array[i]);
- len += strlen(retval + len);
+ STRCPY(retval + len, reg->y_array[i].data);
+ len += reg->y_array[i].size;
- // Insert a NL between lines and after the last line if y_type is
- // kMTLineWise.
+ // Insert a newline between lines and after the last line if y_type is kMTLineWise.
if (reg->y_type == kMTLineWise || i < reg->y_size - 1) {
retval[len++] = '\n';
}
@@ -4993,8 +5013,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app
semsg(_(e_nobufnr), (int64_t)num);
}
} else {
- buf = buflist_findnr(buflist_findpat(str, str + strlen(str),
- true, false, false));
+ buf = buflist_findnr(buflist_findpat(str, str + len, true, false, false));
}
if (buf == NULL) {
return;
@@ -5090,7 +5109,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
}
// Grow the register array to hold the pointers to the new lines.
- char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char *));
+ String *pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(String));
y_ptr->y_array = pp;
size_t lnum = y_ptr->y_size; // The current line number.
@@ -5102,7 +5121,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
if (str_list) {
for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) {
size_t ss_len = strlen(*ss);
- pp[lnum] = xmemdupz(*ss, ss_len);
+ pp[lnum] = cbuf_to_string(*ss, ss_len);
maxlen = MAX(maxlen, ss_len);
}
} else {
@@ -5115,22 +5134,22 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
maxlen = MAX(maxlen, line_len);
// When appending, copy the previous line and free it after.
- size_t extra = append ? strlen(pp[--lnum]) : 0;
+ size_t extra = append ? pp[--lnum].size : 0;
char *s = xmallocz(line_len + extra);
if (extra > 0) {
- memcpy(s, pp[lnum], extra);
+ memcpy(s, pp[lnum].data, extra);
}
memcpy(s + extra, start, line_len);
size_t s_len = extra + line_len;
if (append) {
- xfree(pp[lnum]);
+ xfree(pp[lnum].data);
append = false; // only first line is appended
}
- pp[lnum] = s;
+ pp[lnum] = cbuf_as_string(s, s_len);
// Convert NULs to '\n' to prevent truncation.
- memchrsub(pp[lnum], NUL, '\n', s_len);
+ memchrsub(pp[lnum].data, NUL, '\n', s_len);
}
}
y_ptr->y_type = yank_type;
@@ -6421,7 +6440,7 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
{
- if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) {
+ if (reg->y_size > 0 && reg->y_array[reg->y_size - 1].size == 0) {
// a known-to-be charwise yank might have a final linebreak
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
@@ -6441,7 +6460,7 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
if (reg->y_type == kMTBlockWise) {
size_t maxlen = 0;
for (size_t i = 0; i < reg->y_size; i++) {
- size_t rowlen = strlen(reg->y_array[i]);
+ size_t rowlen = reg->y_array[i].size;
maxlen = MAX(maxlen, rowlen);
}
assert(maxlen <= INT_MAX);
@@ -6511,7 +6530,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
reg->y_type = kMTUnknown;
}
- reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(char *));
+ reg->y_array = xcalloc((size_t)tv_list_len(lines), sizeof(String));
reg->y_size = (size_t)tv_list_len(lines);
reg->additional_data = NULL;
reg->timestamp = 0;
@@ -6523,14 +6542,15 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (TV_LIST_ITEM_TV(li)->v_type != VAR_STRING) {
goto err;
}
- reg->y_array[tv_idx++] = xstrdupnul(TV_LIST_ITEM_TV(li)->vval.v_string);
+ const char *s = TV_LIST_ITEM_TV(li)->vval.v_string;
+ reg->y_array[tv_idx++] = cstr_to_string(s != NULL ? s : "");
});
- if (reg->y_size > 0 && strlen(reg->y_array[reg->y_size - 1]) == 0) {
+ if (reg->y_size > 0 && reg->y_array[reg->y_size - 1].size == 0) {
// a known-to-be charwise yank might have a final linebreak
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
- xfree(reg->y_array[reg->y_size - 1]);
+ xfree(reg->y_array[reg->y_size - 1].data);
reg->y_size--;
if (reg->y_type == kMTUnknown) {
reg->y_type = kMTLineWise;
@@ -6545,7 +6565,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
if (reg->y_type == kMTBlockWise) {
size_t maxlen = 0;
for (size_t i = 0; i < reg->y_size; i++) {
- size_t rowlen = strlen(reg->y_array[i]);
+ size_t rowlen = reg->y_array[i].size;
maxlen = MAX(maxlen, rowlen);
}
assert(maxlen <= INT_MAX);
@@ -6558,7 +6578,7 @@ static bool get_clipboard(int name, yankreg_T **target, bool quiet)
err:
if (reg->y_array) {
for (size_t i = 0; i < reg->y_size; i++) {
- xfree(reg->y_array[i]);
+ xfree(reg->y_array[i].data);
}
xfree(reg->y_array);
}
@@ -6582,7 +6602,7 @@ static void set_clipboard(int name, yankreg_T *reg)
list_T *const lines = tv_list_alloc((ptrdiff_t)reg->y_size + (reg->y_type != kMTCharWise));
for (size_t i = 0; i < reg->y_size; i++) {
- tv_list_append_string(lines, reg->y_array[i], -1);
+ tv_list_append_string(lines, reg->y_array[i].data, -1);
}
char regtype;
@@ -6666,7 +6686,7 @@ static inline bool reg_empty(const yankreg_T *const reg)
|| reg->y_size == 0
|| (reg->y_size == 1
&& reg->y_type == kMTCharWise
- && *(reg->y_array[0]) == NUL));
+ && reg->y_array[0].size == 0));
}
/// Iterate over global registers.
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index dfa2d4b112..ed7e5f7466 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -105,7 +105,7 @@ enum GRegFlags {
/// Definition of one register
typedef struct {
- char **y_array; ///< Pointer to an array of line pointers.
+ String *y_array; ///< Pointer to an array of Strings.
size_t y_size; ///< Number of lines in y_array.
MotionType y_type; ///< Register type
colnr_T y_width; ///< Register width (only valid for y_type == kBlockWise).
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 11fe291559..9e9f762cd5 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -246,7 +246,7 @@ typedef struct {
struct reg { // yankreg_T
char name;
MotionType type;
- char **contents;
+ String *contents;
bool is_unnamed;
size_t contents_size;
size_t width;
@@ -1491,7 +1491,7 @@ static ShaDaWriteResult shada_pack_entry(PackerBuffer *const packer, ShadaEntry
PACK_KEY(REG_KEY_CONTENTS);
mpack_array(&sbuf.ptr, (uint32_t)entry.data.reg.contents_size);
for (size_t i = 0; i < entry.data.reg.contents_size; i++) {
- mpack_bin(cstr_as_string(entry.data.reg.contents[i]), &sbuf);
+ mpack_bin(entry.data.reg.contents[i], &sbuf);
}
PACK_KEY(KEY_NAME_CHAR);
mpack_uint(&sbuf.ptr, (uint8_t)entry.data.reg.name);
@@ -2930,7 +2930,7 @@ static void shada_free_shada_entry(ShadaEntry *const entry)
break;
case kSDItemRegister:
for (size_t i = 0; i < entry->data.reg.contents_size; i++) {
- xfree(entry->data.reg.contents[i]);
+ api_free_string(entry->data.reg.contents[i]);
}
xfree(entry->data.reg.contents);
break;
@@ -3312,9 +3312,9 @@ shada_read_next_item_start:
goto shada_read_next_item_error;
}
entry->data.reg.contents_size = it.rc.size;
- entry->data.reg.contents = xmalloc(it.rc.size * sizeof(char *));
+ entry->data.reg.contents = xmalloc(it.rc.size * sizeof(String));
for (size_t j = 0; j < it.rc.size; j++) {
- entry->data.reg.contents[j] = xmemdupz(it.rc.items[j].data, it.rc.items[j].size);
+ entry->data.reg.contents[j] = copy_string(it.rc.items[j], NULL);
}
kv_destroy(it.rc);
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index f444021b90..5ff7f721ba 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -895,13 +895,13 @@ static bool is_filter_char(int c)
return !!(tpf_flags & flag);
}
-void terminal_paste(int count, char **y_array, size_t y_size)
+void terminal_paste(int count, String *y_array, size_t y_size)
{
if (y_size == 0) {
return;
}
vterm_keyboard_start_paste(curbuf->terminal->vt);
- size_t buff_len = strlen(y_array[0]);
+ size_t buff_len = y_array[0].size;
char *buff = xmalloc(buff_len);
for (int i = 0; i < count; i++) {
// feed the lines to the terminal
@@ -914,13 +914,13 @@ void terminal_paste(int count, char **y_array, size_t y_size)
terminal_send(curbuf->terminal, "\n", 1);
#endif
}
- size_t len = strlen(y_array[j]);
+ size_t len = y_array[j].size;
if (len > buff_len) {
buff = xrealloc(buff, len);
buff_len = len;
}
char *dst = buff;
- char *src = y_array[j];
+ char *src = y_array[j].data;
while (*src != NUL) {
len = (size_t)utf_ptr2len(src);
int c = utf_ptr2char(src);