5.12.10.2 Port Implementation
This section describes how to implement a new port type in C.
As described in the previous section, a port type object (ptob) is
a structure of type scm_ptob_descriptor
. A ptob is created by
calling scm_make_port_type
.
— Function: scm_t_bits
scm_make_port_type (
char *name, int (
*fill_input) (
SCM port)
, void (
*write) (
SCM port, const void *data, size_t size))
Return a new port type object. The name, fill_input and
write parameters are initial values for those port type fields,
as described below. The other fields are initialized with default
values and can be changed later.
All of the elements of the ptob, apart from name
, are procedures
which collectively implement the port behaviour. Creating a new port
type mostly involves writing these procedures.
name
- A pointer to a NUL terminated string: the name of the port type. This
is the only element of
scm_ptob_descriptor
which is not
a procedure. Set via the first argument to scm_make_port_type
.
mark
- Called during garbage collection to mark any SCM objects that a port
object may contain. It doesn't need to be set unless the port has
SCM
components. Set using
— Function: void
scm_set_port_mark (
scm_t_bits tc, SCM (
*mark) (
SCM port))
free
- Called when the port is collected during gc. It
should free any resources used by the port.
Set using
— Function: void
scm_set_port_free (
scm_t_bits tc, size_t (
*free) (
SCM port))
print
- Called when
write
is called on the port object, to print a
port description. E.g., for an fport it may produce something like:
#<input: /etc/passwd 3>
. Set using
— Function: void
scm_set_port_print (
scm_t_bits tc, int (
*print) (
SCM port, SCM dest_port, scm_print_state *pstate))
The first argument port is the object being printed, the second
argument dest_port is where its description should go.
equalp
- Not used at present. Set using
— Function: void
scm_set_port_equalp (
scm_t_bits tc, SCM (
*equalp) (
SCM, SCM))
close
- Called when the port is closed, unless it was collected during gc. It
should free any resources used by the port.
Set using
— Function: void
scm_set_port_close (
scm_t_bits tc, int (
*close) (
SCM port))
write
- Accept data which is to be written using the port. The port implementation
may choose to buffer the data instead of processing it directly.
Set via the third argument to
scm_make_port_type
.
flush
- Complete the processing of buffered output data. Reset the value of
rw_active
to SCM_PORT_NEITHER
.
Set using
— Function: void
scm_set_port_flush (
scm_t_bits tc, void (
*flush) (
SCM port))
end_input
- Perform any synchronization required when switching from input to output
on the port. Reset the value of
rw_active
to SCM_PORT_NEITHER
.
Set using
— Function: void
scm_set_port_end_input (
scm_t_bits tc, void (
*end_input) (
SCM port, int offset))
fill_input
- Read new data into the read buffer and return the first character. It
can be assumed that the read buffer is empty when this procedure is called.
Set via the second argument to
scm_make_port_type
.
input_waiting
- Return a lower bound on the number of bytes that could be read from the
port without blocking. It can be assumed that the current state of
rw_active
is SCM_PORT_NEITHER
.
Set using
— Function: void
scm_set_port_input_waiting (
scm_t_bits tc, int (
*input_waiting) (
SCM port))
seek
- Set the current position of the port. The procedure can not make
any assumptions about the value of
rw_active
when it's
called. It can reset the buffers first if desired by using something
like:
if (pt->rw_active == SCM_PORT_READ)
scm_end_input (port);
else if (pt->rw_active == SCM_PORT_WRITE)
ptob->flush (port);
However note that this will have the side effect of discarding any data
in the unread-char buffer, in addition to any side effects from the
end_input
and flush
ptob procedures. This is undesirable
when seek is called to measure the current position of the port, i.e.,
(seek p 0 SEEK_CUR)
. The libguile fport and string port
implementations take care to avoid this problem.
The procedure is set using
— Function: void
scm_set_port_seek (
scm_t_bits tc, off_t (
*seek) (
SCM port, off_t offset, int whence))
truncate
- Truncate the port data to be specified length. It can be assumed that the
current state of
rw_active
is SCM_PORT_NEITHER
.
Set using
— Function: void
scm_set_port_truncate (
scm_t_bits tc, void (
*truncate) (
SCM port, off_t length))