mirror of
https://github.com/neovim/neovim.git
synced 2025-12-11 17:12:40 +00:00
Merge branch 'api-events'
This commit is contained in:
@@ -5,3 +5,28 @@
|
|||||||
fun:nss_parse_service_list
|
fun:nss_parse_service_list
|
||||||
fun:__nss_database_lookup
|
fun:__nss_database_lookup
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
ex_function_1
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:try_malloc
|
||||||
|
fun:xmalloc
|
||||||
|
fun:ex_function
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ex_function_2
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:realloc
|
||||||
|
fun:xrealloc
|
||||||
|
fun:ga_grow
|
||||||
|
fun:ex_function
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ex_function_3
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:strdup
|
||||||
|
fun:xstrdup
|
||||||
|
fun:vim_strsave
|
||||||
|
fun:ex_function
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
src/nvim/api/buffer.c
|
src/nvim/api/buffer.c
|
||||||
src/nvim/api/buffer.h
|
src/nvim/api/buffer.h
|
||||||
src/nvim/api/defs.h
|
src/nvim/api/private/defs.h
|
||||||
src/nvim/api/helpers.c
|
src/nvim/api/private/helpers.c
|
||||||
src/nvim/api/helpers.h
|
src/nvim/api/private/helpers.h
|
||||||
|
src/nvim/api/private/handle.c
|
||||||
|
src/nvim/api/private/handle.h
|
||||||
src/nvim/api/tabpage.c
|
src/nvim/api/tabpage.c
|
||||||
src/nvim/api/tabpage.h
|
src/nvim/api/tabpage.h
|
||||||
src/nvim/api/vim.c
|
src/nvim/api/vim.c
|
||||||
@@ -40,3 +42,7 @@ src/nvim/os/signal.c
|
|||||||
src/nvim/os/signal.h
|
src/nvim/os/signal.h
|
||||||
src/nvim/os/time.c
|
src/nvim/os/time.c
|
||||||
src/nvim/os/time.h
|
src/nvim/os/time.h
|
||||||
|
src/nvim/os/server.c
|
||||||
|
src/nvim/os/server.h
|
||||||
|
src/nvim/os/channel.c
|
||||||
|
src/nvim/os/channel.h
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ end
|
|||||||
output:write([[
|
output:write([[
|
||||||
};
|
};
|
||||||
|
|
||||||
void msgpack_rpc_dispatch(msgpack_object *req, msgpack_packer *res)
|
void msgpack_rpc_dispatch(uint64_t id, msgpack_object *req, msgpack_packer *res)
|
||||||
{
|
{
|
||||||
Error error = { .set = false };
|
Error error = { .set = false };
|
||||||
uint64_t method_id = (uint32_t)req->via.array.ptr[2].via.u64;
|
uint64_t method_id = (uint32_t)req->via.array.ptr[2].via.u64;
|
||||||
@@ -119,7 +119,9 @@ void msgpack_rpc_dispatch(msgpack_object *req, msgpack_packer *res)
|
|||||||
switch (method_id) {
|
switch (method_id) {
|
||||||
case 0:
|
case 0:
|
||||||
msgpack_pack_nil(res);
|
msgpack_pack_nil(res);
|
||||||
// The result is the `msgpack_metadata` byte array
|
// The result is the [channel_id, metadata] array
|
||||||
|
msgpack_pack_array(res, 2);
|
||||||
|
msgpack_pack_uint64(res, id);
|
||||||
msgpack_pack_raw(res, sizeof(msgpack_metadata));
|
msgpack_pack_raw(res, sizeof(msgpack_metadata));
|
||||||
msgpack_pack_raw_body(res, msgpack_metadata, sizeof(msgpack_metadata));
|
msgpack_pack_raw_body(res, msgpack_metadata, sizeof(msgpack_metadata));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
tmpdir="$(pwd)/tmp"
|
tmpdir="$(pwd)/tmp"
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
mkdir -p "$tmpdir"
|
mkdir -p "$tmpdir"
|
||||||
|
suppressions="$(pwd)/.valgrind.supp"
|
||||||
|
|
||||||
valgrind_check() {
|
valgrind_check() {
|
||||||
(
|
(
|
||||||
@@ -171,7 +172,7 @@ elif [ "$TRAVIS_BUILD_TYPE" = "api/python" ]; then
|
|||||||
sudo pip install .
|
sudo pip install .
|
||||||
sudo pip install nose
|
sudo pip install nose
|
||||||
test_cmd="nosetests --verbosity=2"
|
test_cmd="nosetests --verbosity=2"
|
||||||
nvim_cmd="valgrind -q --track-origins=yes --log-file=$tmpdir/valgrind-%p.log ../build/bin/nvim -u NONE"
|
nvim_cmd="valgrind -q --track-origins=yes --leak-check=yes --suppressions=$suppressions --log-file=$tmpdir/valgrind-%p.log ../build/bin/nvim -u NONE"
|
||||||
if ! ../scripts/run-api-tests.exp "$test_cmd" "$nvim_cmd"; then
|
if ! ../scripts/run-api-tests.exp "$test_cmd" "$nvim_cmd"; then
|
||||||
valgrind_check "$tmpdir"
|
valgrind_check "$tmpdir"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ set(CONV_SRCS
|
|||||||
os/wstream.c
|
os/wstream.c
|
||||||
os/msgpack_rpc.c
|
os/msgpack_rpc.c
|
||||||
api/buffer.c
|
api/buffer.c
|
||||||
api/helpers.c
|
api/private/helpers.c
|
||||||
|
api/private/handle.c
|
||||||
api/tabpage.c
|
api/tabpage.c
|
||||||
api/window.c
|
api/window.c
|
||||||
api/vim.h
|
api/vim.h
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
|
|||||||
rv = slice.items[0];
|
rv = slice.items[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(slice.items);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +219,8 @@ void buffer_set_slice(Buffer buffer,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as with replacing
|
// Same as with replacing, but we also need to free lines
|
||||||
|
free(lines[i]);
|
||||||
lines[i] = NULL;
|
lines[i] = NULL;
|
||||||
extra++;
|
extra++;
|
||||||
}
|
}
|
||||||
@@ -307,7 +310,7 @@ Integer buffer_get_number(Buffer buffer, Error *err)
|
|||||||
|
|
||||||
String buffer_get_name(Buffer buffer, Error *err)
|
String buffer_get_name(Buffer buffer, Error *err)
|
||||||
{
|
{
|
||||||
String rv = {.size = 0, .data = ""};
|
String rv = STRING_INIT;
|
||||||
buf_T *buf = find_buffer(buffer, err);
|
buf_T *buf = find_buffer(buffer, err);
|
||||||
|
|
||||||
if (!buf || buf->b_ffname == NULL) {
|
if (!buf || buf->b_ffname == NULL) {
|
||||||
@@ -333,6 +336,7 @@ void buffer_set_name(Buffer buffer, String name, Error *err)
|
|||||||
// Using aucmd_*: autocommands will be executed by rename_buffer
|
// Using aucmd_*: autocommands will be executed by rename_buffer
|
||||||
aucmd_prepbuf(&aco, buf);
|
aucmd_prepbuf(&aco, buf);
|
||||||
ren_ret = rename_buffer((char_u *)val);
|
ren_ret = rename_buffer((char_u *)val);
|
||||||
|
free(val);
|
||||||
aucmd_restbuf(&aco);
|
aucmd_restbuf(&aco);
|
||||||
|
|
||||||
if (try_end(err)) {
|
if (try_end(err)) {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef NVIM_API_DEFS_H
|
#ifndef NVIM_API_PRIVATE_DEFS_H
|
||||||
#define NVIM_API_DEFS_H
|
#define NVIM_API_PRIVATE_DEFS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define ARRAY_DICT_INIT {.size = 0, .items = NULL}
|
#define ARRAY_DICT_INIT {.size = 0, .items = NULL}
|
||||||
|
#define STRING_INIT {.data = NULL, .size = 0}
|
||||||
#define REMOTE_TYPE(type) typedef uint64_t type
|
#define REMOTE_TYPE(type) typedef uint64_t type
|
||||||
|
|
||||||
#define TYPED_ARRAY_OF(type) \
|
#define TYPED_ARRAY_OF(type) \
|
||||||
@@ -84,5 +85,5 @@ struct key_value_pair {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // NVIM_API_DEFS_H
|
#endif // NVIM_API_PRIVATE_DEFS_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef NVIM_API_HANDLE_H
|
#ifndef NVIM_API_PRIVATE_HANDLE_H
|
||||||
#define NVIM_API_HANDLE_H
|
#define NVIM_API_PRIVATE_HANDLE_H
|
||||||
|
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
@@ -16,5 +16,5 @@ HANDLE_DECLS(tabpage_T, tabpage)
|
|||||||
void handle_init(void);
|
void handle_init(void);
|
||||||
|
|
||||||
|
|
||||||
#endif // NVIM_API_HANDLE_H
|
#endif // NVIM_API_PRIVATE_HANDLE_H
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err)
|
|||||||
|
|
||||||
char *val = xstrndup(value.data.string.data, value.data.string.size);
|
char *val = xstrndup(value.data.string.data, value.data.string.size);
|
||||||
set_option_value_for(key, 0, val, opt_flags, type, to, err);
|
set_option_value_for(key, 0, val, opt_flags, type, to, err);
|
||||||
|
free(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -319,7 +320,7 @@ tabpage_T * find_tab(Tabpage tabpage, Error *err)
|
|||||||
|
|
||||||
String cstr_to_string(const char *str) {
|
String cstr_to_string(const char *str) {
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
return (String) { .data = NULL, .size = 0 };
|
return (String) STRING_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = strlen(str);
|
size_t len = strlen(str);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef NVIM_API_HELPERS_H
|
#ifndef NVIM_API_PRIVATE_HELPERS_H
|
||||||
#define NVIM_API_HELPERS_H
|
#define NVIM_API_PRIVATE_HELPERS_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@@ -94,5 +94,5 @@ tabpage_T * find_tab(Tabpage tabpage, Error *err);
|
|||||||
/// empty String is returned
|
/// empty String is returned
|
||||||
String cstr_to_string(const char *str);
|
String cstr_to_string(const char *str);
|
||||||
|
|
||||||
#endif // NVIM_API_HELPERS_H
|
#endif // NVIM_API_PRIVATE_HELPERS_H
|
||||||
|
|
||||||
|
|||||||
102
src/nvim/eval.c
102
src/nvim/eval.c
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
@@ -67,6 +66,7 @@
|
|||||||
#include "nvim/os/rstream.h"
|
#include "nvim/os/rstream.h"
|
||||||
#include "nvim/os/rstream_defs.h"
|
#include "nvim/os/rstream_defs.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
|
#include "nvim/os/channel.h"
|
||||||
|
|
||||||
#if defined(FEAT_FLOAT)
|
#if defined(FEAT_FLOAT)
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
@@ -680,11 +680,6 @@ static void f_range(typval_T *argvars, typval_T *rettv);
|
|||||||
static void f_readfile(typval_T *argvars, typval_T *rettv);
|
static void f_readfile(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_reltime(typval_T *argvars, typval_T *rettv);
|
static void f_reltime(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_reltimestr(typval_T *argvars, typval_T *rettv);
|
static void f_reltimestr(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_remote_expr(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_remote_foreground(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_remote_peek(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_remote_read(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_remote_send(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_remove(typval_T *argvars, typval_T *rettv);
|
static void f_remove(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_rename(typval_T *argvars, typval_T *rettv);
|
static void f_rename(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_repeat(typval_T *argvars, typval_T *rettv);
|
static void f_repeat(typval_T *argvars, typval_T *rettv);
|
||||||
@@ -700,8 +695,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv);
|
|||||||
static void f_searchpair(typval_T *argvars, typval_T *rettv);
|
static void f_searchpair(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
|
static void f_searchpairpos(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_searchpos(typval_T *argvars, typval_T *rettv);
|
static void f_searchpos(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_server2client(typval_T *argvars, typval_T *rettv);
|
static void f_send_event(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_serverlist(typval_T *argvars, typval_T *rettv);
|
|
||||||
static void f_setbufvar(typval_T *argvars, typval_T *rettv);
|
static void f_setbufvar(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
|
static void f_setcmdpos(typval_T *argvars, typval_T *rettv);
|
||||||
static void f_setline(typval_T *argvars, typval_T *rettv);
|
static void f_setline(typval_T *argvars, typval_T *rettv);
|
||||||
@@ -6936,11 +6930,6 @@ static struct fst {
|
|||||||
{"readfile", 1, 3, f_readfile},
|
{"readfile", 1, 3, f_readfile},
|
||||||
{"reltime", 0, 2, f_reltime},
|
{"reltime", 0, 2, f_reltime},
|
||||||
{"reltimestr", 1, 1, f_reltimestr},
|
{"reltimestr", 1, 1, f_reltimestr},
|
||||||
{"remote_expr", 2, 3, f_remote_expr},
|
|
||||||
{"remote_foreground", 1, 1, f_remote_foreground},
|
|
||||||
{"remote_peek", 1, 2, f_remote_peek},
|
|
||||||
{"remote_read", 1, 1, f_remote_read},
|
|
||||||
{"remote_send", 2, 3, f_remote_send},
|
|
||||||
{"remove", 2, 3, f_remove},
|
{"remove", 2, 3, f_remove},
|
||||||
{"rename", 2, 2, f_rename},
|
{"rename", 2, 2, f_rename},
|
||||||
{"repeat", 2, 2, f_repeat},
|
{"repeat", 2, 2, f_repeat},
|
||||||
@@ -6956,8 +6945,7 @@ static struct fst {
|
|||||||
{"searchpair", 3, 7, f_searchpair},
|
{"searchpair", 3, 7, f_searchpair},
|
||||||
{"searchpairpos", 3, 7, f_searchpairpos},
|
{"searchpairpos", 3, 7, f_searchpairpos},
|
||||||
{"searchpos", 1, 4, f_searchpos},
|
{"searchpos", 1, 4, f_searchpos},
|
||||||
{"server2client", 2, 2, f_server2client},
|
{"send_event", 3, 3, f_send_event},
|
||||||
{"serverlist", 0, 0, f_serverlist},
|
|
||||||
{"setbufvar", 3, 3, f_setbufvar},
|
{"setbufvar", 3, 3, f_setbufvar},
|
||||||
{"setcmdpos", 1, 1, f_setcmdpos},
|
{"setcmdpos", 1, 1, f_setcmdpos},
|
||||||
{"setline", 2, 2, f_setline},
|
{"setline", 2, 2, f_setline},
|
||||||
@@ -12226,46 +12214,6 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv)
|
|||||||
rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
|
rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "remote_expr()" function
|
|
||||||
*/
|
|
||||||
static void f_remote_expr(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
rettv->v_type = VAR_STRING;
|
|
||||||
rettv->vval.v_string = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "remote_foreground()" function
|
|
||||||
*/
|
|
||||||
static void f_remote_foreground(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void f_remote_peek(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
rettv->vval.v_number = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void f_remote_read(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
char_u *r = NULL;
|
|
||||||
|
|
||||||
rettv->v_type = VAR_STRING;
|
|
||||||
rettv->vval.v_string = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "remote_send()" function
|
|
||||||
*/
|
|
||||||
static void f_remote_send(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
rettv->v_type = VAR_STRING;
|
|
||||||
rettv->vval.v_string = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "remove()" function
|
* "remove()" function
|
||||||
*/
|
*/
|
||||||
@@ -13111,6 +13059,36 @@ do_searchpair (
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "send_event()" function
|
||||||
|
static void f_send_event(typval_T *argvars, typval_T *rettv)
|
||||||
|
{
|
||||||
|
rettv->v_type = VAR_NUMBER;
|
||||||
|
rettv->vval.v_number = 0;
|
||||||
|
|
||||||
|
if (check_restricted() || check_secure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_NUMBER || argvars[0].vval.v_number <= 0) {
|
||||||
|
EMSG2(_(e_invarg2), "Channel id must be a positive integer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvars[1].v_type != VAR_STRING) {
|
||||||
|
EMSG2(_(e_invarg2), "Event type must be a string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channel_send_event((uint64_t)argvars[0].vval.v_number,
|
||||||
|
(char *)argvars[1].vval.v_string,
|
||||||
|
&argvars[2])) {
|
||||||
|
EMSG2(_(e_invarg2), "Channel doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rettv->vval.v_number = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "searchpos()" function
|
* "searchpos()" function
|
||||||
*/
|
*/
|
||||||
@@ -13136,20 +13114,6 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv)
|
|||||||
list_append_number(rettv->vval.v_list, (varnumber_T)n);
|
list_append_number(rettv->vval.v_list, (varnumber_T)n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void f_server2client(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
rettv->vval.v_number = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void f_serverlist(typval_T *argvars, typval_T *rettv)
|
|
||||||
{
|
|
||||||
char_u *r = NULL;
|
|
||||||
|
|
||||||
rettv->v_type = VAR_STRING;
|
|
||||||
rettv->vval.v_string = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "setbufvar()" function
|
* "setbufvar()" function
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
|
|
||||||
#include "nvim/lib/klist.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/os/channel.h"
|
#include "nvim/os/channel.h"
|
||||||
#include "nvim/os/channel_defs.h"
|
#include "nvim/os/channel_defs.h"
|
||||||
#include "nvim/os/rstream.h"
|
#include "nvim/os/rstream.h"
|
||||||
@@ -15,8 +15,10 @@
|
|||||||
#include "nvim/os/msgpack_rpc.h"
|
#include "nvim/os/msgpack_rpc.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/map.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint64_t id;
|
||||||
ChannelProtocol protocol;
|
ChannelProtocol protocol;
|
||||||
bool is_job;
|
bool is_job;
|
||||||
union {
|
union {
|
||||||
@@ -30,22 +32,26 @@ typedef struct {
|
|||||||
struct {
|
struct {
|
||||||
RStream *read;
|
RStream *read;
|
||||||
WStream *write;
|
WStream *write;
|
||||||
|
uv_stream_t *uv;
|
||||||
} streams;
|
} streams;
|
||||||
} data;
|
} data;
|
||||||
} Channel;
|
} Channel;
|
||||||
|
|
||||||
#define _destroy_channel(x)
|
static uint64_t next_id = 1;
|
||||||
|
static Map(uint64_t) *channels = NULL;
|
||||||
|
static msgpack_sbuffer msgpack_event_buffer;
|
||||||
|
|
||||||
KLIST_INIT(Channel, Channel *, _destroy_channel)
|
|
||||||
|
|
||||||
static klist_t(Channel) *channels = NULL;
|
|
||||||
static void on_job_stdout(RStream *rstream, void *data, bool eof);
|
static void on_job_stdout(RStream *rstream, void *data, bool eof);
|
||||||
static void on_job_stderr(RStream *rstream, void *data, bool eof);
|
static void on_job_stderr(RStream *rstream, void *data, bool eof);
|
||||||
static void parse_msgpack(RStream *rstream, void *data, bool eof);
|
static void parse_msgpack(RStream *rstream, void *data, bool eof);
|
||||||
|
static void send_msgpack(Channel *channel, String type, Object data);
|
||||||
|
static void close_channel(Channel *channel);
|
||||||
|
static void close_cb(uv_handle_t *handle);
|
||||||
|
|
||||||
void channel_init()
|
void channel_init()
|
||||||
{
|
{
|
||||||
channels = kl_init(Channel);
|
channels = map_new(uint64_t)();
|
||||||
|
msgpack_sbuffer_init(&msgpack_event_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void channel_teardown()
|
void channel_teardown()
|
||||||
@@ -56,24 +62,9 @@ void channel_teardown()
|
|||||||
|
|
||||||
Channel *channel;
|
Channel *channel;
|
||||||
|
|
||||||
while (kl_shift(Channel, channels, &channel) == 0) {
|
map_foreach_value(channels, channel, {
|
||||||
|
close_channel(channel);
|
||||||
switch (channel->protocol) {
|
});
|
||||||
case kChannelProtocolMsgpack:
|
|
||||||
msgpack_sbuffer_free(channel->proto.msgpack.sbuffer);
|
|
||||||
msgpack_unpacker_free(channel->proto.msgpack.unpacker);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel->is_job) {
|
|
||||||
job_stop(channel->data.job_id);
|
|
||||||
} else {
|
|
||||||
rstream_free(channel->data.streams.read);
|
|
||||||
wstream_free(channel->data.streams.write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void channel_from_job(char **argv, ChannelProtocol prot)
|
void channel_from_job(char **argv, ChannelProtocol prot)
|
||||||
@@ -92,10 +83,11 @@ void channel_from_job(char **argv, ChannelProtocol prot)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel->id = next_id++;
|
||||||
channel->protocol = prot;
|
channel->protocol = prot;
|
||||||
channel->is_job = true;
|
channel->is_job = true;
|
||||||
channel->data.job_id = job_start(argv, channel, rcb, on_job_stderr, NULL);
|
channel->data.job_id = job_start(argv, channel, rcb, on_job_stderr, NULL);
|
||||||
*kl_pushp(Channel, channels) = channel;
|
map_put(uint64_t)(channels, channel->id, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void channel_from_stream(uv_stream_t *stream, ChannelProtocol prot)
|
void channel_from_stream(uv_stream_t *stream, ChannelProtocol prot)
|
||||||
@@ -115,6 +107,7 @@ void channel_from_stream(uv_stream_t *stream, ChannelProtocol prot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream->data = NULL;
|
stream->data = NULL;
|
||||||
|
channel->id = next_id++;
|
||||||
channel->protocol = prot;
|
channel->protocol = prot;
|
||||||
channel->is_job = false;
|
channel->is_job = false;
|
||||||
// read stream
|
// read stream
|
||||||
@@ -124,8 +117,32 @@ void channel_from_stream(uv_stream_t *stream, ChannelProtocol prot)
|
|||||||
// write stream
|
// write stream
|
||||||
channel->data.streams.write = wstream_new(1024 * 1024);
|
channel->data.streams.write = wstream_new(1024 * 1024);
|
||||||
wstream_set_stream(channel->data.streams.write, stream);
|
wstream_set_stream(channel->data.streams.write, stream);
|
||||||
// push to channel list
|
channel->data.streams.uv = stream;
|
||||||
*kl_pushp(Channel, channels) = channel;
|
map_put(uint64_t)(channels, channel->id, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool channel_send_event(uint64_t id, char *type, typval_T *data)
|
||||||
|
{
|
||||||
|
Channel *channel = map_get(uint64_t)(channels, id);
|
||||||
|
|
||||||
|
if (!channel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String event_type = {.size = strnlen(type, 1024), .data = type};
|
||||||
|
Object event_data = vim_to_object(data);
|
||||||
|
|
||||||
|
switch (channel->protocol) {
|
||||||
|
case kChannelProtocolMsgpack:
|
||||||
|
send_msgpack(channel, event_type, event_data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
msgpack_rpc_free_object(event_data);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_job_stdout(RStream *rstream, void *data, bool eof)
|
static void on_job_stdout(RStream *rstream, void *data, bool eof)
|
||||||
@@ -141,8 +158,13 @@ static void on_job_stderr(RStream *rstream, void *data, bool eof)
|
|||||||
|
|
||||||
static void parse_msgpack(RStream *rstream, void *data, bool eof)
|
static void parse_msgpack(RStream *rstream, void *data, bool eof)
|
||||||
{
|
{
|
||||||
msgpack_unpacked unpacked;
|
|
||||||
Channel *channel = data;
|
Channel *channel = data;
|
||||||
|
|
||||||
|
if (eof) {
|
||||||
|
close_channel(channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t count = rstream_available(rstream);
|
uint32_t count = rstream_available(rstream);
|
||||||
|
|
||||||
// Feed the unpacker with data
|
// Feed the unpacker with data
|
||||||
@@ -152,17 +174,18 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)
|
|||||||
count);
|
count);
|
||||||
msgpack_unpacker_buffer_consumed(channel->proto.msgpack.unpacker, count);
|
msgpack_unpacker_buffer_consumed(channel->proto.msgpack.unpacker, count);
|
||||||
|
|
||||||
|
msgpack_unpacked unpacked;
|
||||||
msgpack_unpacked_init(&unpacked);
|
msgpack_unpacked_init(&unpacked);
|
||||||
|
|
||||||
// Deserialize everything we can.
|
// Deserialize everything we can.
|
||||||
while (msgpack_unpacker_next(channel->proto.msgpack.unpacker, &unpacked)) {
|
while (msgpack_unpacker_next(channel->proto.msgpack.unpacker, &unpacked)) {
|
||||||
// Each object is a new msgpack-rpc request and requires an empty response
|
// Each object is a new msgpack-rpc request and requires an empty response
|
||||||
msgpack_packer response;
|
msgpack_packer response;
|
||||||
msgpack_packer_init(&response,
|
msgpack_packer_init(&response,
|
||||||
channel->proto.msgpack.sbuffer,
|
channel->proto.msgpack.sbuffer,
|
||||||
msgpack_sbuffer_write);
|
msgpack_sbuffer_write);
|
||||||
// Perform the call
|
// Perform the call
|
||||||
msgpack_rpc_call(&unpacked.data, &response);
|
msgpack_rpc_call(channel->id, &unpacked.data, &response);
|
||||||
wstream_write(channel->data.streams.write,
|
wstream_write(channel->data.streams.write,
|
||||||
xmemdup(channel->proto.msgpack.sbuffer->data,
|
xmemdup(channel->proto.msgpack.sbuffer->data,
|
||||||
channel->proto.msgpack.sbuffer->size),
|
channel->proto.msgpack.sbuffer->size),
|
||||||
@@ -173,3 +196,49 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof)
|
|||||||
msgpack_sbuffer_clear(channel->proto.msgpack.sbuffer);
|
msgpack_sbuffer_clear(channel->proto.msgpack.sbuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_msgpack(Channel *channel, String type, Object data)
|
||||||
|
{
|
||||||
|
msgpack_packer packer;
|
||||||
|
msgpack_packer_init(&packer, &msgpack_event_buffer, msgpack_sbuffer_write);
|
||||||
|
msgpack_rpc_notification(type, data, &packer);
|
||||||
|
char *bytes = xmemdup(msgpack_event_buffer.data, msgpack_event_buffer.size);
|
||||||
|
|
||||||
|
wstream_write(channel->data.streams.write,
|
||||||
|
bytes,
|
||||||
|
msgpack_event_buffer.size,
|
||||||
|
true);
|
||||||
|
|
||||||
|
msgpack_sbuffer_clear(&msgpack_event_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_channel(Channel *channel)
|
||||||
|
{
|
||||||
|
map_del(uint64_t)(channels, channel->id);
|
||||||
|
|
||||||
|
switch (channel->protocol) {
|
||||||
|
case kChannelProtocolMsgpack:
|
||||||
|
msgpack_sbuffer_free(channel->proto.msgpack.sbuffer);
|
||||||
|
msgpack_unpacker_free(channel->proto.msgpack.unpacker);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->is_job) {
|
||||||
|
job_stop(channel->data.job_id);
|
||||||
|
} else {
|
||||||
|
rstream_free(channel->data.streams.read);
|
||||||
|
wstream_free(channel->data.streams.write);
|
||||||
|
uv_close((uv_handle_t *)channel->data.streams.uv, close_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_cb(uv_handle_t *handle)
|
||||||
|
{
|
||||||
|
free(handle->data);
|
||||||
|
free(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "nvim/vim.h"
|
||||||
#include "nvim/os/channel_defs.h"
|
#include "nvim/os/channel_defs.h"
|
||||||
|
|
||||||
/// Initializes the module
|
/// Initializes the module
|
||||||
@@ -25,5 +26,13 @@ void channel_from_stream(uv_stream_t *stream, ChannelProtocol prot);
|
|||||||
/// @param prot The rpc protocol used
|
/// @param prot The rpc protocol used
|
||||||
void channel_from_job(char **argv, ChannelProtocol prot);
|
void channel_from_job(char **argv, ChannelProtocol prot);
|
||||||
|
|
||||||
|
/// Sends event/data to channel
|
||||||
|
///
|
||||||
|
/// @param id The channel id
|
||||||
|
/// @param type The event type, an arbitrary string
|
||||||
|
/// @param obj The event data
|
||||||
|
/// @return True if the data was sent successfully, false otherwise.
|
||||||
|
bool channel_send_event(uint64_t id, char *type, typval_T *data);
|
||||||
|
|
||||||
#endif // NVIM_OS_CHANNEL_H
|
#endif // NVIM_OS_CHANNEL_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
|
|
||||||
#include "nvim/os/msgpack_rpc.h"
|
#include "nvim/os/msgpack_rpc.h"
|
||||||
@@ -52,7 +55,7 @@
|
|||||||
free(value.items); \
|
free(value.items); \
|
||||||
}
|
}
|
||||||
|
|
||||||
void msgpack_rpc_call(msgpack_object *req, msgpack_packer *res)
|
void msgpack_rpc_call(uint64_t id, msgpack_object *req, msgpack_packer *res)
|
||||||
{
|
{
|
||||||
// The initial response structure is the same no matter what happens,
|
// The initial response structure is the same no matter what happens,
|
||||||
// we set it up here
|
// we set it up here
|
||||||
@@ -107,7 +110,16 @@ void msgpack_rpc_call(msgpack_object *req, msgpack_packer *res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dispatch the message
|
// dispatch the message
|
||||||
msgpack_rpc_dispatch(req, res);
|
msgpack_rpc_dispatch(id, req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void msgpack_rpc_notification(String type, Object data, msgpack_packer *pac)
|
||||||
|
{
|
||||||
|
msgpack_pack_array(pac, 3);
|
||||||
|
msgpack_pack_int(pac, 2);
|
||||||
|
msgpack_pack_raw(pac, type.size);
|
||||||
|
msgpack_pack_raw_body(pac, type.data, type.size);
|
||||||
|
msgpack_rpc_from_object(data, pac);
|
||||||
}
|
}
|
||||||
|
|
||||||
void msgpack_rpc_error(char *msg, msgpack_packer *res)
|
void msgpack_rpc_error(char *msg, msgpack_packer *res)
|
||||||
@@ -147,9 +159,13 @@ bool msgpack_rpc_to_float(msgpack_object *obj, Float *arg)
|
|||||||
|
|
||||||
bool msgpack_rpc_to_string(msgpack_object *obj, String *arg)
|
bool msgpack_rpc_to_string(msgpack_object *obj, String *arg)
|
||||||
{
|
{
|
||||||
arg->data = (char *)obj->via.raw.ptr;
|
if (obj->type != MSGPACK_OBJECT_RAW) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg->data = xmemdup(obj->via.raw.ptr, obj->via.raw.size);
|
||||||
arg->size = obj->via.raw.size;
|
arg->size = obj->via.raw.size;
|
||||||
return obj->type == MSGPACK_OBJECT_RAW;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg)
|
bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg)
|
||||||
@@ -328,6 +344,15 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void msgpack_rpc_free_string(String value)
|
||||||
|
{
|
||||||
|
if (!value.data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(value.data);
|
||||||
|
}
|
||||||
|
|
||||||
void msgpack_rpc_free_object(Object value)
|
void msgpack_rpc_free_object(Object value)
|
||||||
{
|
{
|
||||||
switch (value.type) {
|
switch (value.type) {
|
||||||
|
|||||||
@@ -6,14 +6,25 @@
|
|||||||
|
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
|
|
||||||
|
#include "nvim/func_attr.h"
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
|
|
||||||
/// Validates the basic structure of the msgpack-rpc call and fills `res`
|
/// Validates the basic structure of the msgpack-rpc call and fills `res`
|
||||||
/// with the basic response structure.
|
/// with the basic response structure.
|
||||||
///
|
///
|
||||||
|
/// @param id The channel id
|
||||||
/// @param req The parsed request object
|
/// @param req The parsed request object
|
||||||
/// @param res A packer that contains the response
|
/// @param res A packer that contains the response
|
||||||
void msgpack_rpc_call(msgpack_object *req, msgpack_packer *res);
|
void msgpack_rpc_call(uint64_t id, msgpack_object *req, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
|
||||||
|
|
||||||
|
/// Packs a notification message
|
||||||
|
///
|
||||||
|
/// @param type The message type, an arbitrary string
|
||||||
|
/// @param data The notification data
|
||||||
|
/// @param packer Where the notification will be packed to
|
||||||
|
void msgpack_rpc_notification(String type, Object data, msgpack_packer *pac)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(3);
|
||||||
|
|
||||||
/// Dispatches to the actual API function after basic payload validation by
|
/// Dispatches to the actual API function after basic payload validation by
|
||||||
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
|
/// `msgpack_rpc_call`. It is responsible for validating/converting arguments
|
||||||
@@ -21,15 +32,20 @@ void msgpack_rpc_call(msgpack_object *req, msgpack_packer *res);
|
|||||||
/// The implementation is generated at compile time with metadata extracted
|
/// The implementation is generated at compile time with metadata extracted
|
||||||
/// from the api/*.h headers,
|
/// from the api/*.h headers,
|
||||||
///
|
///
|
||||||
|
/// @param id The channel id
|
||||||
/// @param req The parsed request object
|
/// @param req The parsed request object
|
||||||
/// @param res A packer that contains the response
|
/// @param res A packer that contains the response
|
||||||
void msgpack_rpc_dispatch(msgpack_object *req, msgpack_packer *res);
|
void msgpack_rpc_dispatch(uint64_t id,
|
||||||
|
msgpack_object *req,
|
||||||
|
msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_NONNULL_ARG(3);
|
||||||
|
|
||||||
/// Finishes the msgpack-rpc call with an error message.
|
/// Finishes the msgpack-rpc call with an error message.
|
||||||
///
|
///
|
||||||
/// @param msg The error message
|
/// @param msg The error message
|
||||||
/// @param res A packer that contains the response
|
/// @param res A packer that contains the response
|
||||||
void msgpack_rpc_error(char *msg, msgpack_packer *res);
|
void msgpack_rpc_error(char *msg, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
|
||||||
/// Functions for validating and converting from msgpack types to C types.
|
/// Functions for validating and converting from msgpack types to C types.
|
||||||
/// These are used by `msgpack_rpc_dispatch` to validate and convert each
|
/// These are used by `msgpack_rpc_dispatch` to validate and convert each
|
||||||
@@ -38,21 +54,36 @@ void msgpack_rpc_error(char *msg, msgpack_packer *res);
|
|||||||
/// @param obj The object to convert
|
/// @param obj The object to convert
|
||||||
/// @param[out] arg A pointer to the avalue
|
/// @param[out] arg A pointer to the avalue
|
||||||
/// @return true if the convertion succeeded, false otherwise
|
/// @return true if the convertion succeeded, false otherwise
|
||||||
bool msgpack_rpc_to_boolean(msgpack_object *obj, Boolean *arg);
|
bool msgpack_rpc_to_boolean(msgpack_object *obj, Boolean *arg)
|
||||||
bool msgpack_rpc_to_integer(msgpack_object *obj, Integer *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_float(msgpack_object *obj, Float *arg);
|
bool msgpack_rpc_to_integer(msgpack_object *obj, Integer *arg)
|
||||||
bool msgpack_rpc_to_position(msgpack_object *obj, Position *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_string(msgpack_object *obj, String *arg);
|
bool msgpack_rpc_to_float(msgpack_object *obj, Float *arg)
|
||||||
bool msgpack_rpc_to_buffer(msgpack_object *obj, Buffer *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_window(msgpack_object *obj, Window *arg);
|
bool msgpack_rpc_to_position(msgpack_object *obj, Position *arg)
|
||||||
bool msgpack_rpc_to_tabpage(msgpack_object *obj, Tabpage *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg);
|
bool msgpack_rpc_to_string(msgpack_object *obj, String *arg)
|
||||||
bool msgpack_rpc_to_stringarray(msgpack_object *obj, StringArray *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_bufferarray(msgpack_object *obj, BufferArray *arg);
|
bool msgpack_rpc_to_buffer(msgpack_object *obj, Buffer *arg)
|
||||||
bool msgpack_rpc_to_windowarray(msgpack_object *obj, WindowArray *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_tabpagearray(msgpack_object *obj, TabpageArray *arg);
|
bool msgpack_rpc_to_window(msgpack_object *obj, Window *arg)
|
||||||
bool msgpack_rpc_to_array(msgpack_object *obj, Array *arg);
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
bool msgpack_rpc_to_dictionary(msgpack_object *obj, Dictionary *arg);
|
bool msgpack_rpc_to_tabpage(msgpack_object *obj, Tabpage *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_stringarray(msgpack_object *obj, StringArray *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_bufferarray(msgpack_object *obj, BufferArray *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_windowarray(msgpack_object *obj, WindowArray *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_tabpagearray(msgpack_object *obj, TabpageArray *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_array(msgpack_object *obj, Array *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
bool msgpack_rpc_to_dictionary(msgpack_object *obj, Dictionary *arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL;
|
||||||
|
|
||||||
/// Functions for converting from C types to msgpack types.
|
/// Functions for converting from C types to msgpack types.
|
||||||
/// These are used by `msgpack_rpc_dispatch` to convert return values
|
/// These are used by `msgpack_rpc_dispatch` to convert return values
|
||||||
@@ -60,28 +91,43 @@ bool msgpack_rpc_to_dictionary(msgpack_object *obj, Dictionary *arg);
|
|||||||
///
|
///
|
||||||
/// @param result A pointer to the result
|
/// @param result A pointer to the result
|
||||||
/// @param res A packer that contains the response
|
/// @param res A packer that contains the response
|
||||||
void msgpack_rpc_from_boolean(Boolean result, msgpack_packer *res);
|
void msgpack_rpc_from_boolean(Boolean result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_integer(Integer result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_float(Float result, msgpack_packer *res);
|
void msgpack_rpc_from_integer(Integer result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_position(Position result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_string(String result, msgpack_packer *res);
|
void msgpack_rpc_from_float(Float result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_buffer(Buffer result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_window(Window result, msgpack_packer *res);
|
void msgpack_rpc_from_position(Position result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_tabpage(Tabpage result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_object(Object result, msgpack_packer *res);
|
void msgpack_rpc_from_string(String result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_stringarray(StringArray result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_bufferarray(BufferArray result, msgpack_packer *res);
|
void msgpack_rpc_from_buffer(Buffer result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_windowarray(WindowArray result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_tabpagearray(TabpageArray result, msgpack_packer *res);
|
void msgpack_rpc_from_window(Window result, msgpack_packer *res)
|
||||||
void msgpack_rpc_from_array(Array result, msgpack_packer *res);
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res);
|
void msgpack_rpc_from_tabpage(Tabpage result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_object(Object result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_stringarray(StringArray result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_bufferarray(BufferArray result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_windowarray(WindowArray result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_tabpagearray(TabpageArray result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_array(Array result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(2);
|
||||||
|
|
||||||
/// Helpers for initializing types that may be freed later
|
/// Helpers for initializing types that may be freed later
|
||||||
#define msgpack_rpc_init_boolean
|
#define msgpack_rpc_init_boolean
|
||||||
#define msgpack_rpc_init_integer
|
#define msgpack_rpc_init_integer
|
||||||
#define msgpack_rpc_init_float
|
#define msgpack_rpc_init_float
|
||||||
#define msgpack_rpc_init_position
|
#define msgpack_rpc_init_position
|
||||||
#define msgpack_rpc_init_string
|
#define msgpack_rpc_init_string = STRING_INIT
|
||||||
#define msgpack_rpc_init_buffer
|
#define msgpack_rpc_init_buffer
|
||||||
#define msgpack_rpc_init_window
|
#define msgpack_rpc_init_window
|
||||||
#define msgpack_rpc_init_tabpage
|
#define msgpack_rpc_init_tabpage
|
||||||
@@ -100,9 +146,7 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res);
|
|||||||
#define msgpack_rpc_free_integer(value)
|
#define msgpack_rpc_free_integer(value)
|
||||||
#define msgpack_rpc_free_float(value)
|
#define msgpack_rpc_free_float(value)
|
||||||
#define msgpack_rpc_free_position(value)
|
#define msgpack_rpc_free_position(value)
|
||||||
// Strings are not copied from msgpack and so don't need to be freed(they
|
void msgpack_rpc_free_string(String value);
|
||||||
// probably "live" in the msgpack streaming buffer)
|
|
||||||
#define msgpack_rpc_free_string(value)
|
|
||||||
#define msgpack_rpc_free_buffer(value)
|
#define msgpack_rpc_free_buffer(value)
|
||||||
#define msgpack_rpc_free_window(value)
|
#define msgpack_rpc_free_window(value)
|
||||||
#define msgpack_rpc_free_tabpage(value)
|
#define msgpack_rpc_free_tabpage(value)
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ void server_start(char *endpoint, ChannelProtocol prot)
|
|||||||
char *port_end;
|
char *port_end;
|
||||||
// Extract the port
|
// Extract the port
|
||||||
port = strtol(ip_end + 1, &port_end, 10);
|
port = strtol(ip_end + 1, &port_end, 10);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (errno != 0 || port == 0 || port > 0xffff) {
|
if (errno != 0 || port == 0 || port > 0xffff) {
|
||||||
// Invalid port, treat as named pipe or unix socket
|
// Invalid port, treat as named pipe or unix socket
|
||||||
server_type = kServerTypePipe;
|
server_type = kServerTypePipe;
|
||||||
@@ -156,7 +156,7 @@ void server_start(char *endpoint, ChannelProtocol prot)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Listen on named pipe or unix socket
|
// Listen on named pipe or unix socket
|
||||||
strcpy(server->socket.pipe.addr, addr);
|
xstrlcpy(server->socket.pipe.addr, addr, sizeof(server->socket.pipe.addr));
|
||||||
uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0);
|
uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0);
|
||||||
server->socket.pipe.handle.data = server;
|
server->socket.pipe.handle.data = server;
|
||||||
uv_pipe_bind(&server->socket.pipe.handle, server->socket.pipe.addr);
|
uv_pipe_bind(&server->socket.pipe.handle, server->socket.pipe.addr);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ void server_init();
|
|||||||
void server_teardown();
|
void server_teardown();
|
||||||
|
|
||||||
/// Starts listening on arbitrary tcp/unix addresses specified by
|
/// Starts listening on arbitrary tcp/unix addresses specified by
|
||||||
/// `endpoint` for API calls. The type of socket used(tcp or unix/pipe) will
|
/// `endpoint` for API calls. The type of socket used(tcp or unix/pipe) will
|
||||||
/// be determined by parsing `endpoint`: If it's a valid tcp address in the
|
/// be determined by parsing `endpoint`: If it's a valid tcp address in the
|
||||||
/// 'ip:port' format, then it will be tcp socket, else it will be a unix
|
/// 'ip:port' format, then it will be tcp socket, else it will be a unix
|
||||||
/// socket or named pipe.
|
/// socket or named pipe.
|
||||||
|
|||||||
Reference in New Issue
Block a user