diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-11-01 17:34:19 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-01 09:34:19 +0000 |
commit | cbd8b2c1622e0c1cb4d38b65730e259eb6c100df (patch) | |
tree | 3300c416bd92aa912fcb2084853130d1f758331e | |
parent | 9b357e30fdd0a575480182872331fdb87e9cc331 (diff) | |
download | rneovim-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.h | 6 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 6 | ||||
-rw-r--r-- | src/nvim/ops.c | 246 | ||||
-rw-r--r-- | src/nvim/ops.h | 2 | ||||
-rw-r--r-- | src/nvim/shada.c | 10 | ||||
-rw-r--r-- | src/nvim/terminal.c | 8 |
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); |