123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- ;;; binary-ports.scm --- Binary IO on ports
- ;;; Copyright (C) 2009-2011,2013,2016,2019,2021,2023 Free Software Foundation, Inc.
- ;;;
- ;;; This library is free software: you can redistribute it and/or modify
- ;;; it under the terms of the GNU Lesser General Public License as
- ;;; published by the Free Software Foundation, either version 3 of the
- ;;; License, or (at your option) any later version.
- ;;;
- ;;; This library is distributed in the hope that it will be useful, but
- ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;;; Lesser General Public License for more details.
- ;;;
- ;;; You should have received a copy of the GNU Lesser General Public
- ;;; License along with this program. If not, see
- ;;; <http://www.gnu.org/licenses/>.
- ;;; Author: Ludovic Courtès <ludo@gnu.org>
- ;;; Commentary:
- ;;;
- ;;; The I/O port API of the R6RS is provided by this module. In many areas
- ;;; it complements or refines Guile's own historical port API. For instance,
- ;;; it allows for binary I/O with bytevectors.
- ;;;
- ;;; Code:
- (define-module (ice-9 binary-ports)
- #:use-module (rnrs bytevectors)
- #:use-module (ice-9 match)
- #:use-module (ice-9 custom-ports)
- #:export (eof-object
- open-bytevector-input-port
- open-bytevector-output-port
- get-u8
- lookahead-u8
- get-bytevector-n
- get-bytevector-n!
- get-bytevector-some
- get-bytevector-some! ; Guile extension, not in R6RS
- get-bytevector-all
- get-string-n!
- put-u8
- put-bytevector
- unget-bytevector
- make-custom-binary-input-port
- make-custom-binary-output-port
- make-custom-binary-input/output-port
- call-with-input-bytevector
- call-with-output-bytevector))
- ;; Note that this extension also defines %make-transcoded-port, which is
- ;; not exported but is used by (rnrs io ports).
- (load-extension (string-append "libguile-" (effective-version))
- "scm_init_r6rs_ports")
- (define (call-with-input-bytevector bv proc)
- "Call the one-argument procedure @var{proc} with a newly created
- binary input port from which the bytevector @var{bv}'s contents may be
- read. All values yielded by @var{proc} are returned."
- (proc (open-bytevector-input-port bv)))
- (define (call-with-output-bytevector proc)
- "Call the one-argument procedure @var{proc} with a newly created
- binary output port. When the function returns, port is closed and the
- bytevector composed of the bytes written into the port is returned."
- (call-with-values
- (lambda ()
- (open-bytevector-output-port))
- (lambda (port get-bytevector)
- (proc port)
- (let ((bv (get-bytevector)))
- (close-port port)
- bv))))
- (define (type-error proc expecting val)
- (scm-error 'wrong-type-arg proc "Wrong type (expecting `~S'): ~S"
- (list expecting val) (list val)))
- (define (custom-binary-port-read read)
- (unless (procedure? read)
- (type-error "custom-binary-port-read" "procedure" read))
- (lambda (port bv start count)
- (let ((ret (read bv start count)))
- (unless (and (exact-integer? ret) (<= 0 ret count))
- (scm-error 'out-of-range "custom-binary-port-read"
- "Value out of range: ~S" (list ret) (list ret)))
- ret)))
- (define (custom-binary-port-write write)
- (unless (procedure? write)
- (type-error "custom-binary-port-write" "procedure" write))
- (lambda (port bv start count)
- (let ((ret (write bv start count)))
- (unless (and (exact-integer? ret) (<= 0 ret count))
- (scm-error 'out-of-range "custom-binary-port-write"
- "Value out of range: ~S" (list ret) (list ret)))
- ret)))
- (define (custom-binary-port-seek get-position set-position!)
- (when get-position
- (unless (procedure? get-position)
- (type-error "custom-binary-port-seek" "procedure" get-position)))
- (when set-position!
- (unless (procedure? set-position!)
- (type-error "custom-binary-port-seek" "procedure" set-position!)))
- (define (seek port offset whence)
- (cond
- ((eqv? whence SEEK_CUR)
- (unless get-position
- (type-error "custom-binary-port-seek"
- "R6RS custom binary port with `port-position` support"
- port))
- (if (zero? offset)
- (get-position)
- (seek port (+ (get-position) offset) SEEK_SET)))
- ((eqv? whence SEEK_SET)
- (unless set-position!
- (type-error "custom-binary-port-seek"
- "Seekable R6RS custom binary port"
- port))
- (set-position! offset)
- ;; Assume setting the position succeeds.
- offset)
- ((eqv? whence SEEK_END)
- (error "R6RS custom binary ports do not support `SEEK_END'"))))
- seek)
- (define (custom-binary-port-close close)
- (match close
- (#f (lambda (port) #t))
- ((? procedure?) (lambda (port) (close)))
- (_ (type-error "custom-binary-port-close" "procedure" close))))
- (define (custom-binary-port-random-access? set-position!)
- (if set-position!
- (lambda (port) #t)
- (lambda (port) #f)))
- (define (make-custom-binary-input-port id read get-position set-position! close)
- (unless (string? id)
- (type-error "make-custom-binary-input-port" "string" id))
- (make-custom-port #:id id
- #:read (custom-binary-port-read read)
- #:seek (custom-binary-port-seek get-position set-position!)
- #:close (custom-binary-port-close close)
- #:random-access?
- (custom-binary-port-random-access? set-position!)
- ;; FIXME: Instead default to current encoding, if
- ;; someone reads text from this port.
- #:encoding 'ISO-8859-1 #:conversion-strategy 'error))
- (define (make-custom-binary-output-port id write get-position set-position!
- close)
- (unless (string? id)
- (type-error "make-custom-binary-output-port" "string" id))
- (make-custom-port #:id id
- #:write (custom-binary-port-write write)
- #:seek (custom-binary-port-seek get-position set-position!)
- #:close (custom-binary-port-close close)
- #:random-access?
- (custom-binary-port-random-access? set-position!)
- ;; FIXME: Instead default to current encoding, if
- ;; someone reads text from this port.
- #:encoding 'ISO-8859-1 #:conversion-strategy 'error))
- (define (make-custom-binary-input/output-port id read write get-position
- set-position! close)
- (unless (string? id)
- (type-error "make-custom-binary-input/output-port" "string" id))
- (make-custom-port #:id id
- #:read (custom-binary-port-read read)
- #:write (custom-binary-port-write write)
- #:seek (custom-binary-port-seek get-position set-position!)
- #:close (custom-binary-port-close close)
- #:random-access?
- (custom-binary-port-random-access? set-position!)
- ;; FIXME: Instead default to current encoding, if
- ;; someone reads text from this port.
- #:encoding 'ISO-8859-1 #:conversion-strategy 'error))
|