refactor(api): use arena for runtime and client info

This commit is contained in:
bfredl
2024-02-19 12:09:07 +01:00
parent 1d95abc66b
commit abb8dcd889
2 changed files with 39 additions and 27 deletions

View File

@@ -543,17 +543,22 @@ Integer nvim_strwidth(String text, Error *err)
/// Gets the paths contained in |runtime-search-path|.
///
/// @return List of paths
ArrayOf(String) nvim_list_runtime_paths(Error *err)
ArrayOf(String) nvim_list_runtime_paths(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
return nvim_get_runtime_file(NULL_STRING, true, err);
return nvim_get_runtime_file(NULL_STRING, true, arena, err);
}
Array nvim__runtime_inspect(void)
Array nvim__runtime_inspect(Arena *arena)
{
return runtime_inspect();
return runtime_inspect(arena);
}
typedef struct {
ArrayBuilder rv;
Arena *arena;
} RuntimeCookie;
/// Find files in runtime directories
///
/// "name" can contain wildcards. For example
@@ -566,25 +571,27 @@ Array nvim__runtime_inspect(void)
/// @param name pattern of files to search for
/// @param all whether to return all matches or only the first
/// @return list of absolute paths to the found files
ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_FAST
{
Array rv = ARRAY_DICT_INIT;
RuntimeCookie cookie = { .rv = ARRAY_DICT_INIT, .arena = arena, };
kvi_init(cookie.rv);
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
TRY_WRAP(err, {
do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &rv);
do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &cookie);
});
return rv;
return arena_take_arraybuilder(arena, &cookie.rv);
}
static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cookie)
static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *c)
{
Array *rv = (Array *)cookie;
RuntimeCookie *cookie = (RuntimeCookie *)c;
for (int i = 0; i < num_fnames; i++) {
ADD(*rv, CSTR_TO_OBJ(fnames[i]));
// TODO(bfredl): consider memory management of gen_expand_wildcards() itself
kvi_push(cookie->rv, CSTR_TO_ARENA_OBJ(cookie->arena, fnames[i]));
if (!all) {
return true;
}
@@ -1583,13 +1590,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
///
/// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type,
Dictionary methods, Dictionary attributes, Error *err)
Dictionary methods, Dictionary attributes, Arena *arena, Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{
Dictionary info = ARRAY_DICT_INIT;
PUT(info, "name", copy_object(STRING_OBJ(name), NULL));
MAXSIZE_TEMP_DICT(info, 5);
PUT_C(info, "name", STRING_OBJ(name));
version = copy_dictionary(version, NULL);
bool has_major = false;
for (size_t i = 0; i < version.size; i++) {
if (strequal(version.items[i].key.data, "major")) {
@@ -1598,15 +1604,21 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
}
}
if (!has_major) {
PUT(version, "major", INTEGER_OBJ(0));
Dictionary v = arena_dict(arena, version.size + 1);
if (version.size) {
memcpy(v.items, version.items, version.size * sizeof(v.items[0]));
v.size = version.size;
}
PUT(info, "version", DICTIONARY_OBJ(version));
PUT_C(v, "major", INTEGER_OBJ(0));
version = v;
}
PUT_C(info, "version", DICTIONARY_OBJ(version));
PUT(info, "type", copy_object(STRING_OBJ(type), NULL));
PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL)));
PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL)));
PUT_C(info, "type", STRING_OBJ(type));
PUT_C(info, "methods", DICTIONARY_OBJ(methods));
PUT_C(info, "attributes", DICTIONARY_OBJ(attributes));
rpc_set_client_info(channel_id, info);
rpc_set_client_info(channel_id, copy_dictionary(info, NULL));
}
/// Gets information about a channel.

View File

@@ -574,20 +574,20 @@ static int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback,
return did_one ? OK : FAIL;
}
Array runtime_inspect(void)
Array runtime_inspect(Arena *arena)
{
RuntimeSearchPath path = runtime_search_path;
Array rv = ARRAY_DICT_INIT;
Array rv = arena_array(arena, kv_size(path));
for (size_t i = 0; i < kv_size(path); i++) {
SearchPathItem *item = &kv_A(path, i);
Array entry = ARRAY_DICT_INIT;
ADD(entry, CSTR_TO_OBJ(item->path));
ADD(entry, BOOLEAN_OBJ(item->after));
ADD_C(entry, CSTR_AS_OBJ(item->path));
ADD_C(entry, BOOLEAN_OBJ(item->after));
if (item->has_lua != kNone) {
ADD(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
ADD_C(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
}
ADD(rv, ARRAY_OBJ(entry));
ADD_C(rv, ARRAY_OBJ(entry));
}
return rv;
}