Signal exception if input isn’t vCard
… with a somewhat naïve check. Also, also count horizontal-tab characters as starters of folded lines (as per spec).
This commit is contained in:
parent
5de1c57b18
commit
1bf429571f
50
vcarded.scm
50
vcarded.scm
|
@ -21,6 +21,7 @@
|
|||
(chicken base)
|
||||
(chicken condition)
|
||||
(chicken io)
|
||||
(chicken irregex)
|
||||
(srfi 1)
|
||||
(srfi 4)
|
||||
(srfi 13)
|
||||
|
@ -223,24 +224,53 @@
|
|||
(parse-vcard-value property value-elements))))
|
||||
|
||||
|
||||
;; Reader thunk. Read/parse an entire vcard into a “vcard alist.”
|
||||
(define (read-vcard)
|
||||
(let [(element (read-vcard-element))]
|
||||
;; Reader thunk. Read/parse an entire vCard into a “vCard alist.”
|
||||
;; Ignore the IGNORED parameter.
|
||||
(define (read-vcard . ignored)
|
||||
(let* [(first-element? (optional ignored #t))
|
||||
(element (read-vcard-element first-element?))]
|
||||
(if (not (eof-object? (peek-char)))
|
||||
(append (list element) (read-vcard))
|
||||
(append (list element) (read-vcard #f))
|
||||
(list element))))
|
||||
|
||||
|
||||
;; Read a single unfolded line into a vcard “element” list.
|
||||
(define (read-vcard-element)
|
||||
(parse-vcard-line (read-folded-line)))
|
||||
;; Read a single unfolded line into a vCard “element” list.
|
||||
;; The optional FIRST-ELEMENT? argument simply makes sure the next line is a
|
||||
;; BEGIN:VCARD element (as the first element in any valid vCard file should
|
||||
;; be. It is used internally by READ-VCARD.
|
||||
(define (read-vcard-element . first-element?)
|
||||
(let* [(first-element? (optional first-element? #f))
|
||||
(line (read-folded-line (if first-element? 100 #f)))]
|
||||
(cond
|
||||
;; Ignore blank lines, they’re not doing anyone any harm!
|
||||
[(or (string-null? line)
|
||||
(irregex-search "^[[:whitespace:]]+$" line))
|
||||
(read-vcard-element first-element?)]
|
||||
;; If we’ve previously established this is a vCard stream we’re dealing
|
||||
;; with, just go ahead and parse. If we haven’t established that, make
|
||||
;; sure it’s a BEGIN:VCARD line first.
|
||||
[(or (not first-element?)
|
||||
(and first-element?
|
||||
(string-contains line "BEGIN")
|
||||
(string-contains line "VCARD")))
|
||||
(parse-vcard-line (read-folded-line))]
|
||||
;; If we’re still making sure the file is vCard, and the first non-blank
|
||||
;; line *isn’t* a BEGIN:VCARD line, then the file probably isn’t a vCard.
|
||||
[#t
|
||||
(signal
|
||||
(condition '(exn location vcarded message
|
||||
"Not a valid vCard file.")
|
||||
'(file)
|
||||
'(vcard)))])))
|
||||
|
||||
|
||||
|
||||
;; Reader-thunk. Read a “logical” folded-line, where a line beginning with a
|
||||
;; space is a continuation of the previous line — like with vcards.
|
||||
(define (read-folded-line)
|
||||
(let [(line (read-line))]
|
||||
(if (eq? (peek-char) #\space)
|
||||
(define (read-folded-line #!optional limit)
|
||||
(let [(line (read-line (current-input-port) limit))]
|
||||
(if (or (eq? (peek-char) #\space)
|
||||
(eq? (peek-char) #\tab))
|
||||
(string-concatenate
|
||||
(list line
|
||||
(string-drop (read-folded-line) 1)))
|
||||
|
|
Ŝarĝante…
Reference in New Issue