1999-09-14 09:32:05 -04:00
|
|
|
;;; Basic read and write
|
|
|
|
;;; Copyright (c) 1993 by Olin Shivers.
|
|
|
|
|
|
|
|
;;; Note: read ops should check to see if their string args are mutable.
|
|
|
|
|
|
|
|
(define (bogus-substring-spec? s start end)
|
|
|
|
(or (< start 0)
|
|
|
|
(< (string-length s) end)
|
|
|
|
(< end start)))
|
|
|
|
|
|
|
|
|
|
|
|
;;; Best-effort/forward-progress reading
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(define (read-string!/partial s . args)
|
|
|
|
(let-optionals args ((fd/port (current-input-port))
|
|
|
|
(start 0)
|
|
|
|
(end (string-length s)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(if (bogus-substring-spec? s start end)
|
|
|
|
(error "Bad substring indices" s start end))
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
(cond ((integer? fd/port)
|
2001-09-07 12:05:31 -04:00
|
|
|
(let ((port (fdes->inport fd/port)))
|
2003-01-07 12:32:57 -05:00
|
|
|
(set-port-buffering port bufpol/none)
|
|
|
|
(read-string!/partial s port start end)))
|
2001-09-07 12:05:31 -04:00
|
|
|
|
2003-01-07 12:32:57 -05:00
|
|
|
((open-input-port? fd/port)
|
|
|
|
(if (= start end)
|
|
|
|
0
|
|
|
|
(let* ((buffer (if (= start 0)
|
|
|
|
s
|
|
|
|
(make-string (- end start))))
|
|
|
|
(needed (if (> (byte-vector-length (port-buffer fd/port)) 1)
|
|
|
|
'any
|
|
|
|
'immediate)) ;bufpol/none may return with 0
|
|
|
|
(nread (read-block buffer 0 needed fd/port)))
|
|
|
|
(if (eof-object? nread)
|
|
|
|
#f
|
|
|
|
(begin
|
|
|
|
(if (not (eq? s buffer))
|
|
|
|
(copy-bytes! buffer 0 s start nread))
|
|
|
|
nread)))))
|
|
|
|
|
|
|
|
(else
|
|
|
|
(apply error "Not a fd/port in read-string!/partial" s args)))))
|
2000-05-18 10:03:44 -04:00
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
(define (read-string/partial len . maybe-fd/port)
|
2003-01-07 12:32:57 -05:00
|
|
|
(let* ((fd/port (:optional maybe-fd/port (current-input-port))))
|
|
|
|
(cond ((integer? fd/port)
|
|
|
|
(let ((port (fdes->inport fd/port)))
|
|
|
|
(set-port-buffering port bufpol/none)
|
|
|
|
(read-string/partial len port)))
|
|
|
|
|
|
|
|
((open-input-port? fd/port)
|
|
|
|
(if (= len 0)
|
|
|
|
0
|
|
|
|
(let* ((buffer (make-string len))
|
|
|
|
(needed (if (> (byte-vector-length (port-buffer fd/port)) 1)
|
|
|
|
'any
|
|
|
|
'immediate));; bufpol/none may return with 0
|
|
|
|
(nread (read-block buffer 0 needed fd/port)))
|
|
|
|
(cond ((eof-object? nread) #f)
|
|
|
|
((= nread len) buffer)
|
|
|
|
(else (substring buffer 0 nread))))))
|
|
|
|
(else
|
|
|
|
(error "Not a fd/port in read-string/partial" len fd/port)))))
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
;;; Persistent reading
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2000-05-18 10:03:44 -04:00
|
|
|
;;;
|
|
|
|
;;; Operation on ports is easy, since we can use read-block
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
(define (read-string! s . args)
|
|
|
|
(let-optionals args ((fd/port (current-input-port))
|
|
|
|
(start 0)
|
|
|
|
(end (string-length s)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(if (bogus-substring-spec? s start end)
|
|
|
|
(error "Bad substring indices" s start end))
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
(cond ((integer? fd/port)
|
2001-09-07 12:05:31 -04:00
|
|
|
(let ((port (fdes->inport fd/port)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(set-port-buffering port bufpol/block (- end start))
|
2001-09-07 12:05:31 -04:00
|
|
|
(read-string! port start end)))
|
1999-09-14 09:32:05 -04:00
|
|
|
|
2000-05-18 10:03:44 -04:00
|
|
|
(else ; no differnce between fd/port and s48 ports
|
|
|
|
(let ((nbytes/eof (read-block s start (- end start) fd/port)))
|
|
|
|
(if (eof-object? nbytes/eof)
|
|
|
|
#f
|
|
|
|
nbytes/eof))))))
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
(define (read-string len . maybe-fd/port)
|
|
|
|
(let* ((s (make-string len))
|
|
|
|
(fd/port (:optional maybe-fd/port (current-input-port)))
|
|
|
|
(nread (read-string! s fd/port 0 len)))
|
|
|
|
(cond ((not nread) #f) ; EOF
|
|
|
|
((= nread len) s)
|
|
|
|
(else (substring s 0 nread)))))
|
|
|
|
|
|
|
|
|
|
|
|
;;; Best-effort/forward-progress writing
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Non-blocking output to a buffered port is not defined.
|
|
|
|
|
|
|
|
(define (write-string/partial s . args)
|
|
|
|
(let-optionals args ((fd/port (current-output-port))
|
|
|
|
(start 0)
|
|
|
|
(end (string-length s)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(if (bogus-substring-spec? s start end)
|
|
|
|
(error "Bad substring indices" s start end))
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
(cond ((integer? fd/port)
|
2001-09-07 12:05:31 -04:00
|
|
|
(let ((port (fdes->outport fd/port)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(set-port-buffering port bufpol/block (- end start))
|
2001-09-07 12:05:31 -04:00
|
|
|
(write-string/partial s port start end)))
|
2000-05-18 10:03:44 -04:00
|
|
|
(else
|
|
|
|
;; the only way to implement this, would be to use
|
|
|
|
;; channel-maybe-write. But this is an VM-instruction which is not
|
|
|
|
;; exported. Since we now have threads this shouldn;t matter.
|
2001-09-07 12:05:31 -04:00
|
|
|
(error "write-string/parital is currently dereleased.
|
|
|
|
See the RELEASE file for details")))))
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
;;; Persistent writing
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(define (write-string s . args)
|
|
|
|
(let-optionals args ((fd/port (current-output-port))
|
|
|
|
(start 0)
|
|
|
|
(end (string-length s)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(if (bogus-substring-spec? s start end)
|
|
|
|
(error "Bad substring indices" s start end))
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
(cond ((integer? fd/port)
|
2001-09-07 12:05:31 -04:00
|
|
|
(let ((port (fdes->outport fd/port)))
|
2003-01-07 09:58:13 -05:00
|
|
|
(set-port-buffering port bufpol/block (- end start))
|
2001-09-07 12:05:31 -04:00
|
|
|
(write-string s port start end)))
|
2000-05-18 10:03:44 -04:00
|
|
|
(else (write-block s start (- end start) fd/port)))))
|