Standard IO Interfaces
The :std/io
package provides interfaces for performing binary and
textual IO. The interfaces are generic, easy to implement and
compose, and the standard library provides implementations for files,
sockets, buffers, and so on.
To use bindings form the std io package:
(import :std/io)
IO Sources and Sinks
At the base of of the interface hierarchy sits the Closer
interface,
which is the general representation of closable IO sinks and sources.
Closer
(interface Closer
(close))
Closer-close
(Closer-close closer)
closer := instance of Closer
Closes the underlying IO source or sink.
Binary IO
The Reader
interface provides the basic input facilities, while
the Writer
interface provides the basic output facilities.
Reader
The Reader
interface represents binary input sources; the interface
is defined as follows:
(interface (Reader Closer)
(read output (start 0) (end (u8vector-length output)) (need 0)))
There are two methods in the Reader interface:
Reader-read
(Reader-read reader output (start 0) (end (u8vector-length output)) (need 0)) -> fixnum
reader := Reader implementation
output := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length output)
need := fixnum; 0 <= need <= end-start
Reads from a reader into the output
buffer, with the write range being [start, end)
.
Returns the number of bytes read, with 0 denoting the end of input.
If need > 0
, then it specifies the number of bytes needed; if less than need
bytes
are read before encountering the end of input, an error is raised.
Writer
The Writer
interface represents binary output sinks; the interface
is defined as follows:
(interface (Writer Closer)
(write input (start 0) (end (u8vector-length input))))
There are two methods in the Writer interface:
Writer-write
(Writer-write writer input (start 0) (end (u8vector-length output)) (need 0)) -> fixnum
writer := Writer implementation
input := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length input)
Writes into a writer from the input
buffer, with the read range being [start, end)
.
Returns the number of bytes written; if fewer bytes are written than expected, an error`
is raised.
File IO
You can operate on files using the Reader and Writer interfaces.
The following methods provide constructors for file Readers and Writers:
open-file-reader
(open-file-reader path flags: (flags default-file-reader-flags)) -> Reader
path := string
flags := fixnum
Opens a file for reading and returns a Reader instance reading from the file.
Notes:
- the path is expanded before opening the file.
- the default flags are
O_NOATIME
if available in the sytem, otherwise 0. - see
:std/os/fcntl
for relevant flags.
open-file-writer
(open-file-writer path flags: (flags default-file-writer-flags) mode: (mode #o644)) -> Writer
path := string
flags := fixnum
mode := fixnum
Opens a file for writing and returns a Writer instance writing to the file.
Notes:
- the path is expanded before opening the file.
- the default flags are
O_CREAT|O_TRUNC
. - mode is the permissions associated with the file if a new file is created.
- see
:std/os/fcntl
for relevant flags.
Sockets
Base Socket Functionality
The base Socket
interface defines methods that are common for all sockets:
(interface (Socket Closer)
(domain)
(address)
(peer-address)
(getsockopt level option)
(setsockopt level option value)
(set-input-timeout! timeo)
(set-output-timeout! timeo))
Socket-domain
(Socket-domain socket) -> fixnum
socket := Socket
Returns the domain (address family) of the socket.
Socket-address
(Socket-address socket) -> address
socket := Socket
Returns the local address of a socket.
Socket-peer-address
(Socket-peer-address socket) -> address
socket := Socket
Returns the peer address for a connected socket; this is undefined for ServerSockets.
Socket-getsockopt
(Socket-getsockopt socket level option) -> any
socket := Socket
level := fixnum
option := fixnum
Gets a socket option.
See :std/os/socket
for supported sockopts and their value types.
Socket-setsockopt
(Socket-setsockopt socket level option value)
socket := Socket
level := fixnum
option := fixnum
value := any
Sets a socket option.
See :std/os/socket
for supported sockopts and their value types.
Socket-set-input-timeout!
(Socket-set-input-timeout! socket timeo)
socket := Socket
timeo := timeout or #f
Sets the timeout for input operations on the socket.
Notes:
- #f clears the timeout
- a real value sets a relative timeout.
- a time object sets an absolute timeout.
Socket-set-output-timeout!
(Socket-set-output-timeout! socket timeo)
socket := Socket
timeo := timeout or #f
Sets the timeout for output operations on the socket.
Notes:
- #f clears the timeout
- a real value sets a relative timeout.
- a time object sets an absolute timeout.
Stream Sockets
Stream sockets extend the basic socket interface to do IO with a connected stream of bytes:
(interface (StreamSocket Socket)
(recv output (start 0) (end (u8vector-length output)) (flags 0))
(send input (start 0) (end (u8vector-length input)) (flags 0))
(reader)
(writer)
(shutdown direction))
The following methods create and operate on StreamSocket instances:
tcp-connect
(tcp-connect address (timeo #f)) -> StreamSocket
address := address
timeo := timeout or #f
Connects to an Internet address using TCP and returns a StreamSocket.
Notes:
- the address is resolved, if necessary, using a DNS lookup.
unix-connect
(unix-connect path (timeo #f)) -> StreamSocket
path := string
timeo := timeout or #f
Connects to a UNIX address and returns a StreamSocket.
StreamSocket-recv
(StreamSocket-recv socket output (start 0) (end (u8vector-length output)) (flags 0))
-> fixnum
socket := StreamSocket
output := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length output)
flags := fixnum
Receives from a socket into the output
buffer, with the write range being [start, end)
.
Returns the number of bytes read, with 0 denoting the end of input.
StreamSocket-send
(StreamSocket-send socket input (start 0) (end (u8vector-length input)) (flags 0))
-> fixnum
socket := StreamSocket
input := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length input)
flags := fixnum
Send to a socket from the input
buffer, with the write range being [start, end)
.
Returns the number of bytes written.
StreamSocket-reader
(StreamSocket-reader socket) -> Reader
socket := StreamSocket
Returns a Reader instance reading from the socket. Closing the reader shuts down the input direction of the socket.
StreamSocket-writer
(StreamSocket-writer socket) -> Writer
socket := StreamSocket
Returns a Writer instance writing to the socket. Closing the writer shuts down the output of the socket.
StreamSocket-shutdown
(StreamSocket-shutdown socket direction)
socket := StreamSocket
direction := 'in, 'out, or 'inout
Shuts down the socket in the direction specified; if both directions are shutdown, the socket is automatically closed.
Server Sockets
Server sockets abstract listening sockets that can accept connections:
(interface (ServerSocket Socket)
(accept))
The following methods create and operate on server sockets
tcp-listen
(tcp-listen address
backlog: (backlog default-backlog)
sockopts: (sockopts default-listen-sockopts))
-> ServerSocket
address := address
backlog := fixnum
sockopts := list of fixnum.
Binds and listens to a local interface address and returns a ServerSocket.
Notes:
- the address is not resolved; you can use
inaddr-any4
orinaddr-any6
as the host for binding to any interface with IPv4 and IPv6 respectively. - backlog is the backlog of the listener; defaults to 10.
- sockopts is a list of SOL_SOCKET socket options to enable.
Default is
[SO_REUSEADDR]
.
unix-listen
(unix-listen path
backlog: (backlog default-backlog)
sockopts: (sockopts default-listen-sockopts))
-> ServerSocket
path := string
backlog := fixnum
sockopts := list of fixnum.
Binds and listens to a local path and returns a ServerSocket.
ServerSocket-accept
(ServerSocket-accept socket) -> StreamSocket
socket := ServerSocket
Accepts an incoming connection from a server socket and returns the connected stream socket.
Datagram Sockets
Datagram sockets abstract packet oriented socket IO:
(interface (DatagramSocket Socket)
(recvfrom peer u8v (start 0) (end (u8vector-length u8v)) (flags 0))
(sendto peer u8v (start 0) (end (u8vector-length u8v)) (flags 0))
(connect peer)
(recv u8v (start 0) (end (u8vector-length u8v)) (flags 0))
(send u8v (start 0) (end (u8vector-length u8v)) (flags 0)))
The following methods create and operate on datagram sockets:
udp-socket
(udp-socket (address #f)) -> DatagramSocket
address := address or #f
Creates a UDP socket; if the address is not #f
then it must be a local Internet
address where the socket is bound.
udp-multicast-socket
(udp-multicast-socket group-ip-address local-address (ifindex 0)) -> DatagramSocket
group-ip-address := IP address; u8vector or string
local-address := address
ifindex := fixnum
Creates a multicast UDP socket.
DatagramSocket-recvfrom
(DatagramSocket-recvfrom socket peer output (start 0) (end (u8vector-length output)) (flags 0))
-> fixnum
socket := DatagramSocket
peer := box
output := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length output)
flags := fixnum
Receives a datagram from the socket, placing the peer's address in the supplied box. Returns the number of bytes read.
DatagramSocket-sendto
(DatagramSocket-sendto socket peer input (start 0) (end (u8vector-length input)) (flags 0))
-> fixnum
socket := DatagramSocket
peer := address
input := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length input)
flags := fixnum
Sends a datagram to a peer. Returns the number of bytes written.
DatagramSocket-connect
(DatgramSocket-connect socket peer)
Connects a datagram socket to a peer.
DatagramSocket-recv
(DatagramSocket-recv socket output (start 0) (end (u8vector-length output)) (flags 0))
-> fixnum
socket := DatagramSocket
output := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length output)
flags := fixnum
Receives a datagram from the socket, which must have been previously connected. Returns the number of bytes read.
DatagramSocket-send
(DatagramSocket-send socket input (start 0) (end (u8vector-length input)) (flags 0))
-> fixnum
socket := DatagramSocket
input := u8vector
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (u8vector-length input)
flags := fixnum
Sends a datagram to the connected peer. Returns the number of bytes written.
Addresses and default socket options
- Internet addresses are normalized as pairs, consing the host with the port;
see the
:std/net/address
module. - Unix addresses are just strings, representing file system paths.
The following are the default sockopts applied to sockets:
- stream sockets set
TCP_NODELAY
. - server sockets set
SO_REUSEADDR
. - datagram sockets that are bound set
SO_REUSEADDR
.
Buffered IO
The BufferedReader
and BufferedWriter
interfaces provide buffered
IO facilities. Buffers can be attached to any implementation of Reader
and Writer.
BufferedReader
The BufferedReader interface is defined as follows:
(interface (BufferedReader Reader)
(read-u8)
(peek-u8)
(put-back previous-input)
(skip count)
(delimit limit)
(reset! reader))
The following procedures create and apply to BufferedReader instances.
open-buffered-reader
(open-buffered-reader reader (buffer-or-size default-buffer-size)) -> BufferedReader
reader := Reader or u8vector
buffer-or-size := fixnum or u8vector
Creates a BufferedReader
using reader
as the underlying source.
If the reader
argument is a u8vector then the new buffered reader use it as a source.
The default buffer size is 32KB.
BufferedReader-peek-u8
(BufferedReader-peek-u8 buf) -> u8 or #!eof
buf := BufferedReader
Peeks the next byt from the buffer, filling it if it is empty.
Returns #!eof
if the end of input is reached.
BufferedReader-read-u8
(BufferedReader-read-u8 buf) -> u8 or #!eof
buf := BufferedReader
Reads a byte from the buffer.
Returns #!eof
if the end of input is reached.
BufferedReader-read-u8!
(BufferedReader-read-u8! buf) -> u8
buf := BufferedReader
Like BufferedReader-read-u8
, but raises an error if the end of input is reached.
BufferedReader-read-u16
(BufferedReader-read-u16 buf) -> integer
buf := BufferedReader
Reads an usigned 16 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-s16
(BufferedReader-read-s16 buf) -> integer
buf := BufferedReader
Reads a signed 16 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-u32
(BufferedReader-read-u32 buf) -> integer
buf := BufferedReader
Reads an usigned 32 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-s32
(BufferedReader-read-s32 buf) -> integer
buf := BufferedReader
Reads a signed 32 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-u64
(BufferedReader-read-u64 buf) -> integer
buf := BufferedReader
Reads an unsigned 64 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-s64
(BufferedReader-read-s64 buf) -> integer
buf := BufferedReader
Reads signed 64 bit integer, encoded in network byte order. Raises an error if the end of input is reached.
BufferedReader-read-varuint
(BufferedReader-read-varuint buf (max-bits 64)) -> integer
buf := BufferedReader
max-bits := fixnum or #f
Reads an unsigned integer, with variadic encoding and a maximum integer length of max-bits
if
specified.
Raises an error if the end of input is reached.
BufferedReader-read-varint
(BufferedReader-read-varint buf (max-bits 64)) -> integer
buf := BufferedReader
max-bits := fixnum or #f
Reads a signed integer, with variadic encoding and a maximum integer length of max-bits
Raises an error if the end of input is reached.
BufferedReader-read-char
(BufferedReader-read-char buf) -> char or #!eof
buf := BufferedReader
Reads a utf8-encoded character.
Returns #!eof
if the endo if input is reached before reading the first byte.
Raises an error if the end of input is reached prematurely for multibyte encoded characters.
Returns the utf8 replacement character and only reads a single byte if a multibyte character
cannot be decoded correctly.
BufferedReader-read-char!
(BufferedReader-read-char! buf) -> char
buf := BufferedReader
Like BufferedReader-read-char
, but raises an error if the end of
input is reached before reading the first byte.
BufferedReader-read-string
(BufferedReader-read-string buf reader str (start 0) (end (string-length str)) (need 0))
-> fixnum
buf := BufferedReader
str := string
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (string-length input)
need := fixnum
Reads a string from the buffer; semantics of the start
, end
and
need
arguments are the same as in Reader-read
, but applying to
number of characters.
Returns the number of characters read.
If need > 0
and fewer than need
characters are read, an error is raised.
BufferedReader-read-line
(BufferedReader-read-line buf (sep #\newline) (include-sep? #f) (max-chars #f)) -> string
buf := BufferedReader
sep := char or list of chars
include-sep? := bool
max-chars := fixnum or #f
Reads a line, separated by sep
and up to max-chars
of length.
The separator is either a single character or a list of characters.
If include-sep?
is true, then the separator is include in the stream.
If the separator is not encountered within max-chars
, then an error is raised.
BufferedReader-read-delimited
(BufferedReader-read-delimited buf read-value)
buf := BufferedReader
read-value := lambda (BufferedReader) -> any
Reads a varint prefix length delimited value, with read-value
reading the body.
BufferedReader-read-delimited-u8vector
(BufferedReader-read-delimited-u8vector buf) -> u8vector
buf := BufferedReader
Reads a varint prefix length delimited u8vector.
BufferedReader-read-delimited-string
(BufferedReader-read-delimited-string buf) -> string
buf := BufferedReader
Reads a varint prefix length delimited string.
BufferedReader-put-back
(BufferedReader-put-back buf previous-input)
buf := BufferedReader
previous-input := u8 or list of u8
Puts back one or more previously read bytes.
Notes:
- when putting back multiple bytes, the order is the natural one: oldest first.
- the method is guaranteed to succeed, regardless of how many bytes you are putting back; the buffer may grow as needed to accommodate the putback.
- the bytes put back do not have to be the same as bytes previously read from the input stream. Thus the method allows you to inject bytes into the input stream, which may be useful for parsers.
BufferedReader-skip
(BufferedReader-skip buf count)
buf := BufferedReader
count := fixnum
Skips the next count
bytes of input.
If the end of input is encountered before count
bytes are skipped, an error is raised.
BufferedReader-delimit
(BufferedReader-delimit buf limit) -> BufferedReader
buf := BufferedReader
limit := fixnum
returns a new BufferedReader
, sharing the same buffer, that can read up to limit
bytes.
Once the limit is reached, the new buffer signals the end of input.
Note: there is no double buffering; reading from the delimited reader advances the input on the underlying BufferedWriter.
BufferedReader-reset!
(BufferedReader-reset! buf reader)
buf := BufferedReader
reader := Reader
Resets the underlying reader and buffer state, allowing reuse of buffers from a cache.
BufferedWriter
The BufferedWriter interface is defined as follows:
(interface (BufferedWriter Writer)
(write-u8 u8)
(flush)
(reset! output))
The following procedures create and apply to BufferedWriter.
open-buffered-writer
(open-buffered-writer writer (buffer-or-size default-buffer-size)) -> BufferedWriter
writer := Writer or #f
buffer-or-size := fixnum or u8vector
Creates a BufferedWriter
using writer
as the underlying sink.
If writer
is #f
then a new buffered writer is created that collects bytes that can
be retrieved with get-buffer-output-u8vector
or get-buffered-output-chunks
.
The default buffer size is 32KB.
get-buffer-output-u8vector
(get-buffer-output-u8vector wr) -> u8vector
wr := BufferedWriter
Retrieves the output from a BufferedWriter
created with open-buffered-writer
.
get-buffer-output-chunks
(get-buffer-output-chunks wr) -> list of u8vector
wr := BufferedWriter
Retrieves the output chunks from a BufferedWriter
created with open-u8vector-buffered-writer
.
BufferedWriter-write-u8
(BufferedWriter-write-u8 buf u8) -> fixnum
buf := BufferedWriter
u8 := byte
Writes a byte to the buffer. Returns the number of bytes written.
BufferedWriter-write-u16
(BufferedWriter-write-u16 buf u16) -> fixnum
buf := BufferedWriter
u16 := integer
Writes an usigned 16 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-s16
(BufferedWriter-write-s16 buf s16) -> fixnum
buf := BufferedWriter
s16 := integer
Writes a signed 16 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-u32
(BufferedWriter-write-u32 buf u32) -> fixnum
buf := BufferedWriter
u32 := integer
Writes an usigned 32 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-s32
(BufferedWriter-write-s32 buf s32) -> fixnum
buf := BufferedWriter
s32 := integer
Writes a signed 32 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-u64
(BufferedWriter-write-u64 buf u64) -> fixnum
buf := BufferedWriter
u64 := integer
Writes an unsigned 64 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-s64
(BufferedWriter-write-s64 buf s64) -> fixnum
buf := BufferedWriter
s64 := integer
Reads signed 64 bit integer, encoded in network byte order. Returns the number of bytes written.
BufferedWriter-write-varuint
(BufferedWriter-write-varuint buf uint) -> fixnum
buf := BufferedWriter
uint := integer
Writes an unsigned integer with variadic encoding. Returns the number of bytes written.
BufferedWriter-write-varint
(BufferedWriter-write-varint buf int) -> fixnum
buf := BufferedWriter
int := integer
Writes signed integer with variadic encoding. Returns the number of bytes written.
BufferedWriter-write-char
(BufferedWriter-write-char buf char) -> fixnum
buf := BufferedWriter
char := character
Writes a character with utf8 encoding. Returns the number of bytes written.
BufferedWriter-write-string
(BufferdWriter-write-string buf str (start 0) (end (string-length str))) -> fixnum
buf := BufferedWriter
str := string
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (string-length input)
Writes a string with utf8 encoding. Returns the number of bytes written.
BufferedWriter-write-line
(BufferedWriter-write-line buf str (sep #\newline))
buf := BufferedWriter
str := string
sep := char or list of chars
Writes a string, followed by a separator. Returns the number of bytes written
BufferedWriter-write-delimited
(BufferedWriter-write-delimited buf write-value (buffer-or-size default-small-buffer-size))
buf := BufferedWriter
write-value := lambda (BufferedWriter) -> fixnum
Writes a varint prefix length delimited value, with write-value
writing the body.
BufferedWriter-write-delimited-u8vector
(BufferedWriter-read-delimited-u8vector buf bytes) -> fixnum
buf := BufferedReader
bytes := u8veftor
Writes a varint prefix length delimited u8vector.
BufferedWriter-write-delimited-string
(BufferedWriter-write-delimited-string buf str) -> fixnum
buf := BufferedWriter
str := string
Writes a varint prefix length delimited string.
BufferedWriter-flush
(BufferedWriter-flush buf)
buf := BufferedWriter
Drains the buffer into the underlying sync.
BufferedWriter-reset!
(BufferedWriter-reset! buf reader)
buf := BufferedWriter
reader := Reader
Resets the underlying writer and buffer state, allowing reuse of buffers from a cache.
Textual IO
The StringReader
interface provides the basic input facilities, while
the StringWriter
interface provides the basic output facilities.
StringReader
The StringReader
interface represents textual input sources; the interface
is defined as follows:
(interface (StringReader Closer)
(read-string str (start 0) (end (string-length str)) (need 0)))
There is one constructor two methods in the StringReader interface:
open-string-reader
(open-string-reader reader
(buffer-or-size default-buffer-size)
encoding: (codec 'UTF-8))
-> StringReader
reader := Reader or BufferedReader
Creates a StringReader
from an underlying binary Reader
or BufferedReader
,
using the specified encoding.
The only encoding currently supported is UTF-8, but more codecs will be added in the future.
StringReader-read
(StringReader-read reader output (start 0) (end (string-length output)) (need 0)) -> fixnum
reader := StringReader implementation
output := string
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (string-length output)
need := fixnum; 0 <= need <= end-start
Reads from a reader into the output
buffer, with the write range being [start, end)
.
Returns the number of characters read, with 0 denoting the end of input.
If need > 0
, then it specifies the number of bytes needed; if less than need
characters
are read before encountering the end of input, an error is raised.
StringWriter
The StringWriter
interface represents textual output sinks; the interface
is defined as follows:
(interface (StringWriter Closer)
(write-string input (start 0) (end (string-length input))))
There is one constructor two methods in the Writer interface:
open-string-writer
(open-string-writer writer
(buffer-or-size default-buffer-size)
encoding: (codec 'UTF-8))
-> StringWriter
writer := Writer or BufferedWriter
Creates a StringWriter
for an underlying binary Writer
or BufferedWriter
,
using the specified encoding.
The only encoding currently supported is UTF-8, but more codecs will be added in the future.
StringWriter-write-string
(StringWriter-write-string writer input (start 0) (end (string-length output)) (need 0)) -> fixnum
writer := StringWriter implementation
input := string
start := fixnum; 0 <= start < end
end := fixnum; start < end <= (string-length input)
Writes into a writer from the input
buffer, with the read range being [start, end)
.
Returns the number of characters written; if fewer characters are written than expected, an error`
is raised.
Buffered Textual IO
The BufferedStringReader
and BufferedStringWriter
interfaces provide buffered
textual IO facilities. Buffers can be attached to any implementation of StringReader
and StringWriter.
BufferedStringReader
The BufferedStringReader interface is defined as follows:
(interface (BufferedReader Reader)
(read-char)
(peek-char)
(put-back previous-input)
(skip count)
(delimit limit)
(reset! reader))
The following procedures create and apply to BufferedStringReader instances.
open-buffered-string-reader
(open-buffered-string-reader reader (buffer-or-size default-buffer-size)) -> BufferedStringReader
reader := StringReader or string
buffer-or-size := fixnum or string
Creates a BufferedStringReader
using reader
as the underlying source.
If the reader
argument is a string then the new buffered reader use it as a source.
The default buffer size is 32KB.
BufferedStringReader-peek-char
(BufferedStringReader-peek-char buf) -> char or #!eof
buf := BufferedStringReader
Peeks the next char from the buffer, filling it if it is empty.
Returns #!eof
if the end of input is reached.
BufferedStringReader-read-char
(BufferedStringReader-read-char buf) -> char or #!eof
buf := BufferedStringReader
Reads a char from the buffer.
Returns #!eof
if the end of input is reached.
BufferedStringReader-read-line
(BufferedStringReader-read-line buf (sep #\newline) (include-sep? #f) (max-chars #f)) -> string
buf := BufferedStringReader
sep := char or list of chars
include-sep? := bool
max-chars := fixnum or #f
Reads a line, separated by sep
and up to max-chars
of length.
The separator is either a single character or a list of characters.
If include-sep?
is true, then the separator is include in the stream.
If the separator is not encountered within max-chars
, then an error is raised.
BufferedStringReader-put-back
(BufferedStringReader-put-back buf previous-input)
buf := BufferedStringReader
previous-input := char or list of char
Puts back one or more previously read chars.
Notes:
- when putting back multiple chars, the order is the natural one: oldest first.
- the method is guaranteed to succeed, regardless of how many chars you are putting back; the buffer may grow as needed to accommodate the putback.
- the chars put back do not have to be the same as bytes previously read from the input stream. Thus the method allows you to inject characters into the input stream, which may be useful for parsers.
BufferedStringReader-skip
(BufferedStringReader-skip buf count)
buf := BufferedStringReader
count := fixnum
Skips the next count
chars of input.
If the end of input is encountered before count
chars are skipped, an error is raised.
BufferedStringReader-delimit
(BufferedStringReader-delimit buf limit) -> BufferedStringReader
buf := BufferedStringReader
limit := fixnum
returns a new BufferedStringReader
, sharing the same buffer, that can read up to limit
chars.
Once the limit is reached, the new buffer signals the end of input.
Note: there is no double buffering; reading from the delimited reader advances the input on the underlying BufferedStringReader.
BufferedStringReader-reset!
(BufferedStringReader-reset! buf reader)
buf := BufferedStringReader
reader := Reader
Resets the underlying reader and buffer state, allowing reuse of buffers from a cache.
BufferedStringWriter
The BufferedStringWriter interface is defined as follows:
(interface (BufferedStringWriter Writer)
(write-char char)
(flush)
(reset! output))
The following procedures create and apply to BufferedStringWriter.
open-buffered-string-writer
(open-buffered-writer writer (buffer-or-size default-buffer-size)) -> BufferedStringWriter
writer := StringWriter or #f
buffer-or-size := fixnum or string
Creates a BufferedStringWriter
using writer
as the underlying sink.
If writer
is #f
then a new buffered writer is created that collects bytes that can
be retrieved with get-buffer-output-string
or get-buffered-output-string-chunks
.
The default buffer size is 32KB.
get-buffer-output-string
(get-buffer-output-string wr) -> string
wr := BufferedStringWriter
Retrieves the output from a BufferedStringWriter
created with open-buffered-string-writer
.
get-buffer-output-string-chunks
(get-buffer-output-chunks wr) -> list of string
wr := BufferedStringWriter
Retrieves the output chunks from a BufferedStringWriter
created with open-buffered-string-writer
.
BufferedStringWriter-write-char
(BufferedStringWriter-write-char buf char) -> fixnum
buf := BufferedStringWriter
char := char
Writes a char to the buffer.
BufferedStringWriter-write-line
(BufferedStringWriter-write-line buf str (sep #\newline))
buf := BufferedStringWriter
str := string
sep := char or list of chars
Writes a string, followed by a separator. Returns the number of bytes written
BufferedStringWriter-flush
(BufferedStringWriter-flush buf)
buf := BufferedStringWriter
Drains the buffer into the underlying sync.
BufferedStringWriter-reset!
(BufferedStringWriter-reset! buf reader)
buf := BufferedStringWriter
reader := Reader
Resets the underlying writer and buffer state, allowing reuse of buffers from a cache.
Utilities
delimited-reader
(delimted-reader reader limit) -> Reader
reader := Reader
limit := fixnum
Creates a delimited reader that can read up to limit
bytes from reader
.
delimited-string-reader
(delimted-string-reader reader limit) -> StringReader
reader := StringReader
limit := fixnum
Creates a delimited string reader that can read up to limit
chars from reader
.
io-copy!
(io-copy! reader writer (buffer-or-size default-buffer-size)) -> fixnum
reader := Reader or StringReader
writer := Writer or StringWriter, symmetric to reader
buffer-or-size := #f, fixnum or buffer (u8vector or string)
Copies from a reader to a writer. Returns the number of bytes copied.
A Note on thread-safety
In general you should use a Reader from a single thread. There is no mutex protection for the simple reason that if you are reading from multiple threads concurrently you are already shooting yourself in the foot because your input will be non-deterministic.
Similarly for writers, you should use a Writer from a single thread at a time.
For sockets, which are full duplex, you can read and write with two threads concurrently; it is also safe to close the socket from yet another thread.