mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Refactor str_to_reg().
- Update the doxygen comments. - Use more descriptive types. - Localize variables. - Find the '\n' with memchr instead of a for loop. - Remove `if (size)` checks before memmove since memmove(dst,src,0) is a noop. - Use memcpy instead since the pointers don't alias. - Use xmemdupz instead of vim_strnsave. - xrealloc instead of xmalloc/memcpy. - Use memcnt/xmemscan/memchrsub.
This commit is contained in:
parent
5fdca47962
commit
171445ef34
113
src/nvim/ops.c
113
src/nvim/ops.c
@ -4910,45 +4910,36 @@ void write_reg_contents_ex(int name,
|
|||||||
///
|
///
|
||||||
/// @param y_ptr pointer to yank register
|
/// @param y_ptr pointer to yank register
|
||||||
/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
|
/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
|
||||||
/// @param str string to put in register
|
/// @param str string or list of strings to put in register
|
||||||
/// @param len length of the string
|
/// @param len length of the string (Ignored when str_list=true.)
|
||||||
/// @param blocklen width of visual block
|
/// @param blocklen width of visual block, or -1 for "I don't know."
|
||||||
/// @param str_list True if str is `char_u **`.
|
/// @param str_list True if str is `char_u **`.
|
||||||
static void str_to_reg(struct yankreg *y_ptr, int yank_type, const char_u *str,
|
static void str_to_reg(struct yankreg *y_ptr, int yank_type, const char_u *str,
|
||||||
long len, long blocklen, bool str_list)
|
size_t len, colnr_T blocklen, bool str_list)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int type; /* MCHAR, MLINE or MBLOCK */
|
if (y_ptr->y_array == NULL) { // NULL means empty register
|
||||||
int lnum;
|
|
||||||
long start;
|
|
||||||
long i;
|
|
||||||
int extra;
|
|
||||||
int extraline = 0; /* extra line at the end */
|
|
||||||
int append = FALSE; /* append to last line in register */
|
|
||||||
long maxlen;
|
|
||||||
|
|
||||||
if (y_ptr->y_array == NULL) /* NULL means empty register */
|
|
||||||
y_ptr->y_size = 0;
|
y_ptr->y_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = yank_type; // MCHAR, MLINE or MBLOCK
|
||||||
if (yank_type == MAUTO) {
|
if (yank_type == MAUTO) {
|
||||||
type = ((str_list ||
|
type = ((str_list ||
|
||||||
(len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
|
(len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
|
||||||
? MLINE : MCHAR);
|
? MLINE : MCHAR);
|
||||||
} else {
|
|
||||||
type = yank_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the number of lines within the string
|
|
||||||
size_t newlines = 0;
|
size_t newlines = 0;
|
||||||
|
bool extraline = false; // extra line at the end
|
||||||
|
bool append = false; // append to last line in register
|
||||||
|
|
||||||
|
// Count the number of lines within the string
|
||||||
if (str_list) {
|
if (str_list) {
|
||||||
for (char_u **ss = (char_u **) str; *ss != NULL; ++ss) {
|
for (char_u **ss = (char_u **) str; *ss != NULL; ++ss) {
|
||||||
newlines++;
|
newlines++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < len; i++) {
|
newlines = memcnt(str, '\n', len);
|
||||||
if (str[i] == '\n') {
|
|
||||||
++newlines;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
|
if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
|
||||||
extraline = 1;
|
extraline = 1;
|
||||||
++newlines; // count extra newline at the end
|
++newlines; // count extra newline at the end
|
||||||
@ -4959,65 +4950,57 @@ static void str_to_reg(struct yankreg *y_ptr, int yank_type, const char_u *str,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate an array to hold the pointers to the new register lines.
|
|
||||||
// If the register was not empty, move the existing lines to the new array.
|
// Grow the register array to hold the pointers to the new lines.
|
||||||
char_u **pp = xcalloc(y_ptr->y_size + newlines, sizeof(char_u *));
|
char_u **pp = xrealloc(y_ptr->y_array,
|
||||||
for (lnum = 0; lnum < y_ptr->y_size; ++lnum) {
|
(y_ptr->y_size + newlines) * sizeof(char_u *));
|
||||||
pp[lnum] = y_ptr->y_array[lnum];
|
|
||||||
}
|
|
||||||
free(y_ptr->y_array);
|
|
||||||
y_ptr->y_array = pp;
|
y_ptr->y_array = pp;
|
||||||
maxlen = 0;
|
|
||||||
|
linenr_T lnum = y_ptr->y_size; // The current line number.
|
||||||
|
|
||||||
|
// If called with `blocklen < 0`, we have to update the yank reg's width.
|
||||||
|
size_t maxlen = 0;
|
||||||
|
|
||||||
// Find the end of each line and save it into the array.
|
// Find the end of each line and save it into the array.
|
||||||
if (str_list) {
|
if (str_list) {
|
||||||
for (char_u **ss = (char_u **) str; *ss != NULL; ++ss, ++lnum) {
|
for (char_u **ss = (char_u **) str; *ss != NULL; ++ss, ++lnum) {
|
||||||
int i = STRLEN(*ss);
|
size_t ss_len = STRLEN(*ss);
|
||||||
pp[lnum] = vim_strnsave(*ss, i);
|
pp[lnum] = xmemdupz(*ss, ss_len);
|
||||||
if (i > maxlen) {
|
if (ss_len > maxlen) {
|
||||||
maxlen = i;
|
maxlen = ss_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (start = 0; start < len + extraline; start += i + 1) {
|
size_t line_len;
|
||||||
// Let i represent the length of one line.
|
for (const char_u *start = str, *end = str + len;
|
||||||
const char_u *p = str + start;
|
start < end + extraline;
|
||||||
i = (char_u *)xmemscan(p, '\n', len - start) - p;
|
start += line_len + 1, lnum++) {
|
||||||
if (i > maxlen) {
|
line_len = (const char_u *) xmemscan(start, '\n', end - start) - start;
|
||||||
maxlen = i;
|
if (line_len > maxlen) {
|
||||||
|
maxlen = line_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When appending, copy the previous line and free it after.
|
||||||
|
size_t extra = append ? STRLEN(pp[--lnum]) : 0;
|
||||||
|
char_u *s = xmallocz(line_len + extra);
|
||||||
|
memcpy(s, pp[lnum], extra);
|
||||||
|
memcpy(s + extra, start, line_len);
|
||||||
|
ssize_t s_len = extra + line_len;
|
||||||
|
|
||||||
if (append) {
|
if (append) {
|
||||||
--lnum;
|
free(pp[lnum]);
|
||||||
extra = (int)STRLEN(y_ptr->y_array[lnum]);
|
append = false; // only first line is appended
|
||||||
} else {
|
|
||||||
extra = 0;
|
|
||||||
}
|
}
|
||||||
char_u *s = xmalloc(i + extra + 1);
|
pp[lnum] = s;
|
||||||
if (extra) {
|
|
||||||
memmove(s, y_ptr->y_array[lnum], (size_t)extra);
|
// Convert NULs to '\n' to prevent truncation.
|
||||||
}
|
memchrsub(pp[lnum], NUL, '\n', s_len);
|
||||||
if (append) {
|
|
||||||
free(y_ptr->y_array[lnum]);
|
|
||||||
}
|
|
||||||
if (i) {
|
|
||||||
memmove(s + extra, str + start, (size_t)i);
|
|
||||||
}
|
|
||||||
extra += i;
|
|
||||||
s[extra] = NUL;
|
|
||||||
y_ptr->y_array[lnum++] = s;
|
|
||||||
while (--extra >= 0) {
|
|
||||||
if (*s == NUL) {
|
|
||||||
*s = '\n'; // replace NUL with newline
|
|
||||||
}
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
append = FALSE; // only first line is appended
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y_ptr->y_type = type;
|
y_ptr->y_type = type;
|
||||||
y_ptr->y_size = lnum;
|
y_ptr->y_size = lnum;
|
||||||
if (type == MBLOCK) {
|
if (type == MBLOCK) {
|
||||||
y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
|
y_ptr->y_width = (blocklen == -1 ? (colnr_T) maxlen - 1 : blocklen);
|
||||||
} else {
|
} else {
|
||||||
y_ptr->y_width = 0;
|
y_ptr->y_width = 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user