guile-commits
[Top][All Lists]
Advanced

[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;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]