1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-16 16:50:21 +02:00

Custom binary port internals refactor

* libguile/r6rs-ports.c (struct custom_binary_port): Use a struct
  instead of a vector as the state for a custom binary port.  Adapt all
  callers.  Some whitespace fixes as well.
This commit is contained in:
Andy Wingo 2016-04-03 21:54:37 +02:00
parent 693359cb3d
commit b538a96f92

View file

@ -38,6 +38,7 @@
/* Unimplemented features. */ /* Unimplemented features. */
@ -51,7 +52,9 @@ transcoders_not_implemented (void)
PACKAGE_NAME); PACKAGE_NAME);
} }
/* End-of-file object. */ /* End-of-file object. */
SCM_DEFINE (scm_eof_object, "eof-object", 0, 0, 0, SCM_DEFINE (scm_eof_object, "eof-object", 0, 0, 0,
@ -63,7 +66,9 @@ SCM_DEFINE (scm_eof_object, "eof-object", 0, 0, 0,
} }
#undef FUNC_NAME #undef FUNC_NAME
/* Input ports. */ /* Input ports. */
#ifndef MIN #ifndef MIN
@ -186,33 +191,35 @@ SCM_DEFINE (scm_open_bytevector_input_port,
} }
#undef FUNC_NAME #undef FUNC_NAME
/* Custom binary ports. The following routines are shared by input and /* Custom binary ports. The following routines are shared by input and
output custom binary ports. */ output custom binary ports. */
#define SCM_CUSTOM_BINARY_PORT_GET_POSITION_PROC(_port) \ struct custom_binary_port {
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 1) SCM read_buffer;
#define SCM_CUSTOM_BINARY_PORT_SET_POSITION_PROC(_port) \ SCM read;
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 2) SCM write;
#define SCM_CUSTOM_BINARY_PORT_CLOSE_PROC(_port) \ SCM get_position;
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 3) SCM set_position_x;
SCM close;
};
static scm_t_off static scm_t_off
custom_binary_port_seek (SCM port, scm_t_off offset, int whence) custom_binary_port_seek (SCM port, scm_t_off offset, int whence)
#define FUNC_NAME "custom_binary_port_seek" #define FUNC_NAME "custom_binary_port_seek"
{ {
SCM result; SCM result;
struct custom_binary_port *stream = (void *) SCM_STREAM (port);
scm_t_off c_result = 0; scm_t_off c_result = 0;
switch (whence) switch (whence)
{ {
case SEEK_CUR: case SEEK_CUR:
{ {
SCM get_position_proc; if (SCM_LIKELY (scm_is_true (stream->get_position)))
result = scm_call_0 (stream->get_position);
get_position_proc = SCM_CUSTOM_BINARY_PORT_GET_POSITION_PROC (port);
if (SCM_LIKELY (scm_is_true (get_position_proc)))
result = scm_call_0 (get_position_proc);
else else
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
"R6RS custom binary port with " "R6RS custom binary port with "
@ -228,11 +235,8 @@ custom_binary_port_seek (SCM port, scm_t_off offset, int whence)
case SEEK_SET: case SEEK_SET:
{ {
SCM set_position_proc; if (SCM_LIKELY (scm_is_true (stream->set_position_x)))
result = scm_call_1 (stream->set_position_x, scm_from_int (offset));
set_position_proc = SCM_CUSTOM_BINARY_PORT_SET_POSITION_PROC (port);
if (SCM_LIKELY (scm_is_true (set_position_proc)))
result = scm_call_1 (set_position_proc, scm_from_int (offset));
else else
scm_wrong_type_arg_msg (FUNC_NAME, 0, port, scm_wrong_type_arg_msg (FUNC_NAME, 0, port,
"seekable R6RS custom binary port"); "seekable R6RS custom binary port");
@ -256,36 +260,25 @@ custom_binary_port_seek (SCM port, scm_t_off offset, int whence)
static int static int
custom_binary_port_close (SCM port) custom_binary_port_close (SCM port)
{ {
SCM close_proc; struct custom_binary_port *stream = (void *) SCM_STREAM (port);
close_proc = SCM_CUSTOM_BINARY_PORT_CLOSE_PROC (port); if (scm_is_true (stream->close))
if (scm_is_true (close_proc))
/* Invoke the `close' thunk. */ /* Invoke the `close' thunk. */
scm_call_0 (close_proc); scm_call_0 (stream->close);
return 1; return 1;
} }
/* Custom binary input port. */
/* Custom binary input ports. */
static scm_t_bits custom_binary_input_port_type = 0; static scm_t_bits custom_binary_input_port_type = 0;
/* Initial size of the buffer embedded in custom binary input ports. */ /* Initial size of the buffer embedded in custom binary input ports. */
#define CUSTOM_BINARY_INPUT_PORT_BUFFER_SIZE 8192 #define CUSTOM_BINARY_INPUT_PORT_BUFFER_SIZE 8192
/* Return the bytevector associated with PORT. */
#define SCM_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR(_port) \
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 4)
/* Set BV as the bytevector associated with PORT. */
#define SCM_SET_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR(_port, _bv) \
SCM_SIMPLE_VECTOR_SET (SCM_PACK (SCM_STREAM (_port)), 4, (_bv))
/* Return the various procedures of PORT. */
#define SCM_CUSTOM_BINARY_INPUT_PORT_READ_PROC(_port) \
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 0)
/* Set PORT's internal buffer according to READ_SIZE. */ /* Set PORT's internal buffer according to READ_SIZE. */
static void static void
@ -293,9 +286,10 @@ custom_binary_input_port_setvbuf (SCM port, long read_size, long write_size)
{ {
SCM bv; SCM bv;
scm_t_port *pt; scm_t_port *pt;
struct custom_binary_port *stream = (void *) SCM_STREAM (port);
pt = SCM_PTAB_ENTRY (port); pt = SCM_PTAB_ENTRY (port);
bv = SCM_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR (port); bv = stream->read_buffer;
switch (read_size) switch (read_size)
{ {
@ -317,7 +311,7 @@ custom_binary_input_port_setvbuf (SCM port, long read_size, long write_size)
default: default:
/* Fully buffered: allocate a buffer of READ_SIZE bytes. */ /* Fully buffered: allocate a buffer of READ_SIZE bytes. */
bv = scm_c_make_bytevector (read_size); bv = scm_c_make_bytevector (read_size);
SCM_SET_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR (port, bv); stream->read_buffer = bv;
pt->read_buf = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv); pt->read_buf = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv);
pt->read_buf_size = read_size; pt->read_buf_size = read_size;
} }
@ -329,10 +323,11 @@ static inline SCM
make_custom_binary_input_port (SCM read_proc, SCM get_position_proc, make_custom_binary_input_port (SCM read_proc, SCM get_position_proc,
SCM set_position_proc, SCM close_proc) SCM set_position_proc, SCM close_proc)
{ {
SCM port, bv, method_vector; SCM port, bv;
char *c_bv; char *c_bv;
unsigned c_len; unsigned c_len;
scm_t_port *c_port; scm_t_port *c_port;
struct custom_binary_port *stream;
const unsigned long mode_bits = SCM_OPN | SCM_RDNG; const unsigned long mode_bits = SCM_OPN | SCM_RDNG;
/* Use a bytevector as the underlying buffer. */ /* Use a bytevector as the underlying buffer. */
@ -340,19 +335,19 @@ make_custom_binary_input_port (SCM read_proc, SCM get_position_proc,
bv = scm_c_make_bytevector (c_len); bv = scm_c_make_bytevector (c_len);
c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv); c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv);
/* Store the various methods and bytevector in a vector. */ stream = scm_gc_typed_calloc (struct custom_binary_port);
method_vector = scm_c_make_vector (5, SCM_BOOL_F); stream->read_buffer = bv;
SCM_SIMPLE_VECTOR_SET (method_vector, 4, bv); stream->read = read_proc;
SCM_SIMPLE_VECTOR_SET (method_vector, 0, read_proc); stream->write = SCM_BOOL_F;
SCM_SIMPLE_VECTOR_SET (method_vector, 1, get_position_proc); stream->get_position = get_position_proc;
SCM_SIMPLE_VECTOR_SET (method_vector, 2, set_position_proc); stream->set_position_x = set_position_proc;
SCM_SIMPLE_VECTOR_SET (method_vector, 3, close_proc); stream->close = close_proc;
port = scm_c_make_port_with_encoding (custom_binary_input_port_type, port = scm_c_make_port_with_encoding (custom_binary_input_port_type,
mode_bits, mode_bits,
NULL, /* encoding */ NULL, /* encoding */
SCM_FAILED_CONVERSION_ERROR, SCM_FAILED_CONVERSION_ERROR,
SCM_UNPACK (method_vector)); (scm_t_bits) stream);
c_port = SCM_PTAB_ENTRY (port); c_port = SCM_PTAB_ENTRY (port);
@ -370,18 +365,18 @@ custom_binary_input_port_fill_input (SCM port)
{ {
int result; int result;
scm_t_port *c_port = SCM_PTAB_ENTRY (port); scm_t_port *c_port = SCM_PTAB_ENTRY (port);
struct custom_binary_port *stream = (void *) SCM_STREAM (port);
if (c_port->read_pos >= c_port->read_end) if (c_port->read_pos >= c_port->read_end)
{ {
/* Invoke the user's `read!' procedure. */ /* Invoke the user's `read!' procedure. */
int buffered; int buffered;
size_t c_octets, c_requested; size_t c_octets, c_requested;
SCM bv, read_proc, octets; SCM bv, octets;
c_requested = c_port->read_buf_size; c_requested = c_port->read_buf_size;
read_proc = SCM_CUSTOM_BINARY_INPUT_PORT_READ_PROC (port);
bv = SCM_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR (port); bv = stream->read_buffer;
buffered = buffered =
(c_port->read_buf == (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv)); (c_port->read_buf == (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv));
@ -401,16 +396,13 @@ custom_binary_input_port_fill_input (SCM port)
are passed the caller-provided buffer, so we need to check its are passed the caller-provided buffer, so we need to check its
size. */ size. */
if (SCM_BYTEVECTOR_LENGTH (bv) < c_requested) if (SCM_BYTEVECTOR_LENGTH (bv) < c_requested)
{ /* Bad luck: we have to make another allocation. Save that
/* Bad luck: we have to make another allocation. Save that nbytevector for later reuse, in the hope that the application
bytevector for later reuse, in the hope that the application has regular access patterns. */
has regular access patterns. */ stream->read_buffer = bv = scm_c_make_bytevector (c_requested);
bv = scm_c_make_bytevector (c_requested);
SCM_SET_CUSTOM_BINARY_INPUT_PORT_BYTEVECTOR (port, bv);
}
} }
octets = scm_call_3 (read_proc, bv, SCM_INUM0, octets = scm_call_3 (stream->read, bv, SCM_INUM0,
scm_from_size_t (c_requested)); scm_from_size_t (c_requested));
c_octets = scm_to_size_t (octets); c_octets = scm_to_size_t (octets);
if (SCM_UNLIKELY (c_octets > c_requested)) if (SCM_UNLIKELY (c_octets > c_requested))
@ -479,6 +471,7 @@ initialize_custom_binary_input_ports (void)
/* Binary input. */ /* Binary input. */
/* We currently don't support specific binary input ports. */ /* We currently don't support specific binary input ports. */
@ -603,7 +596,6 @@ SCM_DEFINE (scm_get_bytevector_n_x, "get-bytevector-n!", 4, 0, 0,
} }
#undef FUNC_NAME #undef FUNC_NAME
SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some", 1, 0, 0, SCM_DEFINE (scm_get_bytevector_some, "get-bytevector-some", 1, 0, 0,
(SCM port), (SCM port),
"Read from @var{port}, blocking as necessary, until bytes " "Read from @var{port}, blocking as necessary, until bytes "
@ -706,6 +698,7 @@ SCM_DEFINE (scm_get_bytevector_all, "get-bytevector-all", 1, 0, 0,
/* Binary output. */ /* Binary output. */
/* We currently don't support specific binary input ports. */ /* We currently don't support specific binary input ports. */
@ -816,6 +809,7 @@ SCM_DEFINE (scm_unget_bytevector, "unget-bytevector", 2, 2, 0,
/* Bytevector output port. */ /* Bytevector output port. */
/* Implementation of "bytevector output ports". /* Implementation of "bytevector output ports".
@ -1022,36 +1016,38 @@ initialize_bytevector_output_ports (void)
scm_set_port_seek (bytevector_output_port_type, bytevector_output_port_seek); scm_set_port_seek (bytevector_output_port_type, bytevector_output_port_seek);
} }
/* Custom binary output port. */
/* Custom binary output ports. */
static scm_t_bits custom_binary_output_port_type; static scm_t_bits custom_binary_output_port_type;
/* Return the various procedures of PORT. */
#define SCM_CUSTOM_BINARY_OUTPUT_PORT_WRITE_PROC(_port) \
SCM_SIMPLE_VECTOR_REF (SCM_PACK (SCM_STREAM (_port)), 0)
static inline SCM static inline SCM
make_custom_binary_output_port (SCM write_proc, SCM get_position_proc, make_custom_binary_output_port (SCM write_proc, SCM get_position_proc,
SCM set_position_proc, SCM close_proc) SCM set_position_proc, SCM close_proc)
{ {
SCM port, method_vector; SCM port;
scm_t_port *c_port; scm_t_port *c_port;
struct custom_binary_port *stream;
const unsigned long mode_bits = SCM_OPN | SCM_WRTNG; const unsigned long mode_bits = SCM_OPN | SCM_WRTNG;
/* Store the various methods and bytevector in a vector. */ /* Store the various methods and bytevector in a vector. */
method_vector = scm_c_make_vector (4, SCM_BOOL_F); stream = scm_gc_typed_calloc (struct custom_binary_port);
SCM_SIMPLE_VECTOR_SET (method_vector, 0, write_proc);
SCM_SIMPLE_VECTOR_SET (method_vector, 1, get_position_proc); stream->read_buffer = SCM_BOOL_F;
SCM_SIMPLE_VECTOR_SET (method_vector, 2, set_position_proc); stream->read = SCM_BOOL_F;
SCM_SIMPLE_VECTOR_SET (method_vector, 3, close_proc); stream->write = write_proc;
stream->get_position = get_position_proc;
stream->set_position_x = set_position_proc;
stream->close = close_proc;
port = scm_c_make_port_with_encoding (custom_binary_output_port_type, port = scm_c_make_port_with_encoding (custom_binary_output_port_type,
mode_bits, mode_bits,
NULL, /* encoding */ NULL, /* encoding */
SCM_FAILED_CONVERSION_ERROR, SCM_FAILED_CONVERSION_ERROR,
SCM_UNPACK (method_vector)); (scm_t_bits) stream);
c_port = SCM_PTAB_ENTRY (port); c_port = SCM_PTAB_ENTRY (port);
@ -1069,7 +1065,8 @@ custom_binary_output_port_write (SCM port, const void *data, size_t size)
{ {
long int c_result; long int c_result;
size_t c_written; size_t c_written;
SCM bv, write_proc, result; struct custom_binary_port *stream = (void *) SCM_STREAM (port);
SCM bv, result;
/* XXX: Allocating a new bytevector at each `write' call is inefficient, /* XXX: Allocating a new bytevector at each `write' call is inefficient,
but necessary since (1) we don't control the lifetime of the buffer but necessary since (1) we don't control the lifetime of the buffer
@ -1078,8 +1075,6 @@ custom_binary_output_port_write (SCM port, const void *data, size_t size)
bv = scm_c_make_bytevector (size); bv = scm_c_make_bytevector (size);
memcpy (SCM_BYTEVECTOR_CONTENTS (bv), data, size); memcpy (SCM_BYTEVECTOR_CONTENTS (bv), data, size);
write_proc = SCM_CUSTOM_BINARY_OUTPUT_PORT_WRITE_PROC (port);
/* Since the `write' procedure of Guile's ports has type `void', it must /* Since the `write' procedure of Guile's ports has type `void', it must
try hard to write exactly SIZE bytes, regardless of how many bytes the try hard to write exactly SIZE bytes, regardless of how many bytes the
sink can handle. */ sink can handle. */
@ -1087,7 +1082,7 @@ custom_binary_output_port_write (SCM port, const void *data, size_t size)
c_written < size; c_written < size;
c_written += c_result) c_written += c_result)
{ {
result = scm_call_3 (write_proc, bv, result = scm_call_3 (stream->write, bv,
scm_from_size_t (c_written), scm_from_size_t (c_written),
scm_from_size_t (size - c_written)); scm_from_size_t (size - c_written));
@ -1141,8 +1136,11 @@ initialize_custom_binary_output_ports (void)
scm_set_port_close (custom_binary_output_port_type, custom_binary_port_close); scm_set_port_close (custom_binary_output_port_type, custom_binary_port_close);
} }
/* Transcoded ports. */ /* Transcoded ports. */
static scm_t_bits transcoded_port_type = 0; static scm_t_bits transcoded_port_type = 0;
#define TRANSCODED_PORT_INPUT_BUFFER_SIZE 4096 #define TRANSCODED_PORT_INPUT_BUFFER_SIZE 4096