Length-limited line reading

This commit is contained in:
Tony Garnock-Jones 2011-08-10 11:26:11 -04:00
parent 0b60d73f64
commit 3ffa667e89
2 changed files with 49 additions and 0 deletions

26
safe-io.rkt Normal file
View File

@ -0,0 +1,26 @@
#lang racket/base
(provide read-line-limited)
;; Uses Internet (CRLF) convention.
(define (read-line-limited port limit)
(let collect-chars ((acc '())
(remaining limit))
(let ((ch (read-char port)))
(cond
((eof-object? ch) (if (null? acc)
ch
(list->string (reverse acc))))
((eqv? ch #\return) (let ((ch (read-char port)))
(if (eqv? ch #\linefeed)
(list->string (reverse acc))
(error 'read-line-limited
"Invalid character ~v after #\\return"
ch))))
((eqv? ch #\newline)
;; Is this a good idea?
(error 'read-line-limited "Bare #\\linefeed encountered"))
((positive? remaining) (collect-chars (cons ch acc) (- remaining 1)))
(else (error 'read-line-limited
"Line too long (more than ~v bytes before CRLF)"
limit))))))

23
test-safe-io.rkt Normal file
View File

@ -0,0 +1,23 @@
#lang racket/base
(require "safe-io.rkt")
(require rackunit)
(define (s str)
(open-input-string str))
(check-equal? (read-line-limited (s "") 5) eof)
(check-equal? (read-line-limited (s "abc") 5) "abc")
(check-equal? (read-line-limited (s "abc\r\ndef") 5) "abc")
(check-equal? (read-line-limited (s "abcxy\r\ndef") 5) "abcxy")
(check-exn #rx"read-line-limited: Invalid character #<eof> after #\\\\return"
(lambda () (read-line-limited (s "abc\r") 5)))
(check-exn #rx"read-line-limited: Invalid character #\\\\d after #\\\\return"
(lambda () (read-line-limited (s "abc\rdef") 5)))
(check-exn #rx"Bare #\\\\linefeed encountered"
(lambda () (read-line-limited (s "abc\ndef") 5)))
(check-exn #rx"Line too long \\(more than 5 bytes before CRLF\\)"
(lambda () (read-line-limited (s "abcxyz\r\ndef") 5)))