refactor(api): use arena for channel info and terminal info

This commit is contained in:
bfredl
2024-02-17 20:33:11 +01:00
parent f25fcc68a3
commit 146333ca12
7 changed files with 66 additions and 63 deletions

View File

@@ -1046,7 +1046,7 @@ static Array translate_firstarg(UI *ui, Array args, Arena *arena)
ADD_C(new_args, ARRAY_OBJ(translate_contents(ui, contents, arena))); ADD_C(new_args, ARRAY_OBJ(translate_contents(ui, contents, arena)));
for (size_t i = 1; i < args.size; i++) { for (size_t i = 1; i < args.size; i++) {
ADD(new_args, args.items[i]); ADD_C(new_args, args.items[i]);
} }
return new_args; return new_args;
} }

View File

@@ -1633,7 +1633,7 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
/// the RPC channel), if provided by it via /// the RPC channel), if provided by it via
/// |nvim_set_client_info()|. /// |nvim_set_client_info()|.
/// ///
Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Error *err) Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err)
FUNC_API_SINCE(4) FUNC_API_SINCE(4)
{ {
if (chan < 0) { if (chan < 0) {
@@ -1644,17 +1644,17 @@ Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Error *err)
assert(channel_id <= INT64_MAX); assert(channel_id <= INT64_MAX);
chan = (Integer)channel_id; chan = (Integer)channel_id;
} }
return channel_info((uint64_t)chan); return channel_info((uint64_t)chan, arena);
} }
/// Get information about all open channels. /// Get information about all open channels.
/// ///
/// @returns Array of Dictionaries, each describing a channel with /// @returns Array of Dictionaries, each describing a channel with
/// the format specified at |nvim_get_chan_info()|. /// the format specified at |nvim_get_chan_info()|.
Array nvim_list_chans(void) Array nvim_list_chans(Arena *arena)
FUNC_API_SINCE(4) FUNC_API_SINCE(4)
{ {
return channel_all_info(); return channel_all_info(arena);
} }
/// Calls many API methods atomically. /// Calls many API methods atomically.
@@ -1891,7 +1891,7 @@ Array nvim_get_proc_children(Integer pid, Arena *arena, Error *err)
// syscall failed (possibly because of kernel options), try shelling out. // syscall failed (possibly because of kernel options), try shelling out.
DLOG("fallback to vim._os_proc_children()"); DLOG("fallback to vim._os_proc_children()");
MAXSIZE_TEMP_ARRAY(a, 1); MAXSIZE_TEMP_ARRAY(a, 1);
ADD(a, INTEGER_OBJ(pid)); ADD_C(a, INTEGER_OBJ(pid));
Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, kRetObject, arena, err); Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, kRetObject, arena, err);
if (o.type == kObjectTypeArray) { if (o.type == kObjectTypeArray) {
rvobj = o.data.array; rvobj = o.data.array;
@@ -1903,7 +1903,7 @@ Array nvim_get_proc_children(Integer pid, Arena *arena, Error *err)
} else { } else {
rvobj = arena_array(arena, proc_count); rvobj = arena_array(arena, proc_count);
for (size_t i = 0; i < proc_count; i++) { for (size_t i = 0; i < proc_count; i++) {
ADD(rvobj, INTEGER_OBJ(proc_list[i])); ADD_C(rvobj, INTEGER_OBJ(proc_list[i]));
} }
} }
@@ -1925,7 +1925,7 @@ Object nvim_get_proc(Integer pid, Arena *arena, Error *err)
}); });
#ifdef MSWIN #ifdef MSWIN
rvobj = DICTIONARY_OBJ(os_proc_info((int)pid)); rvobj = DICTIONARY_OBJ(os_proc_info((int)pid, arena));
if (rvobj.data.dictionary.size == 0) { // Process not found. if (rvobj.data.dictionary.size == 0) { // Process not found.
return NIL; return NIL;
} }

View File

@@ -238,7 +238,8 @@ void channel_create_event(Channel *chan, const char *ext_source)
} }
assert(chan->id <= VARNUMBER_MAX); assert(chan->id <= VARNUMBER_MAX);
Dictionary info = channel_info(chan->id); Arena arena = ARENA_EMPTY;
Dictionary info = channel_info(chan->id, &arena);
typval_T tv = TV_INITIAL_VALUE; typval_T tv = TV_INITIAL_VALUE;
// TODO(bfredl): do the conversion in one step. Also would be nice // TODO(bfredl): do the conversion in one step. Also would be nice
// to pretty print top level dict in defined order // to pretty print top level dict in defined order
@@ -247,7 +248,7 @@ void channel_create_event(Channel *chan, const char *ext_source)
char *str = encode_tv2json(&tv, NULL); char *str = encode_tv2json(&tv, NULL);
ILOG("new channel %" PRIu64 " (%s) : %s", chan->id, source, str); ILOG("new channel %" PRIu64 " (%s) : %s", chan->id, source, str);
xfree(str); xfree(str);
api_free_dictionary(info); arena_mem_free(arena_finish(&arena));
#else #else
(void)ext_source; (void)ext_source;
@@ -876,7 +877,8 @@ static void set_info_event(void **argv)
save_v_event_T save_v_event; save_v_event_T save_v_event;
dict_T *dict = get_v_event(&save_v_event); dict_T *dict = get_v_event(&save_v_event);
Dictionary info = channel_info(chan->id); Arena arena = ARENA_EMPTY;
Dictionary info = channel_info(chan->id, &arena);
typval_T retval; typval_T retval;
object_to_vim(DICTIONARY_OBJ(info), &retval, NULL); object_to_vim(DICTIONARY_OBJ(info), &retval, NULL);
assert(retval.v_type == VAR_DICT); assert(retval.v_type == VAR_DICT);
@@ -886,7 +888,7 @@ static void set_info_event(void **argv)
apply_autocmds(event, NULL, NULL, false, curbuf); apply_autocmds(event, NULL, NULL, false, curbuf);
restore_v_event(dict, &save_v_event); restore_v_event(dict, &save_v_event);
api_free_dictionary(info); arena_mem_free(arena_finish(&arena));
channel_decref(chan); channel_decref(chan);
} }
@@ -898,15 +900,15 @@ bool channel_job_running(uint64_t id)
&& !process_is_stopped(&chan->stream.proc)); && !process_is_stopped(&chan->stream.proc));
} }
Dictionary channel_info(uint64_t id) Dictionary channel_info(uint64_t id, Arena *arena)
{ {
Channel *chan = find_channel(id); Channel *chan = find_channel(id);
if (!chan) { if (!chan) {
return (Dictionary)ARRAY_DICT_INIT; return (Dictionary)ARRAY_DICT_INIT;
} }
Dictionary info = ARRAY_DICT_INIT; Dictionary info = arena_dict(arena, 8);
PUT(info, "id", INTEGER_OBJ((Integer)chan->id)); PUT_C(info, "id", INTEGER_OBJ((Integer)chan->id));
const char *stream_desc, *mode_desc; const char *stream_desc, *mode_desc;
switch (chan->streamtype) { switch (chan->streamtype) {
@@ -914,18 +916,20 @@ Dictionary channel_info(uint64_t id)
stream_desc = "job"; stream_desc = "job";
if (chan->stream.proc.type == kProcessTypePty) { if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty); const char *name = pty_process_tty_name(&chan->stream.pty);
PUT(info, "pty", CSTR_TO_OBJ(name)); PUT_C(info, "pty", CSTR_TO_ARENA_OBJ(arena, name));
} }
char **p = chan->stream.proc.argv; char **args = chan->stream.proc.argv;
Array argv = ARRAY_DICT_INIT; Array argv = ARRAY_DICT_INIT;
if (p != NULL) { if (args != NULL) {
while (*p != NULL) { size_t n;
ADD(argv, CSTR_TO_OBJ(*p)); for (n = 0; args[n] != NULL; n++) {}
p++; argv = arena_array(arena, n);
for (size_t i = 0; i < n; i++) {
ADD_C(argv, CSTR_AS_OBJ(args[i]));
} }
} }
PUT(info, "argv", ARRAY_OBJ(argv)); PUT_C(info, "argv", ARRAY_OBJ(argv));
break; break;
} }
@@ -938,25 +942,25 @@ Dictionary channel_info(uint64_t id)
break; break;
case kChannelStreamInternal: case kChannelStreamInternal:
PUT(info, "internal", BOOLEAN_OBJ(true)); PUT_C(info, "internal", BOOLEAN_OBJ(true));
FALLTHROUGH; FALLTHROUGH;
case kChannelStreamSocket: case kChannelStreamSocket:
stream_desc = "socket"; stream_desc = "socket";
break; break;
} }
PUT(info, "stream", CSTR_TO_OBJ(stream_desc)); PUT_C(info, "stream", CSTR_AS_OBJ(stream_desc));
if (chan->is_rpc) { if (chan->is_rpc) {
mode_desc = "rpc"; mode_desc = "rpc";
PUT(info, "client", DICTIONARY_OBJ(rpc_client_info(chan))); PUT_C(info, "client", DICTIONARY_OBJ(chan->rpc.info));
} else if (chan->term) { } else if (chan->term) {
mode_desc = "terminal"; mode_desc = "terminal";
PUT(info, "buffer", BUFFER_OBJ(terminal_buf(chan->term))); PUT_C(info, "buffer", BUFFER_OBJ(terminal_buf(chan->term)));
} else { } else {
mode_desc = "bytes"; mode_desc = "bytes";
} }
PUT(info, "mode", CSTR_TO_OBJ(mode_desc)); PUT_C(info, "mode", CSTR_AS_OBJ(mode_desc));
return info; return info;
} }
@@ -969,21 +973,20 @@ static int int64_t_cmp(const void *pa, const void *pb)
return a == b ? 0 : a > b ? 1 : -1; return a == b ? 0 : a > b ? 1 : -1;
} }
Array channel_all_info(void) Array channel_all_info(Arena *arena)
{ {
// order the items in the array by channel number, for Determinism™ // order the items in the array by channel number, for Determinism™
kvec_t(int64_t) ids = KV_INITIAL_VALUE; kvec_t(int64_t) ids = KV_INITIAL_VALUE;
kv_resize(ids, map_size(&channels)); kv_fixsize_arena(arena, ids, map_size(&channels));
uint64_t id; uint64_t id;
map_foreach_key(&channels, id, { map_foreach_key(&channels, id, {
kv_push(ids, (int64_t)id); kv_push(ids, (int64_t)id);
}); });
qsort(ids.items, ids.size, sizeof ids.items[0], int64_t_cmp); qsort(ids.items, ids.size, sizeof ids.items[0], int64_t_cmp);
Array ret = ARRAY_DICT_INIT; Array ret = arena_array(arena, ids.size);
for (size_t i = 0; i < ids.size; i++) { for (size_t i = 0; i < ids.size; i++) {
ADD(ret, DICTIONARY_OBJ(channel_info((uint64_t)ids.items[i]))); ADD_C(ret, DICTIONARY_OBJ(channel_info((uint64_t)ids.items[i], arena)));
} }
kv_destroy(ids);
return ret; return ret;
} }

View File

@@ -947,10 +947,10 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
Error err = ERROR_INIT; Error err = ERROR_INIT;
MAXSIZE_TEMP_ARRAY(a, 4); MAXSIZE_TEMP_ARRAY(a, 4);
ADD(a, INTEGER_OBJ((int)chan)); ADD_C(a, INTEGER_OBJ((int)chan));
ADD(a, CSTR_AS_OBJ(server_addr)); ADD_C(a, CSTR_AS_OBJ(server_addr));
ADD(a, CSTR_AS_OBJ(connect_error)); ADD_C(a, CSTR_AS_OBJ(connect_error));
ADD(a, ARRAY_OBJ(args)); ADD_C(a, ARRAY_OBJ(args));
String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)"); String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)");
Object o = nlua_exec(s, a, kRetObject, NULL, &err); Object o = nlua_exec(s, a, kRetObject, NULL, &err);
kv_destroy(args); kv_destroy(args);

View File

@@ -682,12 +682,11 @@ static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler
semsg("paste: %s", err->msg); semsg("paste: %s", err->msg);
api_clear_error(err); api_clear_error(err);
} else { } else {
Array args = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(args, 2);
ADD(args, INTEGER_OBJ(err->type)); ADD_C(args, INTEGER_OBJ(err->type));
ADD(args, CSTR_TO_OBJ(err->msg)); ADD_C(args, CSTR_AS_OBJ(err->msg));
msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"), msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"),
args, &pac); args, &pac);
api_free_array(args);
} }
} else { } else {
msgpack_rpc_serialize_response(response_id, err, arg, &pac); msgpack_rpc_serialize_response(response_id, err, arg, &pac);

View File

@@ -230,7 +230,7 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
/// ///
/// @param pid Process to inspect. /// @param pid Process to inspect.
/// @return Map of process properties, empty on error. /// @return Map of process properties, empty on error.
Dictionary os_proc_info(int pid) Dictionary os_proc_info(int pid, Arena *arena)
{ {
Dictionary pinfo = ARRAY_DICT_INIT; Dictionary pinfo = ARRAY_DICT_INIT;
PROCESSENTRY32 pe; PROCESSENTRY32 pe;
@@ -258,9 +258,10 @@ Dictionary os_proc_info(int pid)
CloseHandle(h); CloseHandle(h);
if (pe.th32ProcessID == (DWORD)pid) { if (pe.th32ProcessID == (DWORD)pid) {
PUT(pinfo, "pid", INTEGER_OBJ(pid)); pinfo = arena_dict(arena, 3);
PUT(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID)); PUT_C(pinfo, "pid", INTEGER_OBJ(pid));
PUT(pinfo, "name", CSTR_TO_OBJ(pe.szExeFile)); PUT_C(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID));
PUT_C(pinfo, "name", CSTR_TO_ARENA_OBJ(arena, pe.szExeFile));
} }
return pinfo; return pinfo;

View File

@@ -1434,28 +1434,28 @@ static void show_verbose_terminfo(TUIData *tui)
abort(); abort();
} }
Array chunks = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(chunks, 3);
Array title = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(title, 2);
ADD(title, CSTR_TO_OBJ("\n\n--- Terminal info --- {{{\n")); ADD_C(title, CSTR_AS_OBJ("\n\n--- Terminal info --- {{{\n"));
ADD(title, CSTR_TO_OBJ("Title")); ADD_C(title, CSTR_AS_OBJ("Title"));
ADD(chunks, ARRAY_OBJ(title)); ADD_C(chunks, ARRAY_OBJ(title));
Array info = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(info, 2);
String str = terminfo_info_msg(ut, tui->term); String str = terminfo_info_msg(ut, tui->term);
ADD(info, STRING_OBJ(str)); ADD_C(info, STRING_OBJ(str));
ADD(chunks, ARRAY_OBJ(info)); ADD_C(chunks, ARRAY_OBJ(info));
Array end_fold = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(end_fold, 2);
ADD(end_fold, CSTR_TO_OBJ("}}}\n")); ADD_C(end_fold, CSTR_AS_OBJ("}}}\n"));
ADD(end_fold, CSTR_TO_OBJ("Title")); ADD_C(end_fold, CSTR_AS_OBJ("Title"));
ADD(chunks, ARRAY_OBJ(end_fold)); ADD_C(chunks, ARRAY_OBJ(end_fold));
Array args = ARRAY_DICT_INIT; MAXSIZE_TEMP_ARRAY(args, 3);
ADD(args, ARRAY_OBJ(chunks)); ADD_C(args, ARRAY_OBJ(chunks));
ADD(args, BOOLEAN_OBJ(true)); // history ADD_C(args, BOOLEAN_OBJ(true)); // history
Dictionary opts = ARRAY_DICT_INIT; MAXSIZE_TEMP_DICT(opts, 1);
PUT(opts, "verbose", BOOLEAN_OBJ(true)); PUT_C(opts, "verbose", BOOLEAN_OBJ(true));
ADD(args, DICTIONARY_OBJ(opts)); ADD_C(args, DICTIONARY_OBJ(opts));
rpc_send_event(ui_client_channel_id, "nvim_echo", args); rpc_send_event(ui_client_channel_id, "nvim_echo", args);
api_free_array(args); xfree(str.data);
} }
void tui_suspend(TUIData *tui) void tui_suspend(TUIData *tui)