Add procedures like port->X but close the port (#1634)

This commit is contained in:
Marc Burns 2017-03-16 15:52:43 -04:00 committed by Sam Tobin-Hochstadt
parent 10aaff692b
commit 1309cf1649
3 changed files with 37 additions and 8 deletions

View File

@ -25,29 +25,38 @@ on @racket[in] until it produces @racket[eof].
(port->list read-number (open-input-string "12345")) (port->list read-number (open-input-string "12345"))
]} ]}
@defproc[(port->string [in input-port? (current-input-port)]) string?]{ @defproc[(port->string [in input-port? (current-input-port)]
[#:close? close? any/c #f])
string?]{
Reads all characters from @racket[in] and returns them as a string. Reads all characters from @racket[in] and returns them as a string.
The input port is closed unless @racket[close?] is @racket[#f].
@examples[#:eval port-eval @examples[#:eval port-eval
(port->string (open-input-string "hello world")) (port->string (open-input-string "hello world"))
]} ]}
@defproc[(port->bytes [in input-port? (current-input-port)]) bytes?]{ @defproc[(port->bytes [in input-port? (current-input-port)]
[#:close? close? any/c #f])
bytes?]{
Reads all bytes from @racket[in] and returns them as a @tech{byte string}. Reads all bytes from @racket[in] and returns them as a @tech{byte string}.
The input port is closed unless @racket[close?] is @racket[#f].
@examples[#:eval port-eval @examples[#:eval port-eval
(port->bytes (open-input-string "hello world")) (port->bytes (open-input-string "hello world"))
]} ]}
@defproc[(port->lines [in input-port? (current-input-port)] @defproc[(port->lines [in input-port? (current-input-port)]
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any]) [#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any]
[#:close? close? any/c #f])
(listof string?)]{ (listof string?)]{
Read all characters from @racket[in], breaking them into lines. The Read all characters from @racket[in], breaking them into lines. The
@racket[line-mode] argument is the same as the second argument to @racket[line-mode] argument is the same as the second argument to
@racket[read-line], but the default is @racket['any] instead of @racket[read-line], but the default is @racket['any] instead of
@racket['linefeed]. @racket['linefeed].
The input port is closed unless @racket[close?] is @racket[#f].
@examples[#:eval port-eval @examples[#:eval port-eval
(port->lines (port->lines
@ -55,11 +64,13 @@ Read all characters from @racket[in], breaking them into lines. The
]} ]}
@defproc[(port->bytes-lines [in input-port? (current-input-port)] @defproc[(port->bytes-lines [in input-port? (current-input-port)]
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any]) [#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any]
[#:close? close? any/c #f])
(listof bytes?)]{ (listof bytes?)]{
Like @racket[port->lines], but reading bytes and collecting them into Like @racket[port->lines], but reading bytes and collecting them into
lines like @racket[read-bytes-line]. lines like @racket[read-bytes-line].
The input port is closed unless @racket[close?] is @racket[#f].
@examples[#:eval port-eval @examples[#:eval port-eval
(port->bytes-lines (port->bytes-lines

View File

@ -22,6 +22,17 @@
(test '("hello" "" "there") port->lines (p) #:line-mode 'any-one) (test '("hello" "" "there") port->lines (p) #:line-mode 'any-one)
(test '(#"hello" #"" #"there") port->bytes-lines (p) #:line-mode 'any-one)) (test '(#"hello" #"" #"there") port->bytes-lines (p) #:line-mode 'any-one))
(let* ([p (lambda () (open-input-string "nothing\r\nwill come of nothing"))]
[closes? (lambda (f) (let ([port (p)]) (f port) (port-closed? port)))])
(test #t closes? (curryr port->string #:close? #t))
(test #f closes? port->string)
(test #t closes? (curryr port->bytes #:close? #t))
(test #f closes? port->bytes)
(test #t closes? (curryr port->lines #:close? #t))
(test #f closes? port->lines)
(test #t closes? (curryr port->bytes-lines #:close? #t))
(test #f closes? port->bytes-lines))
(let* ([x (make-string 50000 #\x)] (let* ([x (make-string 50000 #\x)]
[p (lambda () (open-input-string x))]) [p (lambda () (open-input-string x))])
(test (string-length x) 'long-string (string-length (port->string (p)))) (test (string-length x) 'long-string (string-length (port->string (p))))

View File

@ -87,16 +87,23 @@
(unless (input-port? p) (raise-argument-error who "input-port?" p)) (unless (input-port? p) (raise-argument-error who "input-port?" p))
(let ([s (open-output-string)]) (copy-port p s) s)) (let ([s (open-output-string)]) (copy-port p s) s))
(define (port->string [p (current-input-port)]) (define-syntax-rule (define-port->X (name port-arg rest-args ...) body)
(define (name [port-arg (current-input-port)] rest-args ... #:close? [close? #f])
(begin0
body
(when close?
(close-input-port port-arg)))))
(define-port->X (port->string p)
(get-output-string (port->string-port 'port->string p))) (get-output-string (port->string-port 'port->string p)))
(define (port->bytes [p (current-input-port)]) (define-port->X (port->bytes p)
(get-output-bytes (port->string-port 'port->bytes p) #t)) (get-output-bytes (port->string-port 'port->bytes p) #t))
(define (port->lines [p (current-input-port)] #:line-mode [mode 'any]) (define-port->X (port->lines p #:line-mode [mode 'any])
(port->x-lines 'port->lines p mode read-line)) (port->x-lines 'port->lines p mode read-line))
(define (port->bytes-lines [p (current-input-port)] #:line-mode [mode 'any]) (define-port->X (port->bytes-lines p #:line-mode [mode 'any])
(port->x-lines 'port->bytes-lines p mode read-bytes-line)) (port->x-lines 'port->bytes-lines p mode read-bytes-line))
(define (port->list [r read] [p (current-input-port)]) (define (port->list [r read] [p (current-input-port)])