generalize `xml/plist' to read/write any plist value
Merge to 5.3
This commit is contained in:
parent
1914345af4
commit
3ecf06a8ba
|
@ -784,6 +784,22 @@ END
|
|||
(write-plist plist out)
|
||||
(close-output-port out)
|
||||
(test-equal? (format "~S" plist) (read-plist in) plist))]
|
||||
(test-plist-round-trip example))))))
|
||||
(test-plist-round-trip example)
|
||||
|
||||
(let ()
|
||||
(define array '(array "apple"
|
||||
(true)
|
||||
(false)
|
||||
(integer 5)
|
||||
(real 5.0)))
|
||||
(test-not-false
|
||||
"plist-value?"
|
||||
(plist-value? array))
|
||||
(test-plist-round-trip array)
|
||||
(for ([v (in-list (cdr array))])
|
||||
(test-not-false
|
||||
"plist-value?"
|
||||
(plist-value? v))
|
||||
(test-plist-round-trip v))))))))
|
||||
|
||||
(run-tests xml-tests)
|
||||
|
|
|
@ -22,20 +22,22 @@
|
|||
(= 3 (length v))
|
||||
(eq? (car v) 'assoc-pair)
|
||||
(string? (cadr v))
|
||||
(let pl-value? ([v (caddr v)])
|
||||
(or (string? v)
|
||||
(and (pair? v)
|
||||
(case (car v)
|
||||
[(true) (null? (cdr v))]
|
||||
[(false) (null? (cdr v))]
|
||||
[(integer) (and (= (length v) 2)
|
||||
(exact-integer? (cadr v)))]
|
||||
[(real) (and (= (length v) 2)
|
||||
(real? (cadr v)))]
|
||||
[(array) (andmap pl-value? (cdr v))]
|
||||
[else (plist-dict? v)]))))))
|
||||
(plist-value? (caddr v))))
|
||||
(cdr v))))
|
||||
|
||||
(define (plist-value? v)
|
||||
(or (string? v)
|
||||
(and (pair? v)
|
||||
(case (car v)
|
||||
[(true) (null? (cdr v))]
|
||||
[(false) (null? (cdr v))]
|
||||
[(integer) (and (= (length v) 2)
|
||||
(exact-integer? (cadr v)))]
|
||||
[(real) (and (= (length v) 2)
|
||||
(real? (cadr v)))]
|
||||
[(array) (andmap plist-value? (cdr v))]
|
||||
[else (plist-dict? v)]))))
|
||||
|
||||
|
||||
; raise-plist-exn : string mark-set xexpr symbol -> ???
|
||||
(define (raise-plist-exn tag mark-set xexpr type)
|
||||
|
@ -122,18 +124,17 @@
|
|||
|
||||
; write-plist : xexpr port -> (void)
|
||||
(define (write-plist xexpr port)
|
||||
(let ([plist-xexpr `(plist ,(expand-dict xexpr))])
|
||||
(write-xml
|
||||
(make-document (make-prolog (list (make-p-i #f #f 'xml "version=\"1.0\" encoding=\"UTF-8\""))
|
||||
(make-document-type 'plist
|
||||
(make-external-dtd/system
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd")
|
||||
#f)
|
||||
empty)
|
||||
(xexpr->xml `(plist ((version "0.9"))
|
||||
,(expand-dict xexpr)))
|
||||
null)
|
||||
port)))
|
||||
(write-xml
|
||||
(make-document (make-prolog (list (make-p-i #f #f 'xml "version=\"1.0\" encoding=\"UTF-8\""))
|
||||
(make-document-type 'plist
|
||||
(make-external-dtd/system
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd")
|
||||
#f)
|
||||
empty)
|
||||
(xexpr->xml `(plist ((version "0.9"))
|
||||
,(expand-value xexpr)))
|
||||
null)
|
||||
port))
|
||||
|
||||
|
||||
; collapse-dict : xexpr -> dict
|
||||
|
@ -166,7 +167,7 @@
|
|||
(define tags-without-whitespace
|
||||
'(plist dict array))
|
||||
|
||||
; read-plist : port -> dict
|
||||
; read-plist : port -> value
|
||||
(define (read-plist port)
|
||||
(let* ([xml-doc (read-xml port)]
|
||||
[content (parameterize ([xexpr-drop-empty-attributes #t])
|
||||
|
@ -175,9 +176,12 @@
|
|||
(document-element xml-doc))))])
|
||||
(unless (eq? (car content) 'plist)
|
||||
(error 'read-plist "xml expression is not a plist: ~a" content))
|
||||
(collapse-dict (caddr content))))
|
||||
(collapse-value (caddr content))))
|
||||
|
||||
(provide
|
||||
(contract-out
|
||||
[plist-dict? (any/c . -> . boolean?)]
|
||||
[plist-value? (any/c . -> . boolean?)]
|
||||
[read-plist (input-port? . -> . plist-value?)]
|
||||
[write-plist (plist-value? output-port? . -> . void?)]))
|
||||
|
||||
(provide/contract
|
||||
[plist-dict? (any/c . -> . boolean?)]
|
||||
[read-plist (input-port? . -> . plist-dict?)]
|
||||
[write-plist (plist-dict? output-port? . -> . void?)])
|
||||
|
|
|
@ -387,34 +387,40 @@ used to store dictionaries of string--value associations. This format
|
|||
is used by Mac OS X (both the operating system and its applications)
|
||||
to store all kinds of data.
|
||||
|
||||
A @deftech{plist dictionary} is a value that could be created by an
|
||||
expression matching the following @racket[_dict-expr] grammar:
|
||||
A @deftech{plist value} is a value that could be created by an
|
||||
expression matching the following @racket[_pl-expr] grammar, where a
|
||||
value created by a @racket[_dict-expr] is a @deftech{plist dictionary}:
|
||||
|
||||
@racketgrammar*[
|
||||
#:literals (list quote)
|
||||
[dict-expr (list 'dict assoc-pair ...)]
|
||||
[assoc-pair (list 'assoc-pair string pl-value)]
|
||||
[pl-value string
|
||||
[pl-expr string
|
||||
(list 'true)
|
||||
(list 'false)
|
||||
(list 'integer integer)
|
||||
(list 'real real)
|
||||
dict-expr
|
||||
(list 'array pl-value ...)]
|
||||
(list 'array pl-expr ...)]
|
||||
[dict-expr (list 'dict assoc-pair ...)]
|
||||
[assoc-pair (list 'assoc-pair string pl-expr)]
|
||||
]
|
||||
|
||||
@defproc[(plist-value? [any/c v]) boolean?]{
|
||||
|
||||
Returns @racket[#t] if @racket[v] is a @tech{plist value},
|
||||
@racket[#f] otherwise.}
|
||||
|
||||
@defproc[(plist-dict? [any/c v]) boolean?]{
|
||||
|
||||
Returns @racket[#t] if @racket[v] is a @tech{plist dictionary},
|
||||
@racket[#f] otherwise.}
|
||||
|
||||
@defproc[(read-plist [in input-port?]) plist-dict?]{
|
||||
@defproc[(read-plist [in input-port?]) plist-value?]{
|
||||
|
||||
Reads a plist from a port, and produces a @tech{plist dictionary}.}
|
||||
Reads a plist from a port, and produces a @tech{plist value}.}
|
||||
|
||||
@defproc[(write-plist [dict plist-dict?] [out output-port?]) void?]{
|
||||
@defproc[(write-plist [dict plist-value?] [out output-port?]) void?]{
|
||||
|
||||
Write a @tech{plist dictionary} to the given port.}
|
||||
Write a @tech{plist value} to the given port.}
|
||||
|
||||
@examples[
|
||||
#:eval plist-eval
|
||||
|
|
Loading…
Reference in New Issue
Block a user