aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2014-04-15 18:35:20 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2014-04-16 09:56:45 -0300
commitf276e97de9c47159f2147a3d3b0c2e2076f9d2ac (patch)
tree9fba427a2a2bfe281c95b46b44c23241c600fae4
parent6e4e40a0f7f20614dff580a29f5e9b220b72f2f8 (diff)
downloadrneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.tar.gz
rneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.tar.bz2
rneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.zip
Refactor input module to use RStream class
-rw-r--r--src/os/input.c153
1 files changed, 24 insertions, 129 deletions
diff --git a/src/os/input.c b/src/os/input.c
index 6f44df166f..dfbe5dcc05 100644
--- a/src/os/input.c
+++ b/src/os/input.c
@@ -6,6 +6,8 @@
#include "os/input.h"
#include "os/event.h"
+#include "os/rstream_defs.h"
+#include "os/rstream.h"
#include "vim.h"
#include "globals.h"
#include "ui.h"
@@ -15,7 +17,7 @@
#include "term.h"
#include "misc2.h"
-#define READ_BUFFER_LENGTH 4096
+#define READ_BUFFER_SIZE 256
typedef enum {
kInputNone,
@@ -23,101 +25,41 @@ typedef enum {
kInputEof
} InbufPollResult;
-typedef struct {
- uv_buf_t uvbuf;
- uint32_t rpos, wpos, fpos;
- char_u data[READ_BUFFER_LENGTH];
- bool reading;
-} ReadBuffer;
-
-static ReadBuffer rbuffer;
-static uv_pipe_t read_stream;
-// Use an idle handle to make reading from the fs look like a normal libuv
-// event
-static uv_idle_t fread_idle;
-static uv_handle_type read_channel_type;
-static bool eof = false;
+static RStream *read_stream;
+static bool eof = false, started_reading = false;
static InbufPollResult inbuf_poll(int32_t ms);
static void stderr_switch(void);
-static void alloc_cb(uv_handle_t *, size_t, uv_buf_t *);
-static void read_cb(uv_stream_t *, ssize_t, const uv_buf_t *);
-static void fread_idle_cb(uv_idle_t *);
+static void read_cb(RStream *rstream, void *data, bool eof);
void input_init()
{
- rbuffer.wpos = rbuffer.rpos = rbuffer.fpos = 0;
-#ifdef DEBUG
- memset(&rbuffer.data, 0, READ_BUFFER_LENGTH);
-#endif
-
- if ((read_channel_type = uv_guess_handle(read_cmd_fd)) == UV_FILE) {
- uv_idle_init(uv_default_loop(), &fread_idle);
- } else {
- uv_pipe_init(uv_default_loop(), &read_stream, 0);
- uv_pipe_open(&read_stream, read_cmd_fd);
- }
+ read_stream = rstream_new(read_cb, READ_BUFFER_SIZE, NULL);
+ rstream_set_file(read_stream, read_cmd_fd);
}
// Check if there's pending input
bool input_ready()
{
- return rbuffer.rpos < rbuffer.wpos || eof;
+ return rstream_available(read_stream) > 0 || eof;
}
// Listen for input
void input_start()
{
- // Pin the buffer used by libuv
- rbuffer.uvbuf.len = READ_BUFFER_LENGTH - rbuffer.wpos;
- rbuffer.uvbuf.base = (char *)(rbuffer.data + rbuffer.wpos);
-
- if (read_channel_type == UV_FILE) {
- // Just invoke the `fread_idle_cb` as soon as the loop starts
- uv_idle_start(&fread_idle, fread_idle_cb);
- } else {
- // Start reading
- rbuffer.reading = false;
- uv_read_start((uv_stream_t *)&read_stream, alloc_cb, read_cb);
- }
+ rstream_start(read_stream);
}
// Stop listening for input
void input_stop()
{
- if (read_channel_type == UV_FILE) {
- uv_idle_stop(&fread_idle);
- } else {
- uv_read_stop((uv_stream_t *)&read_stream);
- }
+ rstream_stop(read_stream);
}
// Copies (at most `count`) of was read from `read_cmd_fd` into `buf`
uint32_t input_read(char *buf, uint32_t count)
{
- uint32_t read_count = rbuffer.wpos - rbuffer.rpos;
-
- if (count < read_count) {
- read_count = count;
- }
-
- if (read_count > 0) {
- memcpy(buf, rbuffer.data + rbuffer.rpos, read_count);
- rbuffer.rpos += read_count;
- }
-
- if (rbuffer.wpos == READ_BUFFER_LENGTH) {
- // `wpos` is at the end of the buffer, so free some space by moving unread
- // data...
- memmove(
- rbuffer.data, // ...To the beginning of the buffer(rpos 0)
- rbuffer.data + rbuffer.rpos, // ...From the first unread position
- rbuffer.wpos - rbuffer.rpos); // ...By the number of unread bytes
- rbuffer.wpos -= rbuffer.rpos;
- rbuffer.rpos = 0;
- }
-
- return read_count;
+ return rstream_read(read_stream, buf, count);
}
@@ -188,7 +130,9 @@ static InbufPollResult inbuf_poll(int32_t ms)
}
if (event_poll(ms)) {
- return eof && rbuffer.rpos == rbuffer.wpos ? kInputEof : kInputAvail;
+ return eof && rstream_available(read_stream) == 0 ?
+ kInputEof :
+ kInputAvail;
}
return kInputNone;
@@ -201,69 +145,22 @@ static void stderr_switch()
// cooked mode
settmode(TMODE_COOK);
// Stop the idle handle
- uv_idle_stop(&fread_idle);
+ rstream_stop(read_stream);
// Use stderr for stdin, also works for shell commands.
read_cmd_fd = 2;
// Initialize and start the input stream
- uv_pipe_init(uv_default_loop(), &read_stream, 0);
- uv_pipe_open(&read_stream, read_cmd_fd);
- uv_read_start((uv_stream_t *)&read_stream, alloc_cb, read_cb);
- rbuffer.reading = false;
+ rstream_set_file(read_stream, read_cmd_fd);
+ rstream_start(read_stream);
// Set the mode back to what it was
settmode(mode);
}
-// Called by libuv to allocate memory for reading.
-static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
+static void read_cb(RStream *rstream, void *data, bool at_eof)
{
- if (rbuffer.reading) {
- buf->len = 0;
- return;
- }
-
- buf->base = rbuffer.uvbuf.base;
- buf->len = rbuffer.uvbuf.len;
- // Avoid `alloc_cb`, `alloc_cb` sequences on windows
- rbuffer.reading = true;
-}
-
-// Callback invoked by libuv after it copies the data into the buffer provided
-// by `alloc_cb`. This is also called on EOF or when `alloc_cb` returns a
-// 0-length buffer.
-static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf)
-{
- if (cnt <= 0) {
- if (cnt != UV_ENOBUFS) {
- // Read error or EOF, either way vim must exit
- eof = true;
- }
- return;
- }
-
- // Data was already written, so all we need is to update 'wpos' to reflect
- // the space actually used in the buffer.
- rbuffer.wpos += cnt;
-}
-
-// Called by the by the 'idle' handle to emulate a reading event
-static void fread_idle_cb(uv_idle_t *handle)
-{
- uv_fs_t req;
-
- // Synchronous read
- uv_fs_read(
- uv_default_loop(),
- &req,
- read_cmd_fd,
- &rbuffer.uvbuf,
- 1,
- rbuffer.fpos,
- NULL);
-
- uv_fs_req_cleanup(&req);
-
- if (req.result <= 0) {
- if (rbuffer.fpos == 0 && uv_guess_handle(2) == UV_TTY) {
+ if (at_eof) {
+ if (!started_reading
+ && rstream_is_regular_file(rstream)
+ && uv_guess_handle(2) == UV_TTY) {
// Read error. Since stderr is a tty we switch to reading from it. This
// is for handling for cases like "foo | xargs vim" because xargs
// redirects stdin from /dev/null. Previously, this was done in ui.c
@@ -271,9 +168,7 @@ static void fread_idle_cb(uv_idle_t *handle)
} else {
eof = true;
}
- return;
}
- rbuffer.wpos += req.result;
- rbuffer.fpos += req.result;
+ started_reading = true;
}