diff options
author | Andy Wingo <wingo@pobox.com> | 2023-05-28 14:20:34 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2023-06-08 10:21:02 +0200 |
commit | 075599e5b066e3f6f1a96339d0947ede923b68ff (patch) | |
tree | 45b51cb1e18e3a148b1a0a293637cce6172df898 /doc/ref/api-io.texi | |
parent | 5bdc663af902c986c09adf25e7ac583b6f764bb2 (diff) | |
download | guile-075599e5b066e3f6f1a96339d0947ede923b68ff.tar.gz |
Implement R6RS custom textual ports
* module/ice-9/textual-ports.scm (custom-textual-port-read+flush-input):
(custom-textual-port-write):
(custom-textual-port-seek):
(custom-textual-port-close):
(custom-textual-port-random-access?):
(make-custom-textual-input-port):
(make-custom-textual-output-port):
(make-custom-textual-input/output-port): New procedures.
* doc/ref/api-io.texi (Ports): Update docs.
* doc/ref/r6rs.texi (rnrs io ports): Mention custom textual port
interfaces.
* module/rnrs/io/ports.scm: Re-export custom textual port interfaces
from (ice-9 textual-ports).
* test-suite/tests/r6rs-ports.test: Add minimal tests for textual ports.
Diffstat (limited to 'doc/ref/api-io.texi')
-rw-r--r-- | doc/ref/api-io.texi | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/doc/ref/api-io.texi b/doc/ref/api-io.texi index 5d5dfa58b..70959037e 100644 --- a/doc/ref/api-io.texi +++ b/doc/ref/api-io.texi @@ -45,7 +45,7 @@ example, we might display a string to a file like this: There are also string ports, for taking input from a string, or collecting output to a string; bytevector ports, for doing the same but -using a bytevector as a source or sink of data; and soft ports, for +using a bytevector as a source or sink of data; and custom ports, for arranging to call Scheme functions to provide input or handle output. @xref{Port Types}. @@ -1390,20 +1390,27 @@ away from its default. @xref{Encoding}. @subsubsection Custom Ports Custom ports allow the user to provide input and handle output via -user-supplied procedures. Guile currently only provides custom binary -ports, not textual ports; for custom textual ports, @xref{Soft Ports}. -We should add the R6RS custom textual port interfaces though. -Contributions are appreciated. +user-supplied procedures. The most basic of these operates on the level +of bytes, calling user-supplied functions to supply bytes for input and +accept bytes for output. In Guile, textual ports are built on top of +binary ports, encoding and decoding their codepoint sequences from the +bytes; the higher-level textual layer for custom ports allows users to +deal in characters instead of bytes. + +Before using these procedures, import the appropriate module: + +@example +(use-modules (ice-9 binary-ports)) +(use-modules (ice-9 textual-ports)) +@end example @cindex custom binary input ports @deffn {Scheme Procedure} make-custom-binary-input-port id read! get-position set-position! close -Return a new custom binary input port@footnote{This is similar in spirit -to Guile's @dfn{soft ports} (@pxref{Soft Ports}).} named @var{id} (a -string) whose input is drained by invoking @var{read!} and passing it a -bytevector, an index where bytes should be written, and the number of -bytes to read. The @code{read!} procedure must return an integer -indicating the number of bytes read, or @code{0} to indicate the -end-of-file. +Return a new custom binary input port named @var{id} (a string) whose +input is drained by invoking @var{read!} and passing it a bytevector, an +index where bytes should be written, and the number of bytes to read. +The @code{read!} procedure must return an integer indicating the number +of bytes read, or @code{0} to indicate the end-of-file. Optionally, if @var{get-position} is not @code{#f}, it must be a thunk that will be called when @code{port-position} is invoked on the custom @@ -1477,13 +1484,50 @@ random-access, causing the buffer to be flushed between reads and writes. @end deffn +@cindex custom textual ports +@cindex custom textual input ports +@cindex custom textual output ports +@cindex custom textual input/output ports +@deffn {Scheme Procedure} make-custom-textual-input-port id read! get-position set-position! close +@deffnx {Scheme Procedure} make-custom-textual-output-port id write! get-position set-position! close +@deffnx {Scheme Procedure} make-custom-textual-input/output-port id read! write! get-position set-position! close +Like their custom binary port counterparts, but for textual ports. +Concretely this means that instead of being passed a bytevector, the +@var{read} function is passed a mutable string to fill, and likewise for +the buffer supplied to @var{write}. Port positions are still expressed +in bytes, however. + +If string ports were not supplied with Guile, we could implement them +With custom textual ports: +@example +(define (open-string-input-port source) + (define position 0) + (define length (string-length source)) + + (define (read! dst start count) + (let ((count (min count (- length position)))) + (string-copy! dst start source position (+ position count)) + (set! position (+ position count)) + count)) + + (make-custom-textual-input-port "strport" read! #f #f #f)) + +(read (open-string-input-port "hello")) +@end example +@end deffn + @node Soft Ports @subsubsection Soft Ports @cindex Soft port @cindex Port, soft -A @dfn{soft port} is a port based on a vector of procedures capable of -accepting or delivering characters. It allows emulation of I/O ports. +Soft ports are what Guile had before it had custom binary and textual +ports. Probably you want to use one of those instead. @xref{Custom +Ports}. + +But since you are still here, a @dfn{soft port} is a port based on a +vector of procedures capable of accepting or delivering characters. It +allows emulation of I/O ports. @deffn {Scheme Procedure} make-soft-port pv modes Return a port capable of receiving or delivering characters as @@ -1532,7 +1576,6 @@ For example: @end lisp @end deffn - @node Void Ports @subsubsection Void Ports @cindex Void port |