.
original commit: ea994f7880653d3de4b4995ec343df49577eb05e
This commit is contained in:
parent
eb8680e0e5
commit
ae1c288d62
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
(module port mzscheme
|
(module port mzscheme
|
||||||
(require (lib "etc.ss"))
|
(require (lib "etc.ss")
|
||||||
|
(lib "contract.ss"))
|
||||||
|
|
||||||
(provide open-output-nowhere
|
(provide open-output-nowhere
|
||||||
make-input-port/read-to-peek
|
make-input-port/read-to-peek
|
||||||
|
@ -10,6 +11,18 @@
|
||||||
convert-stream
|
convert-stream
|
||||||
make-limited-input-port)
|
make-limited-input-port)
|
||||||
|
|
||||||
|
(define (exact-non-negative-integer? i)
|
||||||
|
(and (number? i) (exact? i) (integer? i) (i . >= . 0)))
|
||||||
|
|
||||||
|
(provide/contract (read-bytes-avail!-evt (bytes? input-port? . -> . evt?))
|
||||||
|
(read-bytes!-evt (bytes? input-port? . -> . evt?))
|
||||||
|
(read-bytes-evt (exact-non-negative-integer? input-port? . -> . evt?))
|
||||||
|
(read-string!-evt (string? input-port? . -> . evt?))
|
||||||
|
(read-string-evt (exact-non-negative-integer? input-port? . -> . evt?))
|
||||||
|
(regexp-match-evt ((union regexp? byte-regexp?) input-port? . -> . evt?)))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
(define open-output-nowhere
|
(define open-output-nowhere
|
||||||
(opt-lambda ([name 'nowhere])
|
(opt-lambda ([name 'nowhere])
|
||||||
(make-output-port
|
(make-output-port
|
||||||
|
@ -17,13 +30,15 @@
|
||||||
always-evt
|
always-evt
|
||||||
(lambda (s start end non-block? breakable?) (- end start))
|
(lambda (s start end non-block? breakable?) (- end start))
|
||||||
void
|
void
|
||||||
(lambda (special non-block?) #t)
|
(lambda (special non-block? breakable?) #t)
|
||||||
(lambda (s start end) (convert-evt
|
(lambda (s start end) (convert-evt
|
||||||
always-evt
|
always-evt
|
||||||
(lambda (x)
|
(lambda (x)
|
||||||
(- end start))))
|
(- end start))))
|
||||||
(lambda (special) (convert-evt always-evt (lambda (x) #t))))))
|
(lambda (special) (convert-evt always-evt (lambda (x) #t))))))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
(define (copy-port src dest . dests)
|
(define (copy-port src dest . dests)
|
||||||
(unless (input-port? src)
|
(unless (input-port? src)
|
||||||
(raise-type-error 'copy-port "input-port" src))
|
(raise-type-error 'copy-port "input-port" src))
|
||||||
|
@ -212,7 +227,7 @@
|
||||||
;; Enough has been peeked...
|
;; Enough has been peeked...
|
||||||
(unless (zero? p-commit)
|
(unless (zero? p-commit)
|
||||||
(peek-byte peeked-r (sub1 amt))
|
(peek-byte peeked-r (sub1 amt))
|
||||||
(port-commit-peeked amt peeked-r))
|
(port-commit-peeked amt #f peeked-r))
|
||||||
(set! special-peeked l)
|
(set! special-peeked l)
|
||||||
(when (null? special-peeked)
|
(when (null? special-peeked)
|
||||||
(set! special-peeked-tail #f))
|
(set! special-peeked-tail #f))
|
||||||
|
@ -242,8 +257,12 @@
|
||||||
read-it
|
read-it
|
||||||
;; Peek
|
;; Peek
|
||||||
(if fast-peek
|
(if fast-peek
|
||||||
(lambda (s skip)
|
(let ([fast-peek-k (lambda (s skip)
|
||||||
(fast-peek s skip peek-it))
|
(peek-it s skip #f))])
|
||||||
|
(lambda (s skip unless-evt)
|
||||||
|
(if unless-evt
|
||||||
|
(peek-it s skip unless-evt)
|
||||||
|
(fast-peek s skip fast-peek-k))))
|
||||||
peek-it)
|
peek-it)
|
||||||
close
|
close
|
||||||
(lambda ()
|
(lambda ()
|
||||||
|
@ -366,4 +385,150 @@
|
||||||
n)))))
|
n)))))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(when close-orig?
|
(when close-orig?
|
||||||
(close-input-port port))))))))
|
(close-input-port port)))))))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
(define (read-at-least-bytes!-evt orig-bstr input-port need-more? shrink combo)
|
||||||
|
(nack-guard-evt
|
||||||
|
(lambda (nack)
|
||||||
|
(define ch (make-channel))
|
||||||
|
(thread (lambda ()
|
||||||
|
(let try-again ([pos 0][bstr orig-bstr])
|
||||||
|
(let* ([progress-evt (port-progress-evt input-port)]
|
||||||
|
[v (peek-bytes-avail! bstr pos progress-evt input-port pos)])
|
||||||
|
(cond
|
||||||
|
[(sync/timeout 0 nack) (void)]
|
||||||
|
[(sync/timeout 0 progress-evt) (try-again pos bstr)]
|
||||||
|
[(and (number? v) (need-more? bstr (+ pos v)))
|
||||||
|
=> (lambda (bstr)
|
||||||
|
(try-again (+ v pos) bstr))]
|
||||||
|
[else
|
||||||
|
(let ([v2 (cond
|
||||||
|
[(number? v) (shrink bstr (+ v pos))]
|
||||||
|
[(positive? pos) pos]
|
||||||
|
[else v])])
|
||||||
|
(unless (port-commit-peeked
|
||||||
|
(if (number? v2) v2 1)
|
||||||
|
progress-evt
|
||||||
|
(channel-put-evt
|
||||||
|
ch
|
||||||
|
(combo bstr v2))
|
||||||
|
input-port)
|
||||||
|
(try-again 0 orig-bstr)))])))))
|
||||||
|
ch)))
|
||||||
|
|
||||||
|
(define (read-bytes-avail!-evt bstr input-port)
|
||||||
|
(read-at-least-bytes!-evt bstr input-port
|
||||||
|
(lambda (bstr v) (if (zero? v)
|
||||||
|
bstr
|
||||||
|
#f))
|
||||||
|
(lambda (bstr v) v)
|
||||||
|
(lambda (bstr v) v)))
|
||||||
|
|
||||||
|
(define (read-bytes!-evt bstr input-port)
|
||||||
|
(read-at-least-bytes!-evt bstr input-port
|
||||||
|
(lambda (bstr v)
|
||||||
|
(if (v . < . (bytes-length bstr))
|
||||||
|
bstr
|
||||||
|
#f))
|
||||||
|
(lambda (bstr v) v)
|
||||||
|
(lambda (bstr v) v)))
|
||||||
|
|
||||||
|
(define (read-bytes-evt len input-port)
|
||||||
|
(let ([bstr (make-bytes len)])
|
||||||
|
(convert-evt
|
||||||
|
(read-bytes!-evt bstr input-port)
|
||||||
|
(lambda (v)
|
||||||
|
(if (number? v)
|
||||||
|
(if (= v len)
|
||||||
|
bstr
|
||||||
|
(subbytes bstr 0 v))
|
||||||
|
v)))))
|
||||||
|
|
||||||
|
(define (read-string-evt goal input-port)
|
||||||
|
(let ([bstr (make-bytes goal)]
|
||||||
|
[c (bytes-open-converter "UTF-8-permissive" "UTF-8")])
|
||||||
|
(convert-evt
|
||||||
|
(read-at-least-bytes!-evt bstr input-port
|
||||||
|
(lambda (bstr v)
|
||||||
|
(if (= v (bytes-length bstr))
|
||||||
|
;; We can't easily use bytes-utf-8-length here,
|
||||||
|
;; because we may need more bytes to figure out
|
||||||
|
;; the true role of the last byte. The
|
||||||
|
;; `bytes-convert' function lets us deal with
|
||||||
|
;; the last byte properly.
|
||||||
|
(let-values ([(bstr2 used status)
|
||||||
|
(bytes-convert c bstr 0 v)])
|
||||||
|
(let ([got (bytes-utf-8-length bstr2)])
|
||||||
|
(if (= got goal)
|
||||||
|
;; Done:
|
||||||
|
#f
|
||||||
|
;; Need more bytes:
|
||||||
|
(let ([bstr2 (make-bytes (+ v (- goal got)))])
|
||||||
|
(bytes-copy! bstr2 0 bstr)
|
||||||
|
bstr2))))
|
||||||
|
;; Need more bytes in bstr:
|
||||||
|
bstr))
|
||||||
|
(lambda (bstr v)
|
||||||
|
;; We may need one less than v,
|
||||||
|
;; because we may have had to peek
|
||||||
|
;; an extra byte to discover an
|
||||||
|
;; error in the stream.
|
||||||
|
(if ((bytes-utf-8-length bstr #\? 0 v) . > . goal)
|
||||||
|
(sub1 v)
|
||||||
|
v))
|
||||||
|
cons)
|
||||||
|
(lambda (bstr+v)
|
||||||
|
(let ([bstr (car bstr+v)]
|
||||||
|
[v (cdr bstr+v)])
|
||||||
|
(if (number? v)
|
||||||
|
(bytes->string/utf-8 bstr #\? 0 v)
|
||||||
|
v))))))
|
||||||
|
|
||||||
|
(define (read-string!-evt str input-port)
|
||||||
|
(convert-evt
|
||||||
|
(read-string-evt (string-length str) input-port)
|
||||||
|
(lambda (s)
|
||||||
|
(if (string? s)
|
||||||
|
(begin
|
||||||
|
(string-copy! str 0 s)
|
||||||
|
(string-length s))
|
||||||
|
s))))
|
||||||
|
|
||||||
|
(define (regexp-match-evt pattern input-port)
|
||||||
|
(nack-guard-evt
|
||||||
|
(lambda (nack)
|
||||||
|
(define ch (make-channel))
|
||||||
|
(thread (lambda ()
|
||||||
|
(let try-again ()
|
||||||
|
(let* ([progress-evt (port-progress-evt input-port)]
|
||||||
|
[m (regexp-match-peek-positions pattern input-port 0 #f progress-evt)])
|
||||||
|
(cond
|
||||||
|
[(sync/timeout 0 nack) (void)]
|
||||||
|
[(sync/timeout 0 progress-evt) (try-again)]
|
||||||
|
[(not m)
|
||||||
|
(sync nack
|
||||||
|
(finish-evt progress-evt
|
||||||
|
(lambda (x) (try-again))))]
|
||||||
|
[else
|
||||||
|
(let ([m2 (map (lambda (p)
|
||||||
|
(and p
|
||||||
|
(let ([bstr (make-bytes (- (cdr p) (car p)))])
|
||||||
|
(unless (= (car p) (cdr p))
|
||||||
|
(let loop ([offset 0])
|
||||||
|
(let ([v (peek-bytes-avail! bstr (car p) progress-evt input-port offset)])
|
||||||
|
(unless (zero? v)
|
||||||
|
(when ((+ offset v) . < . (bytes-length bstr))
|
||||||
|
(loop (+ offset v)))))))
|
||||||
|
bstr)))
|
||||||
|
m)])
|
||||||
|
(unless (port-commit-peeked (cdar m)
|
||||||
|
progress-evt
|
||||||
|
(channel-put-evt ch m2)
|
||||||
|
input-port)
|
||||||
|
(try-again)))])))))
|
||||||
|
ch)))
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user