// 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) { RStream *rstream = stream->data; if (cnt <= 0) { if (cnt != UV_ENOBUFS) { // Read error or EOF, either way stop the stream and invoke the callback // with eof == true uv_read_stop(stream); emit_read_event(rstream, true); } return; } // at this point we're sure that cnt is positive, no error occurred size_t nread = (size_t) cnt; // Data was already written, so all we need is to update 'wpos' to reflect // the space actually used in the buffer. rstream->wpos += nread; if (rstream->wpos == rstream->buffer_size) { // The last read filled the buffer, stop reading for now rstream_stop(rstream); } rstream->reading = false; emit_read_event(rstream, false); }
// 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; RStream *rstream = handle->data; rstream->uvbuf.base = rstream->buffer + rstream->wpos; rstream->uvbuf.len = rstream->buffer_size - rstream->wpos; // the offset argument to uv_fs_read is int64_t, could someone really try // to read more than 9 quintillion (9e18) bytes? // upcast is meant to avoid tautological condition warning on 32 bits uintmax_t fpos_intmax = rstream->fpos; assert(fpos_intmax <= INT64_MAX); // Synchronous read uv_fs_read( uv_default_loop(), &req, rstream->fd, &rstream->uvbuf, 1, (int64_t) rstream->fpos, NULL); uv_fs_req_cleanup(&req); if (req.result <= 0) { uv_idle_stop(rstream->fread_idle); emit_read_event(rstream, true); return; } // no errors (req.result (ssize_t) is positive), it's safe to cast. size_t nread = (size_t) req.result; rstream->wpos += nread; rstream->fpos += nread; if (rstream->wpos == rstream->buffer_size) { // The last read filled the buffer, stop reading for now rstream_stop(rstream); } emit_read_event(rstream, false); }
// 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; RStream *rstream = handle->data; rstream->uvbuf.base = rstream->buffer + rstream->wpos; rstream->uvbuf.len = rstream->buffer_size - rstream->wpos; // the offset argument to uv_fs_read is int64_t, could someone really try // to read more than 9 quintillion (9e18) bytes? // DISABLED TO FIX BROKEN BUILD ON 32bit // TODO(elmart): Review types to allow assertion // assert(rstream->fpos <= INT64_MAX); // Synchronous read uv_fs_read( uv_default_loop(), &req, rstream->fd, &rstream->uvbuf, 1, (int64_t) rstream->fpos, NULL); uv_fs_req_cleanup(&req); if (req.result <= 0) { uv_idle_stop(rstream->fread_idle); emit_read_event(rstream, true); return; } // no errors (req.result (ssize_t) is positive), it's safe to cast. size_t nread = (size_t) req.result; rstream->wpos += nread; rstream->fpos += nread; if (rstream->wpos == rstream->buffer_size) { // The last read filled the buffer, stop reading for now rstream_stop(rstream); } emit_read_event(rstream, false); }