[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 01/02: scm_fill_input can guarantee a minimum fill amoun
From: |
Andy Wingo |
Subject: |
[Guile-commits] 01/02: scm_fill_input can guarantee a minimum fill amount |
Date: |
Sun, 01 May 2016 15:01:48 +0000 |
wingo pushed a commit to branch wip-port-refactor
in repository guile.
commit 56c48d14ac99f0c7399a09873bd29d2120c48dbe
Author: Andy Wingo <address@hidden>
Date: Sun May 1 14:29:17 2016 +0200
scm_fill_input can guarantee a minimum fill amount
* libguile/ports.h (scm_fill_input): Add "minimum_size" argument. Adapt
all callers to pass 0 as this argument.
* libguile/ports.c (scm_i_read): Inline into scm_fill_input.
(scm_fill_input): "minimum_size" argument ensures that there are a
certain number of bytes available, or EOF. Instead of shrinking the
read buffer, only fill by the read_buffering amount, or the
minimum_size, whichever is larger.
* libguile/r6rs-ports.c:
* libguile/read.c: Adapt scm_fill_input callers.
---
libguile/ports.c | 77 +++++++++++++++++++++++++++++++------------------
libguile/ports.h | 2 +-
libguile/r6rs-ports.c | 2 +-
libguile/read.c | 2 +-
4 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/libguile/ports.c b/libguile/ports.c
index 319b5f5..13e2895 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -1414,7 +1414,7 @@ get_byte_or_eof (SCM port)
return ret;
}
- buf = scm_fill_input (port);
+ buf = scm_fill_input (port, 0);
buf_bv = scm_port_buffer_bytevector (buf);
buf_cur = scm_port_buffer_cur (buf);
buf_end = scm_port_buffer_end (buf);
@@ -1453,7 +1453,7 @@ peek_byte_or_eof (SCM port)
return ret;
}
- buf = scm_fill_input (port);
+ buf = scm_fill_input (port, 0);
buf_bv = scm_port_buffer_bytevector (buf);
buf_cur = scm_port_buffer_cur (buf);
buf_end = scm_port_buffer_end (buf);
@@ -1495,21 +1495,6 @@ scm_i_read_bytes (SCM port, SCM dst, size_t start,
size_t count)
return filled;
}
-/* scm_i_read is used internally to add bytes to the given port
- buffer. If the number of available bytes in the buffer does not
- increase after a call to scm_i_read, that indicates EOF. */
-static void
-scm_i_read (SCM port, SCM buf)
-{
- size_t count;
-
- count = scm_i_read_bytes (port, scm_port_buffer_bytevector (buf),
- scm_to_size_t (scm_port_buffer_end (buf)),
- scm_port_buffer_can_put (buf));
- scm_port_buffer_did_put (buf, count);
- scm_port_buffer_set_has_eof_p (buf, scm_from_bool (count == 0));
-}
-
/* Used by an application to read arbitrary number of bytes from an SCM
port. Same semantics as libc read, except that scm_c_read_bytes only
returns less than SIZE bytes if at end-of-file.
@@ -1548,7 +1533,7 @@ scm_c_read_bytes (SCM port, SCM dst, size_t start, size_t
count)
buffer directly. */
if (to_read < pt->read_buffering)
{
- read_buf = scm_fill_input (port);
+ read_buf = scm_fill_input (port, 0);
did_read = scm_port_buffer_take (read_buf, dst_ptr, to_read);
dst_ptr += did_read;
to_read -= did_read;
@@ -1598,7 +1583,7 @@ scm_c_read (SCM port, void *buffer, size_t size)
while (copied < size)
{
size_t count;
- read_buf = scm_fill_input (port);
+ read_buf = scm_fill_input (port, 0);
count = scm_port_buffer_take (read_buf, dst + copied, size - copied);
copied += count;
if (count == 0)
@@ -2451,26 +2436,62 @@ scm_flush (SCM port)
}
SCM
-scm_fill_input (SCM port)
+scm_fill_input (SCM port, size_t minimum_size)
{
scm_t_port *pt = SCM_PTAB_ENTRY (port);
SCM read_buf = pt->read_buf;
+ size_t buffered = scm_port_buffer_can_take (read_buf);
- if (scm_port_buffer_can_take (read_buf) ||
- scm_is_true (scm_port_buffer_has_eof_p (read_buf)))
+ if (minimum_size == 0)
+ minimum_size = 1;
+
+ if (buffered >= minimum_size
+ || scm_is_true (scm_port_buffer_has_eof_p (read_buf)))
return read_buf;
if (pt->rw_random)
scm_flush (pt->port);
- /* It could be that putback caused us to enlarge the buffer; now that
- we've read all the bytes we need to shrink it again. */
- if (scm_port_buffer_size (read_buf) != pt->read_buffering)
- read_buf = pt->read_buf = scm_c_make_port_buffer (pt->read_buffering);
- else
+ /* Prepare to read. Make sure there is enough space in the buffer for
+ minimum_size, and ensure that cur is zero so that we fill towards
+ the end of the buffer. */
+ if (minimum_size > scm_port_buffer_size (read_buf))
+ {
+ /* Grow the read buffer. */
+ SCM new_buf = scm_c_make_port_buffer (minimum_size);
+ scm_port_buffer_reset (new_buf);
+ scm_port_buffer_put (new_buf,
+ scm_port_buffer_take_pointer (read_buf),
+ buffered);
+ pt->read_buf = read_buf = new_buf;
+ }
+ else if (buffered == 0)
scm_port_buffer_reset (read_buf);
+ else
+ {
+ const scm_t_uint8 *to_shift = scm_port_buffer_take_pointer (read_buf);
+ scm_port_buffer_reset (read_buf);
+ memmove (scm_port_buffer_put_pointer (read_buf), to_shift, buffered);
+ scm_port_buffer_did_put (read_buf, buffered);
+ }
- scm_i_read (port, read_buf);
+ while (buffered < minimum_size
+ && !scm_is_true (scm_port_buffer_has_eof_p (read_buf)))
+ {
+ size_t count;
+ size_t buffering = pt->read_buffering;
+ size_t to_read;
+
+ if (pt->read_buffering < minimum_size)
+ buffering = minimum_size;
+ to_read = buffering - buffered;
+
+ count = scm_i_read_bytes (port, scm_port_buffer_bytevector (read_buf),
+ buffered, to_read);
+ buffered += count;
+ scm_port_buffer_did_put (read_buf, count);
+ scm_port_buffer_set_has_eof_p (read_buf, scm_from_bool (count == 0));
+ }
return read_buf;
}
diff --git a/libguile/ports.h b/libguile/ports.h
index 2a6e42c..189141f 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -310,7 +310,7 @@ SCM_API SCM scm_unread_string (SCM str, SCM port);
/* Manipulating the buffers. */
SCM_API SCM scm_setvbuf (SCM port, SCM mode, SCM size);
-SCM_API SCM scm_fill_input (SCM port);
+SCM_API SCM scm_fill_input (SCM port, size_t minimum_size);
SCM_INTERNAL size_t scm_take_from_input_buffers (SCM port, char *dest, size_t
read_len);
SCM_API SCM scm_drain_input (SCM port);
SCM_API void scm_end_input (SCM port);
diff --git a/libguile/r6rs-ports.c b/libguile/r6rs-ports.c
index 8a7fddd..aea1c3a 100644
--- a/libguile/r6rs-ports.c
+++ b/libguile/r6rs-ports.c
@@ -474,7 +474,7 @@ SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some",
1, 0, 0,
SCM_VALIDATE_BINARY_INPUT_PORT (1, port);
- buf = scm_fill_input (port);
+ buf = scm_fill_input (port, 0);
size = scm_port_buffer_can_take (buf);
if (size == 0)
{
diff --git a/libguile/read.c b/libguile/read.c
index 20de0bb..cd90b20 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -2073,7 +2073,7 @@ scm_i_scan_for_encoding (SCM port)
if (scm_port_buffer_can_take (buf) == 0)
{
/* We can use the read buffer, and thus avoid a seek. */
- buf = scm_fill_input (port);
+ buf = scm_fill_input (port, 0);
bytes_read = scm_port_buffer_can_take (buf);
if (bytes_read > SCM_ENCODING_SEARCH_SIZE)
bytes_read = SCM_ENCODING_SEARCH_SIZE;