--- orig/libguile/fports.c +++ mod/libguile/fports.c @@ -90,10 +90,10 @@ /* default buffer size, used if the O/S won't supply a value. */ static const size_t default_buffer_size = 1024; -/* create FPORT buffer with specified sizes (or -1 to use default size or - 0 for no buffer. */ +/* Create FPORT buffer with specified sizes (or -1 to use default size or + 0 for no buffer). */ static void -scm_fport_buffer_add (SCM port, long read_size, int write_size) +scm_fport_buffer_add (SCM port, long read_size, long write_size) #define FUNC_NAME "scm_fport_buffer_add" { scm_t_port *pt = SCM_PTAB_ENTRY (port); @@ -217,6 +217,115 @@ } #undef FUNC_NAME +SCM_DEFINE (scm_set_port_input_buffer_size_x, "set-port-input-buffer-size!", + 2, 0, 0, + (SCM port, SCM size), + "Use a @var{size}-octet input buffer for @var{port}, which " + "must be a file or socket port. The current input buffer " + "of @var{port} must contain less than @var{size} octets.") +#define FUNC_NAME s_scm_set_port_input_buffer_size_x +{ + scm_t_port *pt; + size_t c_size; + + SCM_VALIDATE_FPORT (1, port); + c_size = scm_to_uint (size); + + pt = SCM_PTAB_ENTRY (port); + + if (pt->read_buf_size != c_size) + { + size_t c_offset, c_end; + unsigned char *new_buf; + + c_end = pt->read_end - pt->read_buf; + c_offset = pt->read_pos - pt->read_buf; + + if (c_offset > c_size) + scm_wrong_type_arg_msg (FUNC_NAME, 1, port, + "Input buffer must be flushed before it " + "can be shrunk"); + + if (c_size == 0) + new_buf = &pt->shortbuf, c_size = 1; + else + { + if (pt->read_buf != &pt->shortbuf) + new_buf = scm_gc_realloc (pt->read_buf, + pt->read_buf_size, c_size, + "port buffer"); + else + new_buf = scm_gc_malloc (c_size, "port buffer"); + } + + pt->read_buf = new_buf; + pt->read_end = new_buf + c_end; + pt->read_pos = new_buf + c_offset; + pt->read_buf_size = c_size; + + if ((pt->read_buf_size == 0) && (pt->write_buf_size == 0)) + SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0); + } + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + +SCM_DEFINE (scm_set_port_output_buffer_size_x, "set-port-output-buffer-size!", + 2, 0, 0, + (SCM port, SCM size), + "Use a @var{size}-octet output buffer for @var{port}, which " + "must be a file or socket port. The current output buffer of " + "@var{port} must contain less than @var{size} octets.") +#define FUNC_NAME s_scm_set_port_output_buffer_size_x +{ + scm_t_port *pt; + size_t c_size; + + SCM_VALIDATE_FPORT (1, port); + c_size = scm_to_uint (size); + + pt = SCM_PTAB_ENTRY (port); + + if (pt->write_buf_size != c_size) + { + size_t c_offset, c_end; + unsigned char *new_buf; + + c_end = pt->write_end - pt->write_buf; + c_offset = pt->write_pos - pt->write_buf; + + if (c_offset > c_size) + scm_wrong_type_arg_msg (FUNC_NAME, 1, port, + "Output buffer must be flushed before it " + "can be shrunk"); + + if (c_size == 0) + new_buf = &pt->shortbuf, c_size = 1; + else + { + if (pt->write_buf != &pt->shortbuf) + new_buf = scm_gc_realloc (pt->write_buf, + pt->write_buf_size, c_size, + "port buffer"); + else + new_buf = scm_gc_malloc (c_size, "port buffer"); + } + + pt->write_buf = new_buf; + pt->write_end = new_buf + c_end; + pt->write_pos = new_buf + c_offset; + pt->write_buf_size = c_size; + + if ((pt->read_buf_size == 0) && (pt->write_buf_size == 0)) + SCM_SET_CELL_WORD_0 (port, SCM_CELL_WORD_0 (port) | SCM_BUF0); + } + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + /* Move ports with the specified file descriptor to new descriptors, * resetting the revealed count to 0. */ --- orig/libguile/fports.h +++ mod/libguile/fports.h @@ -49,6 +49,8 @@ SCM_API SCM scm_setbuf0 (SCM port); SCM_API SCM scm_setvbuf (SCM port, SCM mode, SCM size); +SCM_API SCM scm_set_port_input_buffer_size_x (SCM port, SCM size); +SCM_API SCM scm_set_port_output_buffer_size_x (SCM port, SCM size); SCM_API void scm_evict_ports (int fd); SCM_API SCM scm_open_file (SCM filename, SCM modes); SCM_API SCM scm_fdes_to_port (int fdes, char *mode, SCM name);