line.ss
#lang scheme/base
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; NET.plt
;;
;; abstraction of common network behaviors and services
;;
;; Bonzai Lab, LLC.  All rights reserved.
;;
;; Licensed under LGPL.
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; line.ss
;; function for parsing folded line as defined by RFC822.
;; yc 8/18/2009 - first version
;; yc 10/12/2009 - adding convert & fws arguments to read-folded-line so it can be extended.
(require "depend.ss"
         )

;; read-folded-line
;; read folded line according to RFC822.
(define (read-folded-line in (convert identity)) 
  (define (folding? c)
    (or (equal? c #\space)
        (equal? c #\tab)))
  (define (return lines) 
    (apply string-append "" (reverse lines)))
  (define (convert-folding lines)
    (let ((c (peek-char in)))
      (cond ((folding? c) 
             (read-char in)
             (convert-folding lines))
            (else
             (helper lines)))))
  (define (helper lines)
    (let ((l (read-line in (line-term))))
      (cond ((eof-object? l)
             (return lines))
            ((string=? l "")
             (return (cons l lines)))
            (else
             (let ((c (peek-char in)))
               (if (folding? c)  
                   ;; (convert-folding (cons (convert l) lines))
                   (helper (cons (convert l) lines))
                   ;; otherwise we are done...
                   (return (cons (convert l) lines))))))))
  (helper '()))

(define (folded-line->string s (convert identity))
  (read-folded-line (open-input-string s) convert))

(provide/contract
 (read-folded-line (->* (input-port?)
                        ((-> any/c any)) 
                        string?))
 (folded-line->string (->* (string?)
                           ((-> any/c any)) 
                           string?))
 )