refactor(api): use arena for nvim_put and nvim_paste

This commit is contained in:
bfredl 2024-02-19 12:07:16 +01:00
parent d14eefaee9
commit 404707c760
3 changed files with 17 additions and 25 deletions

View File

@ -456,9 +456,10 @@ String ga_take_string(garray_T *ga)
/// @param input Binary string
/// @param crlf Also break lines at CR and CRLF.
/// @return [allocated] String array
Array string_to_array(const String input, bool crlf)
Array string_to_array(const String input, bool crlf, Arena *arena)
{
Array ret = ARRAY_DICT_INIT;
ArrayBuilder ret = ARRAY_DICT_INIT;
kvi_init(ret);
for (size_t i = 0; i < input.size; i++) {
const char *start = input.data + i;
const char *end = start;
@ -473,20 +474,17 @@ Array string_to_array(const String input, bool crlf)
if (crlf && *end == CAR && i + 1 < input.size && *(end + 1) == NL) {
i += 1; // Advance past CRLF.
}
String s = {
.size = line_len,
.data = xmemdupz(start, line_len),
};
String s = CBUF_TO_ARENA_STR(arena, start, line_len);
memchrsub(s.data, NUL, NL, line_len);
ADD(ret, STRING_OBJ(s));
kvi_push(ret, STRING_OBJ(s));
// If line ends at end-of-buffer, add empty final item.
// This is "readfile()-style", see also ":help channel-lines".
if (i + 1 == input.size && (*end == NL || (crlf && *end == CAR))) {
ADD(ret, STRING_OBJ(STRING_INIT));
kvi_push(ret, STRING_OBJ(STRING_INIT));
}
}
return ret;
return arena_take_arraybuilder(arena, &ret);
}
/// Normalizes 0-based indexes to buffer line numbers.

View File

@ -1205,14 +1205,13 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error
VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, {
return false;
});
Array lines = ARRAY_DICT_INIT;
if (phase == -1 || phase == 1) { // Start of paste-stream.
draining = false;
} else if (draining) {
// Skip remaining chunks. Report error only once per "stream".
goto theend;
}
lines = string_to_array(data, crlf);
Array lines = string_to_array(data, crlf, arena);
MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, ARRAY_OBJ(lines));
ADD_C(args, INTEGER_OBJ(phase));
@ -1243,7 +1242,6 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:
api_free_array(lines);
if (cancel || phase == -1 || phase == 3) { // End of paste-stream.
draining = false;
}
@ -1264,24 +1262,27 @@ theend:
/// @param after If true insert after cursor (like |p|), or before (like |P|).
/// @param follow If true place cursor at end of inserted text.
/// @param[out] err Error details, if any
void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err)
void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Arena *arena,
Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
yankreg_T *reg = xcalloc(1, sizeof(yankreg_T));
yankreg_T reg[1] = { 0 };
VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, {
goto cleanup;
return;
});
if (lines.size == 0) {
goto cleanup; // Nothing to do.
return; // Nothing to do.
}
reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
reg->y_size = lines.size;
for (size_t i = 0; i < lines.size; i++) {
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
goto cleanup;
return;
});
String line = lines.items[i].data.string;
reg->y_array[i] = xmemdupz(line.data, line.size);
reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
memchrsub(reg->y_array[i], NUL, NL, line.size);
}
@ -1294,10 +1295,6 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
msg_silent--;
VIsual_active = VIsual_was_active;
});
cleanup:
free_register(reg);
xfree(reg);
}
/// Subscribes to event broadcasts.

View File

@ -6499,8 +6499,6 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
}
}
reg->y_array = xcalloc(lines, sizeof(uint8_t *));
reg->y_size = lines;
reg->additional_data = NULL;
reg->timestamp = 0;
return true;
@ -6513,7 +6511,6 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
if (reg->y_type == kMTUnknown || clipboard_adjust) {
xfree(reg->y_array[reg->y_size - 1]);
reg->y_size--;
}
if (reg->y_type == kMTUnknown) {