mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
refactor(os/shell): we have DynamicBuffer at home
DynamicBuffer at home: KVÄCK
This commit is contained in:
@@ -47,17 +47,11 @@
|
|||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/vim_defs.h"
|
#include "nvim/vim_defs.h"
|
||||||
|
|
||||||
#define DYNAMIC_BUFFER_INIT { NULL, 0, 0 }
|
|
||||||
#define NS_1_SECOND 1000000000U // 1 second, in nanoseconds
|
#define NS_1_SECOND 1000000000U // 1 second, in nanoseconds
|
||||||
#define OUT_DATA_THRESHOLD 1024 * 10U // 10KB, "a few screenfuls" of data.
|
#define OUT_DATA_THRESHOLD 1024 * 10U // 10KB, "a few screenfuls" of data.
|
||||||
|
|
||||||
#define SHELL_SPECIAL "\t \"&'$;<>()\\|"
|
#define SHELL_SPECIAL "\t \"&'$;<>()\\|"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *data;
|
|
||||||
size_t cap, len;
|
|
||||||
} DynamicBuffer;
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "os/shell.c.generated.h"
|
# include "os/shell.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -667,7 +661,7 @@ char *shell_argv_to_str(char **const argv)
|
|||||||
/// @return shell command exit code
|
/// @return shell command exit code
|
||||||
int os_call_shell(char *cmd, ShellOpts opts, char *extra_args)
|
int os_call_shell(char *cmd, ShellOpts opts, char *extra_args)
|
||||||
{
|
{
|
||||||
DynamicBuffer input = DYNAMIC_BUFFER_INIT;
|
StringBuilder input = KV_INITIAL_VALUE;
|
||||||
char *output = NULL;
|
char *output = NULL;
|
||||||
char **output_ptr = NULL;
|
char **output_ptr = NULL;
|
||||||
int current_state = State;
|
int current_state = State;
|
||||||
@@ -696,9 +690,9 @@ int os_call_shell(char *cmd, ShellOpts opts, char *extra_args)
|
|||||||
|
|
||||||
size_t nread;
|
size_t nread;
|
||||||
int exitcode = do_os_system(shell_build_argv(cmd, extra_args),
|
int exitcode = do_os_system(shell_build_argv(cmd, extra_args),
|
||||||
input.data, input.len, output_ptr, &nread,
|
input.items, input.size, output_ptr, &nread,
|
||||||
emsg_silent, forward_output);
|
emsg_silent, forward_output);
|
||||||
xfree(input.data);
|
kv_destroy(input);
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
write_output(output, nread, true);
|
write_output(output, nread, true);
|
||||||
@@ -862,7 +856,7 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
|||||||
bool has_input = (input != NULL && input[0] != NUL);
|
bool has_input = (input != NULL && input[0] != NUL);
|
||||||
|
|
||||||
// the output buffer
|
// the output buffer
|
||||||
DynamicBuffer buf = DYNAMIC_BUFFER_INIT;
|
StringBuilder buf = KV_INITIAL_VALUE;
|
||||||
stream_read_cb data_cb = system_data_cb;
|
stream_read_cb data_cb = system_data_cb;
|
||||||
if (nread) {
|
if (nread) {
|
||||||
*nread = 0;
|
*nread = 0;
|
||||||
@@ -950,18 +944,17 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
|||||||
|
|
||||||
// prepare the out parameters if requested
|
// prepare the out parameters if requested
|
||||||
if (output) {
|
if (output) {
|
||||||
if (buf.len == 0) {
|
assert(nread);
|
||||||
|
if (buf.size == 0) {
|
||||||
// no data received from the process, return NULL
|
// no data received from the process, return NULL
|
||||||
*output = NULL;
|
*output = NULL;
|
||||||
xfree(buf.data);
|
*nread = 0;
|
||||||
|
kv_destroy(buf);
|
||||||
} else {
|
} else {
|
||||||
|
*nread = buf.size;
|
||||||
// NUL-terminate to make the output directly usable as a C string
|
// NUL-terminate to make the output directly usable as a C string
|
||||||
buf.data[buf.len] = NUL;
|
kv_push(buf, NUL);
|
||||||
*output = buf.data;
|
*output = buf.items;
|
||||||
}
|
|
||||||
|
|
||||||
if (nread) {
|
|
||||||
*nread = buf.len;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,28 +964,10 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu
|
|||||||
return exitcode;
|
return exitcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// - ensures at least `desired` bytes in buffer
|
|
||||||
///
|
|
||||||
/// TODO(aktau): fold with kvec/garray
|
|
||||||
static void dynamic_buffer_ensure(DynamicBuffer *buf, size_t desired)
|
|
||||||
{
|
|
||||||
if (buf->cap >= desired) {
|
|
||||||
assert(buf->data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->cap = desired;
|
|
||||||
kv_roundup32(buf->cap);
|
|
||||||
buf->data = xrealloc(buf->data, buf->cap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t system_data_cb(RStream *stream, const char *buf, size_t count, void *data, bool eof)
|
static size_t system_data_cb(RStream *stream, const char *buf, size_t count, void *data, bool eof)
|
||||||
{
|
{
|
||||||
DynamicBuffer *dbuf = data;
|
StringBuilder *dbuf = data;
|
||||||
|
kv_concat_len(*dbuf, buf, count);
|
||||||
dynamic_buffer_ensure(dbuf, dbuf->len + count + 1);
|
|
||||||
memcpy(dbuf->data + dbuf->len, buf, count);
|
|
||||||
dbuf->len += count;
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,7 +1198,7 @@ static size_t word_length(const char *str)
|
|||||||
/// event loop starts. If we don't (by writing in chunks returned by `ml_get`)
|
/// event loop starts. If we don't (by writing in chunks returned by `ml_get`)
|
||||||
/// the buffer being modified might get modified by reading from the process
|
/// the buffer being modified might get modified by reading from the process
|
||||||
/// before we finish writing.
|
/// before we finish writing.
|
||||||
static void read_input(DynamicBuffer *buf)
|
static void read_input(StringBuilder *buf)
|
||||||
{
|
{
|
||||||
size_t written = 0;
|
size_t written = 0;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -1237,14 +1212,11 @@ static void read_input(DynamicBuffer *buf)
|
|||||||
} else if (lp[written] == NL) {
|
} else if (lp[written] == NL) {
|
||||||
// NL -> NUL translation
|
// NL -> NUL translation
|
||||||
len = 1;
|
len = 1;
|
||||||
dynamic_buffer_ensure(buf, buf->len + len);
|
kv_push(*buf, NUL);
|
||||||
buf->data[buf->len++] = NUL;
|
|
||||||
} else {
|
} else {
|
||||||
char *s = vim_strchr(lp + written, NL);
|
char *s = vim_strchr(lp + written, NL);
|
||||||
len = s == NULL ? l : (size_t)(s - (lp + written));
|
len = s == NULL ? l : (size_t)(s - (lp + written));
|
||||||
dynamic_buffer_ensure(buf, buf->len + len);
|
kv_concat_len(*buf, lp + written, len);
|
||||||
memcpy(buf->data + buf->len, lp + written, len);
|
|
||||||
buf->len += len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == l) {
|
if (len == l) {
|
||||||
@@ -1253,8 +1225,7 @@ static void read_input(DynamicBuffer *buf)
|
|||||||
|| (!curbuf->b_p_bin && curbuf->b_p_fixeol)
|
|| (!curbuf->b_p_bin && curbuf->b_p_fixeol)
|
||||||
|| (lnum != curbuf->b_no_eol_lnum
|
|| (lnum != curbuf->b_no_eol_lnum
|
||||||
&& (lnum != curbuf->b_ml.ml_line_count || curbuf->b_p_eol))) {
|
&& (lnum != curbuf->b_ml.ml_line_count || curbuf->b_p_eol))) {
|
||||||
dynamic_buffer_ensure(buf, buf->len + 1);
|
kv_push(*buf, NL);
|
||||||
buf->data[buf->len++] = NL;
|
|
||||||
}
|
}
|
||||||
lnum++;
|
lnum++;
|
||||||
if (lnum > curbuf->b_op_end.lnum) {
|
if (lnum > curbuf->b_op_end.lnum) {
|
||||||
|
Reference in New Issue
Block a user