diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-15 18:35:20 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-16 09:56:45 -0300 |
commit | f276e97de9c47159f2147a3d3b0c2e2076f9d2ac (patch) | |
tree | 9fba427a2a2bfe281c95b46b44c23241c600fae4 | |
parent | 6e4e40a0f7f20614dff580a29f5e9b220b72f2f8 (diff) | |
download | rneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.tar.gz rneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.tar.bz2 rneovim-f276e97de9c47159f2147a3d3b0c2e2076f9d2ac.zip |
Refactor input module to use RStream class
-rw-r--r-- | src/os/input.c | 153 |
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; } |