From ce2d6030c73e0a04a2a5661a035c0e0d86d9c999 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 24 Jan 2011 14:45:29 -0700 Subject: [PATCH] add `filter-read-input-port' to `racket/port' --- collects/mzlib/port.rkt | 30 ++++++++++++++++ collects/scribblings/reference/port-lib.scrbl | 35 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/collects/mzlib/port.rkt b/collects/mzlib/port.rkt index a703db51ba..8ddff2bdb8 100644 --- a/collects/mzlib/port.rkt +++ b/collects/mzlib/port.rkt @@ -478,6 +478,35 @@ count-lines!-proc pos))) +(define filter-read-input-port + (lambda (p wrap-read wrap-peek [close? #t]) + (make-input-port + (object-name p) + (lambda (s) + (let ([v (read-bytes-avail!* s p)]) + (wrap-read + s + (if (eq? v 0) (wrap-evt p (lambda (x) 0)) v)))) + (lambda (s skip evt) + (let ([v (peek-bytes-avail!* s skip evt p)]) + (wrap-peek + s skip evt + (if (eq? v 0) + (choice-evt + (wrap-evt p (lambda (x) 0)) + (if evt (wrap-evt evt (lambda (x) #f)) never-evt)) + v)))) + (lambda () + (when close? (close-input-port p))) + (and (port-provides-progress-evts? p) + (lambda () (port-progress-evt p))) + (and (port-provides-progress-evts? p) + (lambda (n evt target-evt) (port-commit-peeked n evt target-evt p))) + (lambda () (port-next-location p)) + (lambda () (port-count-lines! p)) + (let-values ([(line col pos) (port-next-location p)]) + (or pos (file-position p)))))) + ;; Not kill-safe. (define make-pipe-with-specials ;; This implementation of pipes is almost CML-style, with a manager thread @@ -1732,6 +1761,7 @@ peeking-input-port relocate-input-port transplant-input-port + filter-read-input-port special-filter-input-port relocate-output-port transplant-output-port diff --git a/collects/scribblings/reference/port-lib.scrbl b/collects/scribblings/reference/port-lib.scrbl index 7b5f75b8b1..7582c76faa 100644 --- a/collects/scribblings/reference/port-lib.scrbl +++ b/collects/scribblings/reference/port-lib.scrbl @@ -506,6 +506,41 @@ is enabled for the resulting port. The default is @scheme[void].} Like @scheme[transplant-input-port], but for output ports.} +@defproc[(filter-read-input-port [in input-port?] + [read-wrap (bytes? (or/c exact-nonnegative-integer? + eof-object? + procedure? + evt?) + . -> . + (or/c exact-nonnegative-integer? + eof-object? + procedure? + evt?))] + [peek-wrap (bytes? exact-nonnegative-integer? (or/c evt? #f) + (or/c exact-nonnegative-integer? + eof-object? + procedure? + evt? + #f) + . -> . (or/c exact-nonnegative-integer? + eof-object? + procedure? + evt? + #f))] + [close? any/c #t]) + input-port?]{ + +Creates a port that draws from @racket[in], but each result from the +port's read and peek procedures (in the sense of @racket[make-input-port]) +is filtered by @racket[read-wrap] and +@racket[peek-wrap]. The filtering procedures each receive both the +arguments and results of the read and peek procedures on @racket[in] +for each call. + +If @racket[close?] is true, then closing the resulting port also +closes @racket[in].} + + @defproc[(special-filter-input-port [in input-port?] [proc (procedure? bytes? . -> . (or/c exact-nonnegative-integer? eof-object?