#lang racket/base (provide read-line-limited) ;; Port Natural -> (or String EofObject) ;; Uses Internet (CRLF) convention. Limit does not cover the CRLF ;; bytes. (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))))))