From 358fe01fc2a0e1c5765179d8b3c8cbc85c4a2cbd Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 8 Jun 2021 13:38:33 -0400 Subject: [PATCH] Issue #211 - production version of (char-ready?) --- CHANGELOG.md | 1 + include/cyclone/runtime.h | 1 + runtime.c | 33 ++++++--------------------------- scheme/base.sld | 9 +++++++++ 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db258c1..188b927a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Features - Improve performance of runtime by more efficiently unboxing known fixnums. - Improve performance of compiled code slightly by using more efficient closure calls when possible. - Add support for R7RS `#d` decimal specifier for numbers. +- Added `char-ready?` to `(scheme base)` Bug Fixes diff --git a/include/cyclone/runtime.h b/include/cyclone/runtime.h index e0978bb6..d175fb68 100644 --- a/include/cyclone/runtime.h +++ b/include/cyclone/runtime.h @@ -368,6 +368,7 @@ object Cyc_io_close_output_port(void *data, object port); object Cyc_io_flush_output_port(void *data, object port); object Cyc_io_read_char(void *data, object cont, object port); object Cyc_io_peek_char(void *data, object cont, object port); +object Cyc_io_char_ready(void *data, object port); object Cyc_write_u8(void *data, object c, object port); object Cyc_io_read_u8(void *data, object cont, object port); object Cyc_io_peek_u8(void *data, object cont, object port); diff --git a/runtime.c b/runtime.c index 3f719383..97d417b1 100644 --- a/runtime.c +++ b/runtime.c @@ -7728,21 +7728,16 @@ static void _read_return_atom(void *data, object cont, port_type *p) object Cyc_io_char_ready(void *data, object port) { - FILE *stream; - port_type *p; - Cyc_check_port(data, port); { - p = (port_type *)port; - stream = ((port_type *) port)->fp; + port_type *p = (port_type *)port; + FILE *stream = p->fp; if (stream == NULL) { Cyc_rt_raise2(data, "Unable to read from closed port: ", port); } -// TODO: this may be linux-specific -// TODO: what about EOF? if (p->mem_buf_len == 0 || p->mem_buf_len == p->buf_idx) { - // TODO: slow path, does stream have data ready? + // Slow path, check if underlying stream has data ready int fd = fileno(stream); fd_set rfds; struct timeval tv; @@ -7751,10 +7746,11 @@ object Cyc_io_char_ready(void *data, object port) FD_SET(fd, &rfds); tv.tv_sec = 0; tv.tv_usec = 0; - retval = select(fd + 1, &rfds, NULL, NULL, &tv); + retval = select(fd + 1, &rfds, NULL, NULL, &tv); // Non-blocking fd check return (retval ? boolean_t : boolean_f); } else { - return boolean_t; + // Fast path, port has buffered data ready to go + return boolean_t; } } } @@ -7849,23 +7845,6 @@ object Cyc_io_peek_u8(void *data, object cont, object port) return Cyc_EOF; } -// TODO: full requirements are: -// -// Returns #t if a character is ready on the textual input -// port and returns #f otherwise. If char-ready returns #t -// then the next read-char operation on the given port is -// guaranteed not to hang. If the port is at end of file then -// char-ready? returns #t. -// -// This is a bit of a challenge because the internal buffers -// cannot differentiate between being empty and being at EOF. -// -//object Cyc_io_char_ready(void *data, object cont, object port) -//{ -// port_type *p = (port_type *)port; -// Cyc_check_port(data, port); -//} - object Cyc_io_read_char(void *data, object cont, object port) { port_type *p = (port_type *)port; diff --git a/scheme/base.sld b/scheme/base.sld index 018dee6b..9bd3c826 100644 --- a/scheme/base.sld +++ b/scheme/base.sld @@ -145,6 +145,7 @@ write-string-1 write-string-2 flush-output-port + char-ready? peek-char read-char read-line @@ -676,6 +677,14 @@ (if (null? port) (_write-u8 chr (current-output-port)) (_write-u8 chr (car port)))) + (define-c Cyc-char-ready? + "(void *data, int argc, closure _, object k, object port)" + " object rv = Cyc_io_char_ready(data, port); + return_closcall1(data, k, rv); ") + (define (char-ready? . port) + (if (null? port) + (Cyc-char-ready? (current-input-port)) + (Cyc-char-ready? (car port)))) (define (peek-char . port) (if (null? port) (Cyc-peek-char (current-input-port))