diff options
Diffstat (limited to 'src/nvim/buffer_updates.c')
-rw-r--r-- | src/nvim/buffer_updates.c | 114 |
1 files changed, 52 insertions, 62 deletions
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c index 01bcb9d7be..e725678937 100644 --- a/src/nvim/buffer_updates.c +++ b/src/nvim/buffer_updates.c @@ -11,7 +11,6 @@ #include "nvim/buffer.h" #include "nvim/buffer_defs.h" #include "nvim/buffer_updates.h" -#include "nvim/func_attr.h" #include "nvim/globals.h" #include "nvim/log.h" #include "nvim/lua/executor.h" @@ -22,7 +21,7 @@ #include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "buffer_updates.c.generated.h" // IWYU pragma: export +# include "buffer_updates.c.generated.h" #endif // Register a channel. Return True if the channel was added, or already added. @@ -56,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); } @@ -177,16 +173,13 @@ 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); + nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL, NULL); }); } @@ -220,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 @@ -269,46 +260,45 @@ 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; TEXTLOCK_WRAP({ - res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL); + res = nlua_call_ref(cb.on_lines, "lines", args, kRetNilBool, NULL, NULL); }); - if (res.type == kObjectTypeBoolean && res.data.boolean == true) { + if (LUARET_TRUTHY(res)) { buffer_update_callbacks_free(cb); keep = false; } @@ -355,10 +345,10 @@ void buf_updates_send_splice(buf_T *buf, int start_row, colnr_T start_col, bcoun Object res; TEXTLOCK_WRAP({ - res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL); + res = nlua_call_ref(cb.on_bytes, "bytes", args, kRetNilBool, NULL, NULL); }); - if (res.type == kObjectTypeBoolean && res.data.boolean == true) { + if (LUARET_TRUTHY(res)) { buffer_update_callbacks_free(cb); keep = false; } @@ -391,10 +381,10 @@ void buf_updates_changedtick(buf_T *buf) Object res; TEXTLOCK_WRAP({ - res = nlua_call_ref(cb.on_changedtick, "changedtick", args, false, NULL); + res = nlua_call_ref(cb.on_changedtick, "changedtick", args, kRetNilBool, NULL, NULL); }); - if (res.type == kObjectTypeBoolean && res.data.boolean == true) { + if (LUARET_TRUTHY(res)) { buffer_update_callbacks_free(cb); keep = false; } |