diff options
-rw-r--r-- | src/nvim/api/buffer.c | 75 | ||||
-rw-r--r-- | src/nvim/api/deprecated.c | 9 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 4 | ||||
-rw-r--r-- | src/nvim/buffer_updates.c | 97 | ||||
-rw-r--r-- | src/nvim/generators/gen_api_dispatch.lua | 8 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 5 |
6 files changed, 81 insertions, 117 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 751fc1c32d..183483b329 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -264,6 +264,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, Integer start, Integer end, Boolean strict_indexing, + Arena *arena, lua_State *lstate, Error *err) FUNC_API_SINCE(1) @@ -295,18 +296,10 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, size_t size = (size_t)(end - start); - init_line_array(lstate, &rv, size); + init_line_array(lstate, &rv, size, arena); - if (!buf_collect_lines(buf, size, (linenr_T)start, 0, (channel_id != VIML_INTERNAL_CALL), &rv, - lstate, err)) { - goto end; - } - -end: - if (ERROR_SET(err)) { - api_free_array(rv); - rv.items = NULL; - } + buf_collect_lines(buf, size, (linenr_T)start, 0, (channel_id != VIML_INTERNAL_CALL), &rv, + lstate, arena); return rv; } @@ -763,8 +756,8 @@ early_end: ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, Integer start_row, Integer start_col, Integer end_row, Integer end_col, - Dict(empty) *opts, lua_State *lstate, - Error *err) + Dict(empty) *opts, + Arena *arena, lua_State *lstate, Error *err) FUNC_API_SINCE(9) { Array rv = ARRAY_DICT_INIT; @@ -799,44 +792,38 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, size_t size = (size_t)(end_row - start_row) + 1; - init_line_array(lstate, &rv, size); + init_line_array(lstate, &rv, size, arena); if (start_row == end_row) { String line = buf_get_text(buf, start_row, start_col, end_col, err); if (ERROR_SET(err)) { goto end; } - push_linestr(lstate, &rv, line.data, line.size, 0, replace_nl); + push_linestr(lstate, &rv, line.data, line.size, 0, replace_nl, arena); return rv; } String str = buf_get_text(buf, start_row, start_col, MAXCOL - 1, err); - - push_linestr(lstate, &rv, str.data, str.size, 0, replace_nl); - if (ERROR_SET(err)) { goto end; } + push_linestr(lstate, &rv, str.data, str.size, 0, replace_nl, arena); + if (size > 2) { - if (!buf_collect_lines(buf, size - 2, (linenr_T)start_row + 1, 1, replace_nl, &rv, lstate, - err)) { - goto end; - } + buf_collect_lines(buf, size - 2, (linenr_T)start_row + 1, 1, replace_nl, &rv, lstate, arena); } str = buf_get_text(buf, end_row, 0, end_col, err); - push_linestr(lstate, &rv, str.data, str.size, (int)(size - 1), replace_nl); - if (ERROR_SET(err)) { goto end; } + push_linestr(lstate, &rv, str.data, str.size, (int)(size - 1), replace_nl, arena); + end: if (ERROR_SET(err)) { - api_free_array(rv); - rv.size = 0; - rv.items = NULL; + return (Array)ARRAY_DICT_INIT; } return rv; @@ -1394,13 +1381,12 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l /// @param lstate Lua state. When NULL the Array is initialized instead. /// @param a Array to initialize /// @param size Size of array -static inline void init_line_array(lua_State *lstate, Array *a, size_t size) +static inline void init_line_array(lua_State *lstate, Array *a, size_t size, Arena *arena) { if (lstate) { lua_createtable(lstate, (int)size, 0); } else { - a->size = size; - a->items = xcalloc(a->size, sizeof(Object)); + *a = arena_array(arena, size); } } @@ -1413,14 +1399,15 @@ static inline void init_line_array(lua_State *lstate, Array *a, size_t size) /// @param a Array to push onto when not using Lua /// @param s String to push /// @param len Size of string -/// @param idx 0-based index to place s +/// @param idx 0-based index to place s (only used for Lua) /// @param replace_nl Replace newlines ('\n') with null ('\0') static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, int idx, - bool replace_nl) + bool replace_nl, Arena *arena) { if (lstate) { // Vim represents NULs as NLs if (s && replace_nl && strchr(s, '\n')) { + // TODO(bfredl): could manage scratch space in the arena, for the NUL case char *tmp = xmemdupz(s, len); strchrsub(tmp, '\n', '\0'); lua_pushlstring(lstate, tmp, len); @@ -1431,15 +1418,15 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, lua_rawseti(lstate, -2, idx + 1); } else { String str = STRING_INIT; - if (s) { - str = cbuf_to_string(s, len); + if (len > 0) { + str = arena_string(arena, cbuf_as_string((char *)s, len)); if (replace_nl) { // Vim represents NULs as NLs, but this may confuse clients. strchrsub(str.data, '\n', '\0'); } } - a->items[idx] = STRING_OBJ(str); + ADD_C(*a, STRING_OBJ(str)); } } @@ -1450,27 +1437,17 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, /// @param n Number of lines to collect /// @param replace_nl Replace newlines ("\n") with NUL /// @param start Line number to start from -/// @param start_idx First index to push to +/// @param start_idx First index to push to (only used for Lua) /// @param[out] l If not NULL, Lines are copied here /// @param[out] lstate If not NULL, Lines are pushed into a table onto the stack /// @param err[out] Error, if any /// @return true unless `err` was set -bool buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool replace_nl, - Array *l, lua_State *lstate, Error *err) +void buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool replace_nl, + Array *l, lua_State *lstate, Arena *arena) { for (size_t i = 0; i < n; i++) { linenr_T lnum = start + (linenr_T)i; - - if (lnum >= MAXLNUM) { - if (err != NULL) { - api_set_error(err, kErrorTypeValidation, "Line index is too high"); - } - return false; - } - char *bufstr = ml_get_buf(buf, lnum); - push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl); + push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl, arena); } - - return true; } diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c index 27f0589e53..dccaeb6922 100644 --- a/src/nvim/api/deprecated.c +++ b/src/nvim/api/deprecated.c @@ -245,20 +245,18 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *er /// @param index Line index /// @param[out] err Error details, if any /// @return Line string -String buffer_get_line(Buffer buffer, Integer index, Error *err) +String buffer_get_line(Buffer buffer, Integer index, Arena *arena, Error *err) FUNC_API_DEPRECATED_SINCE(1) { String rv = { .size = 0 }; index = convert_index(index); - Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, NULL, err); + Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, arena, NULL, err); if (!ERROR_SET(err) && slice.size) { rv = slice.items[0].data.string; } - xfree(slice.items); - return rv; } @@ -319,12 +317,13 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, Integer end, Boolean include_start, Boolean include_end, + Arena *arena, Error *err) FUNC_API_DEPRECATED_SINCE(1) { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - return nvim_buf_get_lines(0, buffer, start, end, false, NULL, err); + return nvim_buf_get_lines(0, buffer, start, end, false, arena, NULL, err); } /// Replaces a line range on the buffer diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index a47694a0cf..78c2561bbd 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -656,10 +656,10 @@ void nvim_set_current_dir(String dir, Error *err) /// /// @param[out] err Error details, if any /// @return Current line string -String nvim_get_current_line(Error *err) +String nvim_get_current_line(Arena *arena, Error *err) FUNC_API_SINCE(1) { - return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); + return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err); } /// Sets the current line. diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index a91a890d0e..1a02ac78d7 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -55,36 +55,33 @@ bool buf_updates_register(buf_T *buf, uint64_t channel_id, BufUpdateCallbacks cb kv_push(buf->update_channels, channel_id); if (send_buffer) { - Array args = ARRAY_DICT_INIT; - args.size = 6; - args.items = xcalloc(args.size, sizeof(Object)); + MAXSIZE_TEMP_ARRAY(args, 6); // the first argument is always the buffer handle - args.items[0] = BUFFER_OBJ(buf->handle); - args.items[1] = INTEGER_OBJ(buf_get_changedtick(buf)); + ADD_C(args, BUFFER_OBJ(buf->handle)); + ADD_C(args, INTEGER_OBJ(buf_get_changedtick(buf))); // the first line that changed (zero-indexed) - args.items[2] = INTEGER_OBJ(0); + ADD_C(args, INTEGER_OBJ(0)); // the last line that was changed - args.items[3] = INTEGER_OBJ(-1); - Array linedata = ARRAY_DICT_INIT; + ADD_C(args, INTEGER_OBJ(-1)); // collect buffer contents STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM"); size_t line_count = (size_t)buf->b_ml.ml_line_count; - if (line_count >= 1) { - linedata.size = line_count; - linedata.items = xcalloc(line_count, sizeof(Object)); - - buf_collect_lines(buf, line_count, 1, 0, true, &linedata, NULL, NULL); + Array linedata = ARRAY_DICT_INIT; + Arena arena = ARENA_EMPTY; + if (line_count > 0) { + linedata = arena_array(&arena, line_count); + buf_collect_lines(buf, line_count, 1, 0, true, &linedata, NULL, &arena); } - args.items[4] = ARRAY_OBJ(linedata); - args.items[5] = BOOLEAN_OBJ(false); + ADD_C(args, ARRAY_OBJ(linedata)); + ADD_C(args, BOOLEAN_OBJ(false)); rpc_send_event(channel_id, "nvim_buf_lines_event", args); - api_free_array(args); // TODO(bfredl): no + arena_mem_free(arena_finish(&arena)); } else { buf_updates_changedtick_single(buf, channel_id); } @@ -176,13 +173,10 @@ void buf_updates_unload(buf_T *buf, bool can_reload) } if (thecb != LUA_NOREF) { - Array args = ARRAY_DICT_INIT; - Object items[1]; - args.size = 1; - args.items = items; + MAXSIZE_TEMP_ARRAY(args, 1); // the first argument is always the buffer handle - args.items[0] = BUFFER_OBJ(buf->handle); + ADD_C(args, BUFFER_OBJ(buf->handle)); TEXTLOCK_WRAP({ nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL); @@ -219,45 +213,43 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added, // if one the channels doesn't work, put its ID here so we can remove it later uint64_t badchannelid = 0; + Arena arena = ARENA_EMPTY; + Array linedata = ARRAY_DICT_INIT; + if (num_added > 0 && kv_size(buf->update_channels)) { + STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM"); + linedata = arena_array(&arena, (size_t)num_added); + buf_collect_lines(buf, (size_t)num_added, firstline, 0, true, &linedata, + NULL, &arena); + } + // notify each of the active channels for (size_t i = 0; i < kv_size(buf->update_channels); i++) { uint64_t channelid = kv_A(buf->update_channels, i); // send through the changes now channel contents now - Array args = ARRAY_DICT_INIT; - args.size = 6; - args.items = xcalloc(args.size, sizeof(Object)); + MAXSIZE_TEMP_ARRAY(args, 6); // the first argument is always the buffer handle - args.items[0] = BUFFER_OBJ(buf->handle); + ADD_C(args, BUFFER_OBJ(buf->handle)); // next argument is b:changedtick - args.items[1] = send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL; + ADD_C(args, send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL); // the first line that changed (zero-indexed) - args.items[2] = INTEGER_OBJ(firstline - 1); + ADD_C(args, INTEGER_OBJ(firstline - 1)); // the last line that was changed - args.items[3] = INTEGER_OBJ(firstline - 1 + num_removed); + ADD_C(args, INTEGER_OBJ(firstline - 1 + num_removed)); // linedata of lines being swapped in - Array linedata = ARRAY_DICT_INIT; - if (num_added > 0) { - STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM"); - linedata.size = (size_t)num_added; - linedata.items = xcalloc((size_t)num_added, sizeof(Object)); - buf_collect_lines(buf, (size_t)num_added, firstline, 0, true, &linedata, - NULL, NULL); - } - args.items[4] = ARRAY_OBJ(linedata); - args.items[5] = BOOLEAN_OBJ(false); + ADD_C(args, ARRAY_OBJ(linedata)); + ADD_C(args, BOOLEAN_OBJ(false)); if (!rpc_send_event(channelid, "nvim_buf_lines_event", args)) { // We can't unregister the channel while we're iterating over the // update_channels array, so we remember its ID to unregister it at // the end. badchannelid = channelid; } - api_free_array(args); // TODO(bfredl): no } // We can only ever remove one dead channel at a time. This is OK because the @@ -268,38 +260,37 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added, buf_updates_unregister(buf, badchannelid); } - // notify each of the active channels + // callbacks don't use linedata + arena_mem_free(arena_finish(&arena)); + + // notify each of the active callbacks size_t j = 0; for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) { BufUpdateCallbacks cb = kv_A(buf->update_callbacks, i); bool keep = true; if (cb.on_lines != LUA_NOREF && (cb.preview || !cmdpreview)) { - Array args = ARRAY_DICT_INIT; - Object items[8]; - args.size = 6; // may be increased to 8 below - args.items = items; + MAXSIZE_TEMP_ARRAY(args, 8); // 6 or 8 used // the first argument is always the buffer handle - args.items[0] = BUFFER_OBJ(buf->handle); + ADD_C(args, BUFFER_OBJ(buf->handle)); // next argument is b:changedtick - args.items[1] = send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL; + ADD_C(args, send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL); // the first line that changed (zero-indexed) - args.items[2] = INTEGER_OBJ(firstline - 1); + ADD_C(args, INTEGER_OBJ(firstline - 1)); // the last line that was changed - args.items[3] = INTEGER_OBJ(firstline - 1 + num_removed); + ADD_C(args, INTEGER_OBJ(firstline - 1 + num_removed)); // the last line in the updated range - args.items[4] = INTEGER_OBJ(firstline - 1 + num_added); + ADD_C(args, INTEGER_OBJ(firstline - 1 + num_added)); // byte count of previous contents - args.items[5] = INTEGER_OBJ((Integer)deleted_bytes); + ADD_C(args, INTEGER_OBJ((Integer)deleted_bytes)); if (cb.utf_sizes) { - args.size = 8; - args.items[6] = INTEGER_OBJ((Integer)deleted_codepoints); - args.items[7] = INTEGER_OBJ((Integer)deleted_codeunits); + ADD_C(args, INTEGER_OBJ((Integer)deleted_codepoints)); + ADD_C(args, INTEGER_OBJ((Integer)deleted_codeunits)); } Object res; diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index da3010878d..04fe43b712 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -55,15 +55,15 @@ local function add_function(fn) -- for specifying errors fn.parameters[#fn.parameters] = nil end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then + fn.has_lua_imp = true + fn.parameters[#fn.parameters] = nil + end if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then -- return value is allocated in an arena fn.arena_return = true fn.parameters[#fn.parameters] = nil end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then - fn.has_lua_imp = true - fn.parameters[#fn.parameters] = nil - end end end diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index a1ce206a2b..75c23c5bc4 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1672,10 +1672,7 @@ Dictionary ns_get_hl_defs(NS ns_id, Dict(get_highlight) *opts, Arena *arena, Err return rv; cleanup: - api_free_integer(id); - api_free_boolean(link); - Dictionary empty = ARRAY_DICT_INIT; - return empty; + return (Dictionary)ARRAY_DICT_INIT; } /// Outputs a highlight when doing ":hi MyHighlight" |