// Called by libuv to allocate memory for reading. static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) { RStream *rstream = handle_get_rstream(handle); buf->len = rbuffer_available(rstream->buffer); buf->base = rbuffer_write_ptr(rstream->buffer); }
/// Copies data to `rbuffer` read queue. /// /// @param rbuffer the `RBuffer` instance /// @param buffer The buffer containing data to be copied /// @param count Number of bytes that should be copied /// @return The number of bytes actually copied size_t rbuffer_write(RBuffer *rbuffer, char *buffer, size_t count) { size_t write_count = rbuffer_available(rbuffer); if (count < write_count) { write_count = count; } if (write_count > 0) { memcpy(rbuffer_write_ptr(rbuffer), buffer, write_count); rbuffer_produced(rbuffer, write_count); } return write_count; }
size_t input_enqueue(String keys) { char *ptr = keys.data, *end = ptr + keys.size; while (rbuffer_available(input_buffer) >= 6 && ptr < end) { uint8_t buf[6] = {0}; unsigned int new_size = trans_special((uint8_t **)&ptr, buf, true); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); rbuffer_write(input_buffer, (char *)buf, new_size); continue; } if (*ptr == '<') { // Invalid key sequence, skip until the next '>' or until *end do { ptr++; } while (ptr < end && *ptr != '>'); ptr++; continue; } // copy the character, escaping CSI and K_SPECIAL if ((uint8_t)*ptr == CSI) { rbuffer_write(input_buffer, (char *)&(uint8_t){K_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KS_EXTRA}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KE_CSI}, 1); } else if ((uint8_t)*ptr == K_SPECIAL) { rbuffer_write(input_buffer, (char *)&(uint8_t){K_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KS_SPECIAL}, 1); rbuffer_write(input_buffer, (char *)&(uint8_t){KE_FILLER}, 1); } else { rbuffer_write(input_buffer, ptr, 1); } ptr++; } size_t rv = (size_t)(ptr - keys.data); process_interrupts(); return rv; }
// 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_get_rstream((uv_handle_t *)handle); rstream->uvbuf.len = rbuffer_available(rstream->buffer); rstream->uvbuf.base = rbuffer_write_ptr(rstream->buffer); // 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; if (fpos_intmax > INT64_MAX) { ELOG("stream offset overflow"); preserve_exit(); } // 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); return; } // no errors (req.result (ssize_t) is positive), it's safe to cast. size_t nread = (size_t) req.result; rbuffer_produced(rstream->buffer, nread); rstream->fpos += nread; }