guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 07/07: Port buffers are Scheme values


From: Andy Wingo
Subject: [Guile-commits] 07/07: Port buffers are Scheme values
Date: Thu, 21 Apr 2016 08:28:11 +0000

wingo pushed a commit to branch wip-port-refactor
in repository guile.

commit 5a342f61c4b09e503918b8bd2d996f138b114849
Author: Andy Wingo <address@hidden>
Date:   Wed Apr 20 09:09:15 2016 +0200

    Port buffers are Scheme values
    
    * libguile/ports-internal.h (scm_port_buffer_bytevector)
      (scm_port_buffer_cur, scm_port_buffer_set_cur)
      (scm_port_buffer_end, scm_port_buffer_set_end)
      (scm_port_buffer_has_eof_p, scm_port_buffer_set_has_eof_p): New
      helpers.
    * libguile/ports-internal.h (scm_port_buffer_size)
      (scm_port_buffer_reset, scm_port_buffer_reset_end)
      (scm_port_buffer_can_take, scm_port_buffer_can_put)
      (scm_port_buffer_can_putback, scm_port_buffer_did_take)
      (scm_port_buffer_did_put, scm_port_buffer_take_pointer)
      (scm_port_buffer_put_pointer, scm_port_buffer_take)
      (scm_port_buffer_put, scm_port_buffer_putback): Adapt to treat port
      buffers as SCM values and use helpers to access them.
    * libguile/ports.c (scm_i_clear_pending_eof, scm_i_set_pending_eof)
      (scm_c_make_port_buffer, scm_i_read_unlocked)
      (scm_c_read_bytes_unlocked, scm_i_unget_bytes_unlocked)
      (scm_setvbuf, scm_fill_input, scm_take_from_input_buffers)
      (scm_drain_input, scm_end_input_unlocked, scm_flush_unlocked)
      (scm_fill_input_unlocked, scm_i_write_unlocked)
      (scm_c_write_bytes_unlocked, scm_c_write_unlocked)
      (scm_char_ready_p): Adapt to treat port buffers as SCM values and use
      helpers to access them.
      (scm_port_read_buffer, scm_port_write_buffer): New functions,
      allowing (ice-9 ports) to access port buffers.
    * libguile/ports.h: Update comments on port buffers.  Replace
      scm_t_port_buffer structure with a Scheme vector whose fields are
      enumerated by "enum scm_port_buffer_field".
      (scm_get_byte_or_eof_unlocked, scm_peek_byte_or_eof_unlocked): Adapt
      these implementations to port buffer representation change.
    * libguile/r6rs-ports.c (scm_get_bytevector_some):
    * libguile/read.c (scm_i_scan_for_encoding):
    * libguile/rw.c (scm_write_string_partial): Port buffers are Scheme
      objects.
---
 libguile/ports-internal.h |  125 +++++++++++++++++++++++++++-------------
 libguile/ports.c          |  138 ++++++++++++++++++++++++++++++---------------
 libguile/ports.h          |  123 ++++++++++++++++++++++------------------
 libguile/r6rs-ports.c     |    4 +-
 libguile/read.c           |    2 +-
 libguile/rw.c             |    2 +-
 6 files changed, 252 insertions(+), 142 deletions(-)

diff --git a/libguile/ports-internal.h b/libguile/ports-internal.h
index a8c4ea9..19e49a7 100644
--- a/libguile/ports-internal.h
+++ b/libguile/ports-internal.h
@@ -39,88 +39,132 @@
    can_foo and size functions, and otherwise assume that the cur and end
    values are inums within the right ranges.  */
 
+static inline SCM
+scm_port_buffer_bytevector (SCM buf)
+{
+  return SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_BYTEVECTOR);
+}
+
+static inline SCM
+scm_port_buffer_cur (SCM buf)
+{
+  return SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_CUR);
+}
+
+static inline void
+scm_port_buffer_set_cur (SCM buf, SCM cur)
+{
+  SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_CUR, cur);
+}
+
+static inline SCM
+scm_port_buffer_end (SCM buf)
+{
+  return SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_END);
+}
+
+static inline void
+scm_port_buffer_set_end (SCM buf, SCM end)
+{
+  SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_END, end);
+}
+
+static inline SCM
+scm_port_buffer_has_eof_p (SCM buf)
+{
+  return SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_HAS_EOF_P);
+}
+
+static inline void
+scm_port_buffer_set_has_eof_p (SCM buf, SCM has_eof_p)
+{
+  SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_HAS_EOF_P,
+                         has_eof_p);
+}
+
 static inline size_t
-scm_port_buffer_size (scm_t_port_buffer *buf)
+scm_port_buffer_size (SCM buf)
 {
-  if (SCM_LIKELY (SCM_BYTEVECTOR_P (buf->bytevector)))
-    return SCM_BYTEVECTOR_LENGTH (buf->bytevector);
-  scm_misc_error (NULL, "invalid port buffer ~a",
-                  scm_list_1 (buf->bytevector));
+  SCM bv = scm_port_buffer_bytevector (buf);
+  if (SCM_LIKELY (SCM_BYTEVECTOR_P (bv)))
+    return SCM_BYTEVECTOR_LENGTH (bv);
+  scm_misc_error (NULL, "invalid port buffer ~a", scm_list_1 (bv));
   return -1;
 }
 
 static inline void
-scm_port_buffer_reset (scm_t_port_buffer *buf)
+scm_port_buffer_reset (SCM buf)
 {
-  buf->cur = buf->end = SCM_INUM0;
+  scm_port_buffer_set_cur (buf, SCM_INUM0);
+  scm_port_buffer_set_end (buf, SCM_INUM0);
 }
 
 static inline void
-scm_port_buffer_reset_end (scm_t_port_buffer *buf)
+scm_port_buffer_reset_end (SCM buf)
 {
-  buf->cur = buf->end = scm_from_size_t (scm_port_buffer_size (buf));
+  scm_port_buffer_set_cur (buf, scm_from_size_t (scm_port_buffer_size (buf)));
+  scm_port_buffer_set_end (buf, scm_from_size_t (scm_port_buffer_size (buf)));
 }
 
 static inline size_t
-scm_port_buffer_can_take (scm_t_port_buffer *buf)
+scm_port_buffer_can_take (SCM buf)
 {
   size_t cur, end;
-  cur = scm_to_size_t (buf->cur);
-  end = scm_to_size_t (buf->end);
+  cur = scm_to_size_t (scm_port_buffer_cur (buf));
+  end = scm_to_size_t (scm_port_buffer_end (buf));
   if (cur > end || end > scm_port_buffer_size (buf))
-    scm_misc_error (NULL, "invalid port buffer cursors ~a, ~a",
-                    scm_list_2 (buf->cur, buf->end));
+    scm_misc_error (NULL, "invalid port buffer ~a", scm_list_1 (buf));
   return end - cur;
 }
 
 static inline size_t
-scm_port_buffer_can_put (scm_t_port_buffer *buf)
+scm_port_buffer_can_put (SCM buf)
 {
-  size_t end = scm_to_size_t (buf->end);
+  size_t end = scm_to_size_t (scm_port_buffer_end (buf));
   if (end > scm_port_buffer_size (buf))
-    scm_misc_error (NULL, "invalid port buffer cursor ~a",
-                    scm_list_1 (buf->end));
+    scm_misc_error (NULL, "invalid port buffer ~a", scm_list_1 (buf));
   return scm_port_buffer_size (buf) - end;
 }
 
 static inline size_t
-scm_port_buffer_can_putback (scm_t_port_buffer *buf)
+scm_port_buffer_can_putback (SCM buf)
 {
-  size_t cur = scm_to_size_t (buf->cur);
+  size_t cur = scm_to_size_t (scm_port_buffer_cur (buf));
   if (cur > scm_port_buffer_size (buf))
-    scm_misc_error (NULL, "invalid port buffer cursor ~a",
-                    scm_list_1 (buf->cur));
+    scm_misc_error (NULL, "invalid port buffer ~a", scm_list_1 (buf));
   return cur;
 }
 
 static inline void
-scm_port_buffer_did_take (scm_t_port_buffer *buf, size_t count)
+scm_port_buffer_did_take (SCM buf, size_t count)
 {
-  buf->cur = SCM_I_MAKINUM (SCM_I_INUM (buf->cur) + count);
+  scm_port_buffer_set_cur
+    (buf, SCM_I_MAKINUM (SCM_I_INUM (scm_port_buffer_cur (buf)) + count));
 }
 
 static inline void
-scm_port_buffer_did_put (scm_t_port_buffer *buf, size_t count)
+scm_port_buffer_did_put (SCM buf, size_t count)
 {
-  buf->end = SCM_I_MAKINUM (SCM_I_INUM (buf->end) + count);
+  scm_port_buffer_set_end
+    (buf, SCM_I_MAKINUM (SCM_I_INUM (scm_port_buffer_end (buf)) + count));
 }
 
 static inline const scm_t_uint8 *
-scm_port_buffer_take_pointer (scm_t_port_buffer *buf)
+scm_port_buffer_take_pointer (SCM buf)
 {
-  signed char *ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector);
-  return ((scm_t_uint8 *) ret) + scm_to_size_t (buf->cur);
+  signed char *ret = SCM_BYTEVECTOR_CONTENTS (scm_port_buffer_bytevector 
(buf));
+  return ((scm_t_uint8 *) ret) + scm_to_size_t (scm_port_buffer_cur (buf));
 }
 
 static inline scm_t_uint8 *
-scm_port_buffer_put_pointer (scm_t_port_buffer *buf)
+scm_port_buffer_put_pointer (SCM buf)
 {
-  signed char *ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector);
-  return ((scm_t_uint8 *) ret) + scm_to_size_t (buf->end);
+  signed char *ret = SCM_BYTEVECTOR_CONTENTS (scm_port_buffer_bytevector 
(buf));
+  return ((scm_t_uint8 *) ret) + scm_to_size_t (scm_port_buffer_end (buf));
 }
 
 static inline size_t
-scm_port_buffer_take (scm_t_port_buffer *buf, scm_t_uint8 *dst, size_t count)
+scm_port_buffer_take (SCM buf, scm_t_uint8 *dst, size_t count)
 {
   count = min (count, scm_port_buffer_can_take (buf));
   if (dst)
@@ -130,8 +174,7 @@ scm_port_buffer_take (scm_t_port_buffer *buf, scm_t_uint8 
*dst, size_t count)
 }
 
 static inline size_t
-scm_port_buffer_put (scm_t_port_buffer *buf, const scm_t_uint8 *src,
-                     size_t count)
+scm_port_buffer_put (SCM buf, const scm_t_uint8 *src, size_t count)
 {
   count = min (count, scm_port_buffer_can_put (buf));
   if (src)
@@ -141,15 +184,17 @@ scm_port_buffer_put (scm_t_port_buffer *buf, const 
scm_t_uint8 *src,
 }
 
 static inline void
-scm_port_buffer_putback (scm_t_port_buffer *buf, const scm_t_uint8 *src,
-                         size_t count)
+scm_port_buffer_putback (SCM buf, const scm_t_uint8 *src, size_t count)
 {
-  assert (count <= scm_to_size_t (buf->cur));
+  size_t cur = scm_to_size_t (scm_port_buffer_cur (buf));
+
+  assert (count <= cur);
 
   /* Sometimes used to move around data within a buffer, so we must use
      memmove.  */
-  buf->cur = scm_from_size_t (scm_to_size_t (buf->cur) - count);
-  memmove (SCM_BYTEVECTOR_CONTENTS (buf->bytevector) + scm_to_size_t 
(buf->cur),
+  cur -= count;
+  scm_port_buffer_set_cur (buf, scm_from_size_t (cur));
+  memmove (SCM_BYTEVECTOR_CONTENTS (scm_port_buffer_bytevector (buf)) + cur,
            src, count);
 }
 
diff --git a/libguile/ports.c b/libguile/ports.c
index b8b6dbf..ed387c6 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -307,13 +307,13 @@ scm_set_port_get_natural_buffer_sizes
 static void
 scm_i_set_pending_eof (SCM port)
 {
-  SCM_PTAB_ENTRY (port)->read_buf->has_eof_p = SCM_BOOL_T;
+  scm_port_buffer_set_has_eof_p (SCM_PTAB_ENTRY (port)->read_buf, SCM_BOOL_T);
 }
 
 static void
 scm_i_clear_pending_eof (SCM port)
 {
-  SCM_PTAB_ENTRY (port)->read_buf->has_eof_p = SCM_BOOL_F;
+  scm_port_buffer_set_has_eof_p (SCM_PTAB_ENTRY (port)->read_buf, SCM_BOOL_F);
 }
 
 SCM_DEFINE (scm_i_port_property, "%port-property", 2, 0, 0,
@@ -512,14 +512,14 @@ scm_i_dynwind_current_load_port (SCM port)
 
 /* Port buffers.  */
 
-scm_t_port_buffer *
+SCM
 scm_c_make_port_buffer (size_t size)
 {
-  scm_t_port_buffer *ret = scm_gc_typed_calloc (scm_t_port_buffer);
+  SCM ret = scm_c_make_vector (SCM_PORT_BUFFER_FIELD_COUNT, SCM_INUM0);
 
-  ret->bytevector = scm_c_make_bytevector (size);
-  ret->cur = ret->end = SCM_INUM0;
-  ret->has_eof_p = SCM_BOOL_F;
+  SCM_SIMPLE_VECTOR_SET (ret, SCM_PORT_BUFFER_FIELD_BYTEVECTOR,
+                         scm_c_make_bytevector (size));
+  scm_port_buffer_set_has_eof_p (ret, SCM_BOOL_F);
 
   return ret;
 }
@@ -1410,15 +1410,15 @@ scm_i_read_bytes_unlocked (SCM port, SCM dst, size_t 
start, size_t count)
    buffer.  If the number of available bytes in the buffer does not
    increase after a call to scm_i_read_unlocked, that indicates EOF.  */
 static void
-scm_i_read_unlocked (SCM port, scm_t_port_buffer *buf)
+scm_i_read_unlocked (SCM port, SCM buf)
 {
   size_t count;
 
-  count = scm_i_read_bytes_unlocked (port, buf->bytevector,
-                                     scm_to_size_t (buf->end),
+  count = scm_i_read_bytes_unlocked (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);
-  buf->has_eof_p = scm_from_bool (count == 0);
+  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
@@ -1432,7 +1432,7 @@ scm_c_read_bytes_unlocked (SCM port, SCM dst, size_t 
start, size_t count)
 {
   size_t to_read = count;
   scm_t_port *pt;
-  scm_t_port_buffer *read_buf;
+  SCM read_buf;
   scm_t_uint8 *dst_ptr = (scm_t_uint8 *) SCM_BYTEVECTOR_CONTENTS (dst) + start;
 
   SCM_VALIDATE_OPINPORT (1, port);
@@ -1470,7 +1470,7 @@ scm_c_read_bytes_unlocked (SCM port, SCM dst, size_t 
start, size_t count)
           if (did_read == 0)
             {
               /* Consider that we've read off this EOF.  */
-              read_buf->has_eof_p = SCM_BOOL_F;
+              scm_port_buffer_set_has_eof_p (read_buf, SCM_BOOL_F);
               break;
             }
         }
@@ -1499,7 +1499,7 @@ scm_c_read_unlocked (SCM port, void *buffer, size_t size)
 {
   size_t copied = 0;
   scm_t_port *pt;
-  scm_t_port_buffer *read_buf;
+  SCM read_buf;
   scm_t_uint8 *dst = buffer;
 
   SCM_VALIDATE_OPINPORT (1, port);
@@ -1523,7 +1523,7 @@ scm_c_read_unlocked (SCM port, void *buffer, size_t size)
       if (count == 0)
         {
           /* Consider that we've read off this EOF.  */
-          read_buf->has_eof_p = SCM_BOOL_F;
+          scm_port_buffer_set_has_eof_p (read_buf, SCM_BOOL_F);
           break;
         }
     }
@@ -1978,7 +1978,7 @@ scm_i_unget_bytes_unlocked (const scm_t_uint8 *buf, 
size_t len, SCM port)
 #define FUNC_NAME "scm_unget_bytes"
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
-  scm_t_port_buffer *read_buf = pt->read_buf;
+  SCM read_buf = pt->read_buf;
 
   if (pt->rw_random)
     {
@@ -2006,14 +2006,15 @@ scm_i_unget_bytes_unlocked (const scm_t_uint8 *buf, 
size_t len, SCM port)
       else
         {
           /* Bah, have to expand the read_buf for the putback.  */
-          scm_t_port_buffer *new_buf;
+          SCM new_buf;
 
           while (size < len + buffered)
             size *= 2;
 
           new_buf = scm_c_make_port_buffer (size);
           scm_port_buffer_reset_end (new_buf);
-          new_buf->has_eof_p = read_buf->has_eof_p;
+          scm_port_buffer_set_has_eof_p (new_buf,
+                                         scm_port_buffer_has_eof_p (read_buf));
           scm_port_buffer_putback (new_buf,
                                    scm_port_buffer_take_pointer (read_buf),
                                    buffered);
@@ -2286,7 +2287,7 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
   scm_t_ptob_descriptor *ptob;
   scm_t_bits tag_word;
   size_t read_buf_size, write_buf_size;
-  scm_t_port_buffer *saved_read_buf;
+  SCM saved_read_buf;
 
   port = SCM_COERCE_OUTPORT (port);
 
@@ -2348,17 +2349,18 @@ SCM_DEFINE (scm_setvbuf, "setvbuf", 2, 1, 0,
                      port);
 
   if (saved_read_buf)
-    pt->read_buf->has_eof_p = saved_read_buf->has_eof_p;
+    scm_port_buffer_set_has_eof_p (pt->read_buf,
+                                   scm_port_buffer_has_eof_p (saved_read_buf));
 
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
-scm_t_port_buffer*
+SCM
 scm_fill_input (SCM port)
 {
   scm_i_pthread_mutex_t *lock;
-  scm_t_port_buffer *ret;
+  SCM ret;
   
   scm_c_lock_port (port, &lock);
   ret = scm_fill_input_unlocked (port);
@@ -2374,7 +2376,7 @@ scm_fill_input (SCM port)
 size_t
 scm_take_from_input_buffers (SCM port, char *dest, size_t read_len)
 {
-  scm_t_port_buffer *read_buf = SCM_PTAB_ENTRY (port)->read_buf;
+  SCM read_buf = SCM_PTAB_ENTRY (port)->read_buf;
   return scm_port_buffer_take (read_buf, (scm_t_uint8 *) dest, read_len);
 }
 
@@ -2398,7 +2400,7 @@ SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
 {
   SCM result;
   scm_t_port *pt;
-  scm_t_port_buffer *read_buf;
+  SCM read_buf;
   long count;
 
   SCM_VALIDATE_OPINPORT (1, port);
@@ -2423,7 +2425,7 @@ void
 scm_end_input_unlocked (SCM port)
 {
   scm_t_port *pt;
-  scm_t_port_buffer *buf;
+  SCM buf;
   size_t discarded;
 
   pt = SCM_PTAB_ENTRY (port);
@@ -2469,12 +2471,12 @@ SCM_DEFINE (scm_force_output, "force-output", 0, 1, 0,
 }
 #undef FUNC_NAME
 
-static void scm_i_write_unlocked (SCM port, scm_t_port_buffer *src);
+static void scm_i_write_unlocked (SCM port, SCM buf);
 
 void
 scm_flush_unlocked (SCM port)
 {
-  scm_t_port_buffer *buf = SCM_PTAB_ENTRY (port)->write_buf;
+  SCM buf = SCM_PTAB_ENTRY (port)->write_buf;
   if (scm_port_buffer_can_take (buf))
     scm_i_write_unlocked (port, buf);
   SCM_PTAB_ENTRY (port)->rw_active = SCM_PORT_NEITHER;
@@ -2490,13 +2492,14 @@ scm_flush (SCM port)
     scm_i_pthread_mutex_unlock (lock);
 }
 
-scm_t_port_buffer *
+SCM
 scm_fill_input_unlocked (SCM port)
 {
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
-  scm_t_port_buffer *read_buf = pt->read_buf;
+  SCM read_buf = pt->read_buf;
 
-  if (scm_port_buffer_can_take (read_buf) || scm_is_true (read_buf->has_eof_p))
+  if (scm_port_buffer_can_take (read_buf) ||
+      scm_is_true (scm_port_buffer_has_eof_p (read_buf)))
     return read_buf;
 
   if (pt->rw_random)
@@ -2518,6 +2521,54 @@ scm_fill_input_unlocked (SCM port)
   return read_buf;
 }
 
+SCM_DEFINE (scm_port_read_buffer, "port-read-buffer", 1, 0, 0,
+            (SCM port),
+           "Return the read buffer for a port.  If the port is\n"
+            "random-access, its write buffer, if any, will be flushed\n"
+            "if needed.")
+#define FUNC_NAME s_scm_port_read_buffer
+{
+  scm_t_port *pt;
+
+  SCM_VALIDATE_OPINPORT (1, port);
+
+  pt = SCM_PTAB_ENTRY (port);
+
+  if (pt->rw_random)
+    {
+      if (pt->rw_active == SCM_PORT_WRITE)
+        scm_flush (pt->port);
+      pt->rw_active = SCM_PORT_READ;
+    }
+
+  return pt->read_buf;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_port_write_buffer, "port-write-buffer", 1, 0, 0,
+            (SCM port),
+           "Return the write buffer for a port.  If the port is\n"
+            "random-access, its read buffer, if any, will be discarded\n"
+            "if needed.")
+#define FUNC_NAME s_scm_port_write_buffer
+{
+  scm_t_port *pt;
+
+  SCM_VALIDATE_OPOUTPORT (1, port);
+
+  pt = SCM_PTAB_ENTRY (port);
+
+  if (pt->rw_random)
+    {
+      if (pt->rw_active == SCM_PORT_READ)
+        scm_end_input (pt->port);
+      pt->rw_active = SCM_PORT_WRITE;
+    }
+
+  return pt->write_buf;
+}
+#undef FUNC_NAME
+
 
 
 
@@ -2560,23 +2611,21 @@ scm_i_write_bytes_unlocked (SCM port, SCM src, size_t 
start, size_t count)
 }
 
 static void
-scm_i_write_unlocked (SCM port, scm_t_port_buffer *src)
+scm_i_write_unlocked (SCM port, SCM buf)
 {
   size_t start, count;
 
-  assert (scm_to_size_t (src->cur) < scm_to_size_t (src->end));
-  assert (scm_to_size_t (src->end) <= scm_port_buffer_size (src));
-
   /* Update cursors before attempting to write, assuming that I/O errors
      are sticky.  That way if the write throws an error, causing the
      computation to abort, and possibly causing the port to be collected
      by GC when it's open, any subsequent close-port / force-output
      won't signal *another* error.  */
 
-  start = scm_to_size_t (src->cur);
-  count = scm_port_buffer_can_take (src);
-  scm_port_buffer_reset (src);
-  scm_i_write_bytes_unlocked (port, src->bytevector, start, count);
+  start = scm_to_size_t (scm_port_buffer_cur (buf));
+  count = scm_port_buffer_can_take (buf);
+  scm_port_buffer_reset (buf);
+  scm_i_write_bytes_unlocked (port, scm_port_buffer_bytevector (buf), start,
+                              count);
 }
 
 /* Used by an application to write arbitrary number of bytes to an SCM
@@ -2589,7 +2638,7 @@ scm_c_write_bytes_unlocked (SCM port, SCM src, size_t 
start, size_t count)
 #define FUNC_NAME "scm_c_write_bytes"
 {
   scm_t_port *pt;
-  scm_t_port_buffer *write_buf;
+  SCM write_buf;
 
   SCM_VALIDATE_OPOUTPORT (1, port);
 
@@ -2605,8 +2654,8 @@ scm_c_write_bytes_unlocked (SCM port, SCM src, size_t 
start, size_t count)
 
   if (count < scm_port_buffer_size (write_buf))
     {
-      /* Make it so that write_buf->end is only nonzero if there are
-         buffered bytes already.  */
+      /* Make it so that the write_buf "end" cursor is only nonzero if
+         there are buffered bytes already.  */
       if (scm_port_buffer_can_take (write_buf) == 0)
         scm_port_buffer_reset (write_buf);
 
@@ -2648,7 +2697,7 @@ scm_c_write_unlocked (SCM port, const void *ptr, size_t 
size)
 #define FUNC_NAME "scm_c_write"
 {
   scm_t_port *pt;
-  scm_t_port_buffer *write_buf;
+  SCM write_buf;
   size_t written = 0;
   const scm_t_uint8 *src = ptr;
 
@@ -2759,7 +2808,7 @@ SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
 #define FUNC_NAME s_scm_char_ready_p
 {
   scm_t_port *pt;
-  scm_t_port_buffer *read_buf;
+  SCM read_buf;
 
   if (SCM_UNBNDP (port))
     port = scm_current_input_port ();
@@ -2770,7 +2819,8 @@ SCM_DEFINE (scm_char_ready_p, "char-ready?", 0, 1, 0,
   pt = SCM_PTAB_ENTRY (port);
   read_buf = pt->read_buf;
 
-  if (scm_port_buffer_can_take (read_buf) || scm_is_true (read_buf->has_eof_p))
+  if (scm_port_buffer_can_take (read_buf) ||
+      scm_is_true (scm_port_buffer_has_eof_p (read_buf)))
     /* FIXME: Verify that a whole character is available?  */
     return SCM_BOOL_T;
   else
diff --git a/libguile/ports.h b/libguile/ports.h
index 997b755..92799cb 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -37,6 +37,7 @@
 #include "libguile/struct.h"
 #include "libguile/threads.h"
 #include "libguile/strings.h"
+#include "libguile/vectors.h"
 
 
 
@@ -53,42 +54,35 @@ struct scm_port_internal;
 /* Port buffers.
 
    It's important to avoid calling into the kernel too many times.  For
-   that reason we buffer the input and output, using `scm_t_port_buffer'
-   objects.  The bytes in a read buffer are laid out like this:
+   that reason we buffer the input and output, using "port buffer"
+   objects.  Port buffers are represented as vectors containing the
+   buffer, two cursors, and a flag.  The bytes in a read buffer are laid
+   out like this:
 
                     |already read | not yet | invalid
                     |    data     |  read   |  data
       readbuf: #vu8(|r r r r r r r|u u u u u|x x x x x|)
-                    ^buf          ^cur      ^end      ^size
+               ^buf               ^cur      ^end      ^size(buf)
 
    Similarly for a write buffer:
 
                      |already written | not yet | invalid
                      |    data        | written |  data
       writebuf: #vu8(|w w w w w w w w |u u u u u|x x x x x|)
-                     ^buf             ^cur      ^end      ^size
+                ^buf                  ^cur      ^end      ^size(buf)
 
-   We use a `scm_t_port_buffer' object for both purposes.  Port buffers
-   are implemented as their own object so that they can be atomically
-   swapped in or out.  */
-
-typedef struct
-{
-  /* The port buffer. */
-  SCM bytevector;
-
-  /* Offsets into the buffer.  Invariant: cur <= end <= size(buf).  */
-  SCM cur;
-  SCM end;
-
-  /* For read buffers, flag indicating whether the last read() returned
-     zero bytes.  Note that in the case of pushback, there could still
-     be bytes in the buffer, but that after any bytes are read off,
-     peek-u8 should still return EOF.  */
-  SCM has_eof_p;
-
-} scm_t_port_buffer;
+   We use the same port buffer data structure for both purposes.  Port
+   buffers are implemented as their own object so that they can be
+   atomically swapped in or out of ports, and as Scheme vectors so they
+   can be manipulated from Scheme.  */
 
+enum scm_port_buffer_field {
+  SCM_PORT_BUFFER_FIELD_BYTEVECTOR,
+  SCM_PORT_BUFFER_FIELD_CUR,
+  SCM_PORT_BUFFER_FIELD_END,
+  SCM_PORT_BUFFER_FIELD_HAS_EOF_P,
+  SCM_PORT_BUFFER_FIELD_COUNT
+};
 
 /* C representation of a Scheme port.  */
 
@@ -112,8 +106,8 @@ typedef struct
   int column_number;
 
   /* Port buffers.  */
-  scm_t_port_buffer *read_buf;
-  scm_t_port_buffer *write_buf;
+  SCM read_buf;
+  SCM write_buf;
 
   /* All ports have read and write buffers; an unbuffered port simply
      has a one-byte buffer.  However unreading bytes can expand the read
@@ -263,7 +257,7 @@ SCM_API void scm_dynwind_current_error_port (SCM port);
 SCM_INTERNAL void scm_i_dynwind_current_load_port (SCM port);
 
 /* Port buffers.  */
-SCM_INTERNAL scm_t_port_buffer *scm_c_make_port_buffer (size_t size);
+SCM_INTERNAL SCM scm_c_make_port_buffer (size_t size);
 
 /* Mode bits.  */
 SCM_INTERNAL long scm_i_mode_bits (SCM modes);
@@ -341,8 +335,8 @@ 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_t_port_buffer* scm_fill_input (SCM port);
-SCM_API scm_t_port_buffer* scm_fill_input_unlocked (SCM port);
+SCM_API SCM scm_fill_input (SCM port);
+SCM_API SCM scm_fill_input_unlocked (SCM port);
 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);
@@ -350,6 +344,8 @@ SCM_API void scm_end_input_unlocked (SCM port);
 SCM_API SCM scm_force_output (SCM port);
 SCM_API void scm_flush (SCM port);
 SCM_API void scm_flush_unlocked (SCM port);
+SCM_INTERNAL SCM scm_port_read_buffer (SCM port);
+SCM_INTERNAL SCM scm_port_write_buffer (SCM port);
 
 /* Output.  */
 SCM_API void scm_putc (char c, SCM port);
@@ -428,31 +424,42 @@ scm_c_try_lock_port (SCM port, scm_i_pthread_mutex_t 
**lock)
 SCM_INLINE_IMPLEMENTATION int
 scm_get_byte_or_eof_unlocked (SCM port)
 {
-  scm_t_port_buffer *buf = SCM_PTAB_ENTRY (port)->read_buf;
-  size_t cur = SCM_I_INUM (buf->cur);
-
-  if (SCM_LIKELY (SCM_I_INUMP (buf->cur))
-      && SCM_LIKELY (SCM_I_INUMP (buf->end))
-      && SCM_LIKELY (cur < SCM_I_INUM (buf->end))
-      && SCM_LIKELY (cur < SCM_BYTEVECTOR_LENGTH (buf->bytevector)))
+  SCM buf = SCM_PTAB_ENTRY (port)->read_buf;
+  SCM buf_bv, buf_cur, buf_end;
+  size_t cur;
+
+  buf_bv = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_BYTEVECTOR);
+  buf_cur = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_CUR);
+  buf_end = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_END);
+  cur = SCM_I_INUM (buf_cur);
+
+  if (SCM_LIKELY (SCM_I_INUMP (buf_cur))
+      && SCM_LIKELY (SCM_I_INUMP (buf_end))
+      && SCM_LIKELY (cur < SCM_I_INUM (buf_end))
+      && SCM_LIKELY (cur < SCM_BYTEVECTOR_LENGTH (buf_bv)))
     {
-      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector)[cur];
-      buf->cur = SCM_I_MAKINUM (cur + 1);
+      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf_bv)[cur];
+      buf_cur = SCM_I_MAKINUM (cur + 1);
+      SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_CUR, buf_cur);
       return ret;
     }
 
   buf = scm_fill_input_unlocked (port);
-  cur = scm_to_size_t (buf->cur);
-  if (cur < scm_to_size_t (buf->end))
+  buf_bv = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_BYTEVECTOR);
+  buf_cur = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_CUR);
+  buf_end = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_END);
+  cur = scm_to_size_t (buf_cur);
+  if (cur < scm_to_size_t (buf_end))
     {
-      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector)[cur];
-      buf->cur = scm_from_size_t (cur + 1);
+      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf_bv)[cur];
+      buf_cur = SCM_I_MAKINUM (cur + 1);
+      SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_CUR, buf_cur);
       return ret;
     }
 
   /* The next peek or get should cause the read() function to be called
      to see if we still have EOF.  */
-  buf->has_eof_p = SCM_BOOL_F;
+  SCM_SIMPLE_VECTOR_SET (buf, SCM_PORT_BUFFER_FIELD_HAS_EOF_P, SCM_BOOL_F);
   return EOF;
 }
 
@@ -460,23 +467,31 @@ scm_get_byte_or_eof_unlocked (SCM port)
 SCM_INLINE_IMPLEMENTATION int
 scm_peek_byte_or_eof_unlocked (SCM port)
 {
-  scm_t_port_buffer *buf = SCM_PTAB_ENTRY (port)->read_buf;
-  size_t cur = SCM_I_INUM (buf->cur);
-
-  if (SCM_LIKELY (SCM_I_INUMP (buf->cur))
-      && SCM_LIKELY (SCM_I_INUMP (buf->end))
-      && SCM_LIKELY (cur < SCM_I_INUM (buf->end))
-      && SCM_LIKELY (cur < SCM_BYTEVECTOR_LENGTH (buf->bytevector)))
+  SCM buf = SCM_PTAB_ENTRY (port)->read_buf;
+  SCM buf_bv, buf_cur, buf_end;
+  size_t cur;
+
+  buf_bv = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_BYTEVECTOR);
+  buf_cur = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_CUR);
+  buf_end = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_END);
+  cur = SCM_I_INUM (buf_cur);
+  if (SCM_LIKELY (SCM_I_INUMP (buf_cur))
+      && SCM_LIKELY (SCM_I_INUMP (buf_end))
+      && SCM_LIKELY (cur < SCM_I_INUM (buf_end))
+      && SCM_LIKELY (cur < SCM_BYTEVECTOR_LENGTH (buf_bv)))
     {
-      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector)[cur];
+      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf_bv)[cur];
       return ret;
     }
 
   buf = scm_fill_input_unlocked (port);
-  cur = scm_to_size_t (buf->cur);
-  if (cur < scm_to_size_t (buf->end))
+  buf_bv = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_BYTEVECTOR);
+  buf_cur = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_CUR);
+  buf_end = SCM_SIMPLE_VECTOR_REF (buf, SCM_PORT_BUFFER_FIELD_END);
+  cur = scm_to_size_t (buf_cur);
+  if (cur < scm_to_size_t (buf_end))
     {
-      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf->bytevector)[cur];
+      scm_t_uint8 ret = SCM_BYTEVECTOR_CONTENTS (buf_bv)[cur];
       return ret;
     }
 
diff --git a/libguile/r6rs-ports.c b/libguile/r6rs-ports.c
index 4c5c87c..e96e220 100644
--- a/libguile/r6rs-ports.c
+++ b/libguile/r6rs-ports.c
@@ -468,7 +468,7 @@ SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some", 
1, 0, 0,
             "position to point just past these bytes.")
 #define FUNC_NAME s_scm_get_bytevector_some
 {
-  scm_t_port_buffer *buf;
+  SCM buf;
   size_t size;
   SCM bv;
 
@@ -478,7 +478,7 @@ SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some", 
1, 0, 0,
   size = scm_port_buffer_can_take (buf);
   if (size == 0)
     {
-      buf->has_eof_p = SCM_BOOL_F;
+      scm_port_buffer_set_has_eof_p (buf, SCM_BOOL_F);
       return SCM_EOF_VAL;
     }
 
diff --git a/libguile/read.c b/libguile/read.c
index bc5c3c1..d717ea2 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -2057,7 +2057,7 @@ char *
 scm_i_scan_for_encoding (SCM port)
 {
   scm_t_port *pt;
-  scm_t_port_buffer *buf;
+  SCM buf;
   char header[SCM_ENCODING_SEARCH_SIZE+1];
   size_t bytes_read, encoding_length, i;
   char *encoding = NULL;
diff --git a/libguile/rw.c b/libguile/rw.c
index d6437e9..bf4a1f5 100644
--- a/libguile/rw.c
+++ b/libguile/rw.c
@@ -232,7 +232,7 @@ SCM_DEFINE (scm_write_string_partial, 
"write-string/partial", 1, 3, 0,
     {
       SCM port = (SCM_UNBNDP (port_or_fdes)?
                  scm_current_output_port () : port_or_fdes);
-      scm_t_port_buffer *write_buf;
+      SCM write_buf;
 
       SCM_VALIDATE_OPFPORT (2, port);
       SCM_VALIDATE_OUTPUT_PORT (2, port);



reply via email to

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