doc: Started documenting `(rnrs io ports)'.
[guile-r6rs-libs.git] / doc / api-r6rs.texi
blob3d80436eecc6beb8b1cc3cbf2993ae640ad472f1
1 @cindex R6RS
2 @cindex R6RS libraries
4 This section describes Guile's implementation of some of the standard
5 libraries defined in the ``Revised^6 Report on the Algorithmic
6 Language'' aka. @url{http://www.r6rs.org/, R6RS}.
8 @menu
9 * Bytevectors::                 Interpreting raw bit strings.
10 * R6RS I/O Ports::              Input/output ports.
11 @end menu
13 @c *********************************************************************
14 @node Bytevectors
15 @section Bytevectors
17 @cindex bytevector
19 A @dfn{bytevector} is a raw bit string.  The @code{(rnrs bytevector)}
20 module provides procedures to manipulate bytevectors and interpret their
21 contents in a number of ways: bytevector contents can be accessed as
22 signed or unsigned integer of various sizes and endianness, as IEEE-754
23 floating point numbers, or as strings.  It is a useful tool to decode
24 binary data.
26 @menu
27 * Bytevector Endianness::       Dealing with byte order.
28 * Bytevector Manipulation::     Creating, copying, manipulating bytevectors.
29 * Bytevectors as Integers::     Interpreting bytes as integers.
30 * Bytevectors and Integer Lists::  Converting to/from an integer list.
31 * Bytevectors as Floats::       Interpreting bytes as real numbers.
32 * Bytevectors as Strings::      Interpreting bytes as Unicode strings.
33 @end menu
35 @node Bytevector Endianness
36 @subsection Endianness
38 @cindex endianness
39 @cindex byte order
40 @cindex word order
42 Some of the following procedures take an @var{endianness} parameter.
43 The @dfn{endianness} is defined is defined as the order of bytes in
44 multi-byte numbers: numbers encoded in @dfn{big endian} have their most
45 significant bytes written first, whereas numbers encoded in @dfn{little
46 endian} have their least significant bytes first@footnote{Big and little
47 endian are the most common ``endiannesses'' but others exist.  For
48 instance, the GNU MP library allows @dfn{word order} to be specified
49 independently of @dfn{byte order} (@pxref{Integer Import and Export,,,
50 gmp, The GNU Multiple Precision Arithmetic Library Manual}).}  Little
51 endian is the native endianness of the IA32 architecture and its
52 derivatives, while big endian is native to SPARC and PowerPC, among
53 others.  The @code{native-endianness} procedure returns the native
54 endianness of the machine it runs on.
56 @deffn {Scheme Procedure} native-endianness
57 @deffnx {C Function} scm_r6rs_native_endianness ()
58 Return a value denoting the native endianness of the host machine.
59 @end deffn
61 @deffn {Scheme Macro} endianness symbol
62 Return an object denoting the endianness specified by @var{symbol}.  If
63 @var{symbol} is neither @code{big} nor @code{little} then a compile-time
64 error is raised.
65 @end deffn
67 @defvr {C Variable} scm_r6rs_endianness_big
68 @defvrx {C Variable} scm_r6rs_endianness_little
69 The objects denoting big (resp. little) endianness.
70 @end defvr
73 @node Bytevector Manipulation
74 @subsection Manipulating Bytevectors
76 Bytevectors can be created, copied, and analyzed with the following
77 procedures.
79 @deffn {Scheme Procedure} make-bytevector len [fill]
80 @deffnx {C Function} scm_r6rs_make_bytevector (len, fill)
81 @deffnx {C Function} scm_r6rs_c_make_bytevector (unsigned len)
82 Return a new bytevector of @var{len} bytes.  Optionally, if @var{fill}
83 is given, fill it with @var{fill}; @var{fill} must be an 8-bit signed
84 integer, i.e., in the range [-128,127].
85 @end deffn
87 @deffn {Scheme Procedure} bytevector? obj
88 @deffnx {C Function} scm_r6rs_bytevector_p (obj)
89 Return true if @var{obj} is a bytevector.
90 @end deffn
92 @deffn {Scheme Procedure} bytevector-length bv
93 @deffnx {C Function} scm_r6rs_bytevector_length (bv)
94 Return the length in bytes of bytevector @var{bv}.
95 @end deffn
97 @deffn {Scheme Procedure} bytevector=? bv1 bv2
98 @deffnx {C Function} scm_r6rs_bytevector_eq_p (bv1, bv2)
99 Return is @var{bv1} equals to @var{bv2}---i.e., if they have the same
100 length and contents.
101 @end deffn
103 @deffn {Scheme Procedure} bytevector-fill! bv fill
104 @deffnx {C Function} scm_r6rs_bytevector_fill_x (bv, fill)
105 Fill bytevector @var{bv} with @var{fill}, a byte.
106 @end deffn
108 @deffn {Scheme Procedure} bytevector-copy! source source-start target target-start len
109 @deffnx {C Function} scm_r6rs_bytevector_copy_x (source, source_start, target, target_start, len)
110 Copy @var{len} bytes from @var{source} into @var{target}, starting
111 reading from @var{source-start} (a positive index within @var{source})
112 and start writing at @var{target-start}.
113 @end deffn
115 @deffn {Scheme Procedure} bytevector-copy bv
116 @deffnx {C Function} scm_r6rs_bytevector_copy (bv)
117 Return a newly allocated copy of @var{bv}.
118 @end deffn
120 Low-level C macros are available.  They do not perform any
121 type-checking; as such they should be used with care.
123 @deftypefn {C Macro} size_t SCM_R6RS_BYTEVECTOR_LENGTH (bv)
124 Return the length in bytes of bytevector @var{bv}.
125 @end deftypefn
127 @deftypefn {C Macro} {signed char *} SCM_R6RS_BYTEVECTOR_CONTENTS (bv)
128 Return a pointer to the contents of bytevector @var{bv}.
129 @end deftypefn
132 @node Bytevectors as Integers
133 @subsection Interpreting Bytevector Contents as Integers
135 The contents of a bytevector can be interpreted as a sequence of
136 integers of any given size, sign, and endianness.
138 @lisp
139 (let ((bv (make-bytevector 4)))
140   (bytevector-u8-set! bv 0 #x12)
141   (bytevector-u8-set! bv 1 #x34)
142   (bytevector-u8-set! bv 2 #x56)
143   (bytevector-u8-set! bv 3 #x78)
145   (map (lambda (number)
146          (number->string number 16))
147        (list (bytevector-u8-ref bv 0)
148              (bytevector-u16-ref bv 0 (endianness big))
149              (bytevector-u32-ref bv 0 (endianness little)))))
151 @result{} ("12" "1234" "78563412")
152 @end lisp
154 The most generic procedures to interpret bytevector contents as integers
155 are described below.
157 @deffn {Scheme Procedure} bytevector-uint-ref bv index endianness size
158 @deffnx {Scheme Procedure} bytevector-sint-ref bv index endianness size
159 @deffnx {C Function} scm_r6rs_bytevector_uint_ref (bv, index, endianness, size)
160 @deffnx {C Function} scm_r6rs_bytevector_sint_ref (bv, index, endianness, size)
161 Return the @var{size}-byte long unsigned (resp. signed) integer at
162 index @var{index} in @var{bv}, decoded according to @var{endianness}.
163 @end deffn
165 @deffn {Scheme Procedure} bytevector-uint-set! bv index value endianness size
166 @deffnx {Scheme Procedure} bytevector-sint-set! bv index value endianness size
167 @deffnx {C Function} scm_r6rs_bytevector_uint_set_x (bv, index, value, endianness, size)
168 @deffnx {C Function} scm_r6rs_bytevector_sint_set_x (bv, index, value, endianness, size)
169 Set the @var{size}-byte long unsigned (resp. signed) integer at
170 @var{index} to @var{value}, encoded according to @var{endianness}.
171 @end deffn
173 The following procedures are similar to the ones above, but specialized
174 to a given integer size:
176 @deffn {Scheme Procedure} bytevector-u8-ref bv index
177 @deffnx {Scheme Procedure} bytevector-s8-ref bv index
178 @deffnx {Scheme Procedure} bytevector-u16-ref bv index endianness
179 @deffnx {Scheme Procedure} bytevector-s16-ref bv index endianness
180 @deffnx {Scheme Procedure} bytevector-u32-ref bv index endianness
181 @deffnx {Scheme Procedure} bytevector-s32-ref bv index endianness
182 @deffnx {Scheme Procedure} bytevector-u64-ref bv index endianness
183 @deffnx {Scheme Procedure} bytevector-s64-ref bv index endianness
184 @deffnx {C Function} scm_r6rs_bytevector_u8_ref (bv, index)
185 @deffnx {C Function} scm_r6rs_bytevector_s8_ref (bv, index)
186 @deffnx {C Function} scm_r6rs_bytevector_u16_ref (bv, index, endianness)
187 @deffnx {C Function} scm_r6rs_bytevector_s16_ref (bv, index, endianness)
188 @deffnx {C Function} scm_r6rs_bytevector_u32_ref (bv, index, endianness)
189 @deffnx {C Function} scm_r6rs_bytevector_s32_ref (bv, index, endianness)
190 @deffnx {C Function} scm_r6rs_bytevector_u64_ref (bv, index, endianness)
191 @deffnx {C Function} scm_r6rs_bytevector_s64_ref (bv, index, endianness)
192 Return the unsigned @var{n}-bit (signed) integer (where @var{n} is 8,
193 16, 32 or 64) from @var{bv} at @var{index}, decoded according to
194 @var{endianness}.
195 @end deffn
197 @deffn {Scheme Procedure} bytevector-u8-set! bv index value
198 @deffnx {Scheme Procedure} bytevector-s8-set! bv index value
199 @deffnx {Scheme Procedure} bytevector-u16-set! bv index value endianness
200 @deffnx {Scheme Procedure} bytevector-s16-set! bv index value endianness
201 @deffnx {Scheme Procedure} bytevector-u32-set! bv index value endianness
202 @deffnx {Scheme Procedure} bytevector-s32-set! bv index value endianness
203 @deffnx {Scheme Procedure} bytevector-u64-set! bv index value endianness
204 @deffnx {Scheme Procedure} bytevector-s64-set! bv index value endianness
205 @deffnx {C Function} scm_r6rs_bytevector_u8_set_x (bv, index, value)
206 @deffnx {C Function} scm_r6rs_bytevector_s8_set_x (bv, index, value)
207 @deffnx {C Function} scm_r6rs_bytevector_u16_set_x (bv, index, value, endianness)
208 @deffnx {C Function} scm_r6rs_bytevector_s16_set_x (bv, index, value, endianness)
209 @deffnx {C Function} scm_r6rs_bytevector_u32_set_x (bv, index, value, endianness)
210 @deffnx {C Function} scm_r6rs_bytevector_s32_set_x (bv, index, value, endianness)
211 @deffnx {C Function} scm_r6rs_bytevector_u64_set_x (bv, index, value, endianness)
212 @deffnx {C Function} scm_r6rs_bytevector_s64_set_x (bv, index, value, endianness)
213 Store @var{value} as an @var{n}-bit (signed) integer (where @var{n} is
214 8, 16, 32 or 64) in @var{bv} at @var{index}, encoded according to
215 @var{endianness}.
216 @end deffn
218 Finally, a variant specialized for the host's endianness is available
219 for each of these functions (with the exception of the @code{u8}
220 accessors, for obvious reasons):
222 @deffn {Scheme Procedure} bytevector-u16-native-ref bv index
223 @deffnx {Scheme Procedure} bytevector-s16-native-ref bv index
224 @deffnx {Scheme Procedure} bytevector-u32-native-ref bv index
225 @deffnx {Scheme Procedure} bytevector-s32-native-ref bv index
226 @deffnx {Scheme Procedure} bytevector-u64-native-ref bv index
227 @deffnx {Scheme Procedure} bytevector-s64-native-ref bv index
228 @deffnx {C Function} scm_r6rs_bytevector_u16_native_ref (bv, index)
229 @deffnx {C Function} scm_r6rs_bytevector_s16_native_ref (bv, index)
230 @deffnx {C Function} scm_r6rs_bytevector_u32_native_ref (bv, index)
231 @deffnx {C Function} scm_r6rs_bytevector_s32_native_ref (bv, index)
232 @deffnx {C Function} scm_r6rs_bytevector_u64_native_ref (bv, index)
233 @deffnx {C Function} scm_r6rs_bytevector_s64_native_ref (bv, index)
234 Return the unsigned @var{n}-bit (signed) integer (where @var{n} is 8,
235 16, 32 or 64) from @var{bv} at @var{index}, decoded according to the
236 host's native endianness.
237 @end deffn
239 @deffn {Scheme Procedure} bytevector-u16-native-set! bv index value
240 @deffnx {Scheme Procedure} bytevector-s16-native-set! bv index value
241 @deffnx {Scheme Procedure} bytevector-u32-native-set! bv index value
242 @deffnx {Scheme Procedure} bytevector-s32-native-set! bv index value
243 @deffnx {Scheme Procedure} bytevector-u64-native-set! bv index value
244 @deffnx {Scheme Procedure} bytevector-s64-native-set! bv index value
245 @deffnx {C Function} scm_r6rs_bytevector_u16_native_set_x (bv, index, value)
246 @deffnx {C Function} scm_r6rs_bytevector_s16_native_set_x (bv, index, value)
247 @deffnx {C Function} scm_r6rs_bytevector_u32_native_set_x (bv, index, value)
248 @deffnx {C Function} scm_r6rs_bytevector_s32_native_set_x (bv, index, value)
249 @deffnx {C Function} scm_r6rs_bytevector_u64_native_set_x (bv, index, value)
250 @deffnx {C Function} scm_r6rs_bytevector_s64_native_set_x (bv, index, value)
251 Store @var{value} as an @var{n}-bit (signed) integer (where @var{n} is
252 8, 16, 32 or 64) in @var{bv} at @var{index}, encoded according to the
253 host's native endianness.
254 @end deffn
257 @node Bytevectors and Integer Lists
258 @subsection Converting Bytevectors to/from Integer Lists
260 Bytevector contents can readily be converted to/from lists of signed or
261 unsigned integers:
263 @lisp
264 (bytevector->sint-list (u8-list->bytevector (make-list 4 255))
265                        (endianness little) 2)
266 @result{} (-1 -1)
267 @end lisp
269 @deffn {Scheme Procedure} bytevector->u8-list bv
270 @deffnx {C Function} scm_r6rs_bytevector_to_u8_list (bv)
271 Return a newly allocated list of unsigned 8-bit integers from the
272 contents of @var{bv}.
273 @end deffn
275 @deffn {Scheme Procedure} u8-list->bytevector lst
276 @deffnx {C Function} scm_r6rs_u8_list_to_bytevector (lst)
277 Return a newly allocated bytevector consisting of the unsigned 8-bit
278 integers listed in @var{lst}.
279 @end deffn
281 @deffn {Scheme Procedure} bytevector->uint-list bv endianness size
282 @deffnx {Scheme Procedure} bytevector->sint-list bv endianness size
283 @deffnx {C Function} scm_r6rs_bytevector_to_uint_list (bv, endianness, size)
284 @deffnx {C Function} scm_r6rs_bytevector_to_sint_list (bv, endianness, size)
285 Return a list of unsigned (resp. signed) integers of @var{size} bytes
286 representing the contents of @var{bv}, decoded according to
287 @var{endianness}.
288 @end deffn
291 @node Bytevectors as Floats
292 @subsection Interpreting Bytevector Contents as Floating Point Numbers
294 @cindex IEEE-754 floating point numbers
296 Bytevector contents can also be accessed as IEEE-754 single- or
297 double-precision floating point numbers (respectively 32 and 64-bit
298 long) using the procedures described here.
300 @deffn {Scheme Procedure} bytevector-ieee-single-ref bv index endianness
301 @deffnx {Scheme Procedure} bytevector-ieee-double-ref bv index endianness
302 @deffnx {C Function} scm_r6rs_bytevector_ieee_single_ref (bv, index, endianness)
303 @deffnx {C Function} scm_r6rs_bytevector_ieee_double_ref (bv, index, endianness)
304 Return the IEEE-754 single-precision floating point number from @var{bv}
305 at @var{index} according to @var{endianness}.
306 @end deffn
308 @deffn {Scheme Procedure} bytevector-ieee-single-set! bv index value endianness
309 @deffnx {Scheme Procedure} bytevector-ieee-double-set! bv index value endianness
310 @deffnx scm_r6rs_bytevector_ieee_single_set_x (bv, index, value, endianness)
311 @deffnx scm_r6rs_bytevector_ieee_double_set_x (bv, index, value, endianness)
312 Store real number @var{value} in @var{bv} at @var{index} according to
313 @var{endianness}.
314 @end deffn
316 Specialized procedures are also available:
318 @deffn {Scheme Procedure} bytevector-ieee-single-native-ref bv index
319 @deffnx {Scheme Procedure} bytevector-ieee-double-native-ref bv index
320 @deffnx {C Function} scm_r6rs_bytevector_ieee_single_native_ref (bv, index)
321 @deffnx {C Function} scm_r6rs_bytevector_ieee_double_native_ref (bv, index)
322 Return the IEEE-754 single-precision floating point number from @var{bv}
323 at @var{index} according to the host's native endianness.
324 @end deffn
326 @deffn {Scheme Procedure} bytevector-ieee-single-native-set! bv index value
327 @deffnx {Scheme Procedure} bytevector-ieee-double-native-set! bv index value
328 @deffnx scm_r6rs_bytevector_ieee_single_native_set_x (bv, index, value)
329 @deffnx scm_r6rs_bytevector_ieee_double_native_set_x (bv, index, value)
330 Store real number @var{value} in @var{bv} at @var{index} according to
331 the host's native endianness.
332 @end deffn
335 @node Bytevectors as Strings
336 @subsection Interpreting Bytevector Contents as Unicode Strings
338 Bytevector contents can also be interpreted as Unicode strings encoded
339 in one of the most commonly available encoding formats@footnote{Guile
340 1.8 does @emph{not} support Unicode strings.  Therefore, the procedures
341 described here assume that Guile strings are internally encoded
342 according to the current locale.  For instance, if @code{$LC_CTYPE} is
343 @code{fr_FR.ISO-8859-1}, then @code{string->utf-8} @i{et al.} will
344 assume that Guile strings are Latin-1-encoded.}.
346 @lisp
347 (utf8->string (u8-list->bytevector '(99 97 102 101)))
348 @result{} "cafe"
350 (string->utf8 "caf@'e") ;; SMALL LATIN LETTER E WITH ACUTE ACCENT
351 @result{} #vu8(99 97 102 195 169)
352 @end lisp
354 @deffn {Scheme Procedure} string->utf8 str
355 @deffnx {Scheme Procedure} string->utf16 str
356 @deffnx {Scheme Procedure} string->utf32 str
357 @deffnx {C Function} scm_r6rs_string_to_utf8 (str)
358 @deffnx {C Function} scm_r6rs_string_to_utf16 (str)
359 @deffnx {C Function} scm_r6rs_string_to_utf32 (str)
360 Return a newly allocated bytevector that contains the UTF-8, UTF-16, or
361 UTF-32 (aka. UCS-4) encoding of @var{str}.
362 @end deffn
364 @deffn {Scheme Procedure} utf8->string utf
365 @deffnx {Scheme Procedure} utf16->string utf
366 @deffnx {Scheme Procedure} utf32->string utf
367 @deffnx {C Function} scm_r6rs_utf8_to_string (utf)
368 @deffnx {C Function} scm_r6rs_utf16_to_string (utf)
369 @deffnx {C Function} scm_r6rs_utf32_to_string (utf)
370 Return a newly allocated string that contains from the UTF-8-, UTF-16-,
371 or UTF-32-decoded contents of bytevector @var{utf}.
372 @end deffn
375 @c *********************************************************************
376 @node R6RS I/O Ports
377 @section I/O Ports
379 The I/O port API of the R6RS is provided by the @code{(rnrs io ports)}
380 module.  In many areas it complements or refines Guile's own historical
381 port API (@pxref{Input and Output,,, guile, The GNU Guile Reference
382 Manual}).
384 @c FIXME: Update description when implemented.
385 @emph{Note}: The implementation of this R6RS API is currently far from
386 complete, notably due to the lack of support for Unicode I/O and strings
387 in Guile 1.8.
389 @menu
390 * R6RS End-of-File::            The end-of-file object.
391 * R6RS Port Manipulation::      Manipulating R6RS ports.
392 * R6RS Binary I/O::             Binary input/output.
393 @end menu
395 @node R6RS End-of-File
396 @subsection The End-of-File Object
398 @cindex EOF
399 @cindex end-of-file
401 R5RS' @code{eof-object?} procedure is provided by the @code{(rnrs io
402 ports)} module:
404 @deffn {Scheme Procedure} eof-object? obj
405 @deffnx {C Function} scm_eof_object_p (obj)
406 Return true if @var{obj} is the end-of-file (EOF) object.
407 @end deffn
409 In addition, the following procedure is provided:
411 @deffn {Scheme Procedure} eof-object
412 @deffnx {C Function} scm_r6rs_eof_object ()
413 Return the end-of-file (EOF) object.
415 @lisp
416 (eof-object? (eof-object))
417 @result{} #t
418 @end lisp
419 @end deffn
422 @node R6RS Port Manipulation
423 @subsection Port Manipulation
425 The procedures listed below operate on any kind of R6RS I/O port.
427 @deffn {Scheme Procedure} port-position port
428 If @var{port} supports it (see below), return the offset (an integer)
429 indicating where the next octet will be read from/written to in
430 @var{port}.  If @var{port} does not support this operation, an error
431 condition is raised.
432 @end deffn
434 @deffn {Scheme Procedure} port-has-port-position? port
435 Return @code{#t} is @var{port} supports @code{port-position}.
436 @end deffn
438 @deffn {Scheme Procedure} set-port-position! port offset
439 If @var{port} supports it (see below), set the position where the next
440 octet will be read from/written to @var{port} to @var{offset} (an
441 integer).  If @var{port} does not support this operation, an error
442 condition is raised.
443 @end deffn
445 @deffn {Scheme Procedure} port-has-set-port-position!? port
446 Return @code{#t} is @var{port} supports @code{set-port-position!}.
447 @end deffn
449 @deffn {Scheme Procedure} call-with-port port proc
450 Call @var{proc}, passing it @var{port} and closing @var{port} upon exit
451 of @var{proc}.  Return the return values of @var{proc}.
452 @end deffn
455 @node R6RS Binary I/O
456 @subsection Binary Input/Output
458 @cindex binary input
460 R6RS binary input and output ports can be created with the procedures
461 described below.
463 @deffn {Scheme Procedure} open-bytevector-input-port bv [transcoder]
464 @deffnx {C Function} scm_r6rs_open_bytevector_input_port (bv, transcoder)
465 Return an input port whose contents are drawn from bytevector @var{bv}
466 (@pxref{Bytevectors}).
468 @c FIXME: Update description when implemented.
469 The @var{transcoder} argument is currently not supported.
470 @end deffn
472 @deffn {Scheme Procedure} open-bytevector-output-port [transcoder]
473 @deffnx {C Function} scm_r6rs_open_bytevector_output_port (transcoder)
474 Return two values: a binary output port and a procedure.  The latter
475 should be called with zero arguments to obtain a bytevector containing
476 the data accumulated by the port, as illustrated below.
478 @lisp
479 (call-with-values
480   (lambda ()
481     (open-bytevector-output-port))
482   (lambda (port get-bytevector)
483     (display "hello" port)
484     (get-bytevector)))
486 @result{} #vu8(104 101 108 108 111)
487 @end lisp
489 @c FIXME: Update description when implemented.
490 The @var{transcoder} argument is currently not supported.
491 @end deffn
493 @cindex custom binary input ports
495 @deffn {Scheme Procedure} make-custom-binary-input-port id read! [get-position [set-position! [close]]]
496 @deffnx {C Function} scm_r6rs_make_custom_binary_input_port (id, read!, get-position, set-position!, close)
497 Return a new custom binary input port@footnote{This is similar in spirit
498 to Guile's @dfn{soft ports} (@pxref{Soft Ports,,, guile, The GNU Guile
499 Reference Manual}).} named @var{id} (a string) whose input is drained by
500 invoking @var{read!} and passing it a bytevector, an index where bytes
501 should be written, and the number of bytes to read.  The @code{read!}
502 procedure must return an integer indicating the number of bytes read, or
503 @code{0} to indicate the end-of-file.
505 Optionally, @var{get-position}, a thunk, will be called when
506 @var{port-position} is invoked on the custom binary port and should
507 return an integer indicating the position within the underlying data
508 stream; if @var{get-position} was not supplied, the returned port does
509 not support @var{port-position}.
511 Likewise, if @var{set-position!} is given, it should be a one-argument
512 procedure.  When @var{set-port-position!} is invoked on the custom
513 binary input port, @var{set-position!} is passed an integer indicating
514 the position of the next byte is to read.
516 Finally, if @var{close} is supplied, it must be a thunk.  It is invoked
517 when the custom binary input port is closed.
519 Using a custom binary input port, the @code{open-bytevector-input-port}
520 could be implemented as follows:
522 @lisp
523 (define (open-bytevector-input-port source)
524   (define position 0)
525   (define length (bytevector-length source))
527   (define (read! bv start count)
528     (let ((count (min count (- length position))))
529       (bytevector-copy! source position
530                         bv start count)
531       (set! position (+ position count))
532       count))
534   (define (get-position) position)
536   (define (set-position! new-position)
537     (set! position new-position))
539   (make-custom-binary-input-port "the port" read!
540                                   get-position
541                                   set-position!))
543 (read (open-bytevector-input-port (string->utf8 "hello")))
544 @result{} hello
545 @end lisp
546 @end deffn
549 FIXME: Finish.
551 @c LocalWords:  Bytevectors bytevector bytevectors endianness  endian accessors
552 @c LocalWords:  endiannesses
554 @c Local Variables:
555 @c ispell-local-dictionary: "american"
556 @c End: