Title

Stream Ports

Author

Michael Sperber

Status

This SRFI is currently in ``withdrawn'' status. For an explanation of each status that a SRFI can hold, see here. You can access the discussion via the archive of the mailing list.

Abstract

This SRFI augments SRFI 81 (Port I/O) by allowing ports to be constructed from streams as described in SRFI 80 (Stream I/O).

Rationale

Streams provide all the functionality necessary for implementing ports. Sometimes, a stream is available when a port is needed. This SRFI describes an API for constructing ports from streams, and specifies their semantics in terms of it. The resulting semantics is completely consistent with the semantics of "standard" ports. In fact, implementations may choose to implement all ports on top of streams.

Specification

Prerequisites

This SRFI is meant for Scheme implementations with support for SRFIs SRFI 80 (Stream I/O), and SRFI 81 (Port I/O).

Stream ports

These are the procedures that are specific to stream ports.

Stream input ports

(make-stream-input-port input-stream)

This creates a stream input port that points to input-stream.

(stream-input-port? obj)

This returns #t if the argument is a stream input port, #f otherwise.

(input-port-stream stream-input-port)

This returns the input stream underlying stream-input-port.

(set-input-port-stream! stream-input-port input-stream)

This sets the input stream underlying stream-input-port to input-stream.

Stream output ports

(make-stream-output-port output-stream)

This creates a stream output port that points to output-stream.

(stream-output-port? obj)

This returns #t if the argument is a stream output port, #f otherwise.

(output-port-stream stream-output-port)

This returns the output stream underlying stream-output-port.

(set-output-port-stream! stream-output-port output-stream)

This sets the output stream underlying stream-output-port to output-stream.

Port Operations

The following text describes how the operations on ports specified in SRFI 81 (Port I/O) operate on stream ports. Thus, the descriptions here augment those in the Port I/O SRFI for the special case of stream-port arguments.

Stream Input ports

(read-blob-some input-port)

This calls input-blob-some on the underlying input stream, updates the underlying input stream to the second return value, and returns input-blob-some's first return value.

(read-u8 input-port)

This calls input-u8 on the underlying input stream, updates the underlying input stream to the second return value, and returns input-u8's first return value.

(read-blob-n input-port n)

This calls input-blob-n on the underlying input stream, updates the underlying input stream to the second return value, and returns input-blob-n's first return value.

(read-blob-n! input-port blob start count)

This calls input-blob-n! on the underlying input stream, updates the underlying input stream to the second return value, and returns input-blob-n!'s first return value.

(read-blob-all input-port)

This calls input-blob-all on the underlying input stream, updates the underlying input stream to the second return value, and returns input-blob-all's first return value.

(read-string input-port)

This calls input-string on the underlying input stream, updates the underlying input stream to the second return value, and returns input-string's first return value.

(read-char input-port)

This calls input-char on the underlying input stream, updates the underlying input stream to the second return value, and returns input-char's first return value.

(read-string-n input-port n)

This calls input-string-n on the underlying input stream, updates the underlying input stream to the second return value, and returns input-string-n's first return value.

(read-string-n! input-port string start count)

This calls input-string-n! on the underlying input stream, updates the underlying input stream to the second return value, and returns input-string-n!'s first return value.

(read-string-all input-port)

This calls input-string-all on the underlying input stream, updates the underlying input stream to the second return value, and returns input-string-all's first return value.

(peek-u8 input-port)

This calls input-u8 on the underlying input stream, but does not update the underlying input stream. It returns input-u8's first return value.

(peek-char input-port)

This calls input-char on the underlying input stream, but does not update the underlying input stream. It returns input-char's first return value.

(port-eof? input-port)

This returns the result of calling stream-eof? on the input stream underlying input-port.

(input-port-position input-port)

This calls input-stream-position on the underlying input stream and returns the result.

(set-input-port-position! input-port pos)

This extracts the underlying reader, sets its position, and sets the reader of the port to a new input stream constructed from the same reader.

(transcode-input-port! input-port transcoder)

This calls transcode-input-stream on the underlying stream and updates the port with the result.

(close-input-port input-port)

For a stream input port, this calls close-input-stream on the stream underlying input-port.

Stream Output ports

(write-blob output-port blob)
(write-blob output-port blob start)
(write-blob output-port blob start count)

This calls output-blob on the underlying output stream and blob, start and count.

(write-u8 output-port octet)

This calls output-u8 on the underlying output stream and u8. The return values are unspecified.

(write-string-n output-port string)
(write-string-n output-port string start)
(write-string-n output-port string start count)

This calls output-string on the underlying output stream and string, start and count.

(write-char output-port char)

This calls output-char on the underlying output stream and char.

(newline output-port)

This is equivalent to (write-char #\newline output-port). The return values are unspecified.

(flush-output-port output-port)

This calls flush-output-stream on the underlying output stream.

(output-port-buffer-mode output-port)

For a stream output port, this calls output-stream-buffer-mode on the underlying output stream.

(set-output-port-buffer-mode! output-port buffer-mode)

This calls set-output-stream-buffer-mode! on the underlying output stream.

(output-port-position output-port)

This calls output-stream-position on the underlying output stream and returns the result.

(set-output-port-position! output-port pos)

This calls set-output-stream-position! on the underlying output stream with pos and returns whatever it returns.

(transcode-output-port! output-port transcoder)

This calls transcode-output-stream on the underlying stream and updates the port with the result.

(close-output-port output-port)

This calls close-output-stream on the stream underlying output-port.

Reference Implementation

Here is a tarball containing a reference implementation of this SRFI. It only runs on a version of Scheme 48 that has not been released at the time of writing in this SRFI.

However, its actual dependencies on Scheme 48 idiosyncracies are few. Chief are its use of the module system, which is easily replaced by another, and the implementation of Unicode. To implement primitive readers and writers on files, the code only relies on suitable library procedures to open the files, and read-byte and write-byte procedures to read or write single bytes from a (R5RS) port, as well as a force-output procedure to flush a port.

The reference implementation has not been highly tuned, but I have spent a modest amount of time making the code deal with buffers in an economic buffer. Because of this, the code is more complicated than it needs to be, but hopefully also more usable as a basis for implementing this SRFI in actual Scheme systems.

Acknowledgements

Sebastian Egner provided valuable comments on a draft of this SRFI.

References

Copyright

Copyright (C) Michael Sperber (2005). All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Donovan Kolbly