mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-05-18 21:29:19 +02:00
Adding csv-writer support.
This commit is contained in:
parent
8e67defd71
commit
f28168a2a6
3 changed files with 97 additions and 2 deletions
|
@ -9,6 +9,11 @@
|
|||
(define string->csv
|
||||
(opt-lambda (str (reader (csv-read->list)))
|
||||
(reader (open-input-string str))))
|
||||
(define csv->string
|
||||
(opt-lambda (row (writer (csv-writer)))
|
||||
(let ((out (open-output-string)))
|
||||
(writer row out)
|
||||
(get-output-string out))))
|
||||
(define (run-tests)
|
||||
(test-begin "(chibi csv)")
|
||||
(test-assert (eof-object? (string->csv "")))
|
||||
|
@ -73,4 +78,18 @@ Paris,48°51′24″N,2°21′03″E"))
|
|||
(longitude "2°21′03″E")))
|
||||
((csv->sxml 'city '(name latitude longitude))
|
||||
(open-input-string city-csv))))
|
||||
(test "1997,Ford,E350\n"
|
||||
(csv->string '("1997" "Ford" "E350")))
|
||||
(test "1997,Ford,E350,\"Super, luxurious truck\"\n"
|
||||
(csv->string '("1997" "Ford" "E350" "Super, luxurious truck")))
|
||||
(test "1997,Ford,E350,\"Super, \"\"luxurious\"\" truck\"\n"
|
||||
(csv->string '("1997" "Ford" "E350" "Super, \"luxurious\" truck")))
|
||||
(test "1997,Ford,E350,\"Go get one now\nthey are going fast\"\n"
|
||||
(csv->string
|
||||
'("1997" "Ford" "E350" "Go get one now\nthey are going fast")))
|
||||
(test "1997,Ford,E350\n"
|
||||
(csv->string '(1997 "Ford" E350)))
|
||||
(test "1997,\"Ford\",\"E350\"\n"
|
||||
(csv->string '(1997 "Ford" E350)
|
||||
(csv-writer (csv-grammar '((quote-non-numeric? . #t))))))
|
||||
(test-end))))
|
||||
|
|
|
@ -84,6 +84,8 @@
|
|||
(define default-tsv-grammar
|
||||
(csv-grammar '((separator-chars #\tab) (quote-char . #f))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;> \section{CSV Parsers}
|
||||
|
||||
;;> Parsers are low-level utilities to perform operations on records a
|
||||
|
@ -375,3 +377,76 @@
|
|||
(opt-lambda ((in (current-input-port)))
|
||||
(cons '*TOP*
|
||||
(csv->list (csv-read->sxml row-name column-names parser) in)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;> \section{CSV Writers}
|
||||
|
||||
(define (write->string obj)
|
||||
(let ((out (open-output-string)))
|
||||
(write obj out)
|
||||
(get-output-string out)))
|
||||
|
||||
(define (csv-grammar-char-needs-quoting? grammar ch)
|
||||
(or (eqv? ch (csv-grammar-quote-char grammar))
|
||||
(eqv? ch (csv-grammar-escape-char grammar))
|
||||
(memv ch (csv-grammar-separator-chars grammar))
|
||||
(eqv? ch (csv-grammar-record-separator grammar))
|
||||
(memv ch '(#\newline #\return))))
|
||||
|
||||
(define (csv-write-quoted obj out grammar)
|
||||
(let ((in (open-input-string (if (string? obj) obj (write->string obj)))))
|
||||
(write-char (csv-grammar-quote-char grammar) out)
|
||||
(let lp ()
|
||||
(let ((ch (read-char in)))
|
||||
(cond
|
||||
((eof-object? ch))
|
||||
((or (eqv? ch (csv-grammar-quote-char grammar))
|
||||
(eqv? ch (csv-grammar-escape-char grammar)))
|
||||
(cond
|
||||
((and (csv-grammar-quote-doubling-escapes? grammar)
|
||||
(eqv? ch (csv-grammar-quote-char grammar)))
|
||||
(write-char ch out))
|
||||
((csv-grammar-escape-char grammar)
|
||||
=> (lambda (esc) (write-char esc out)))
|
||||
(else (error "no quote defined for" ch grammar)))
|
||||
(write-char ch out)
|
||||
(lp))
|
||||
(else
|
||||
(write-char ch out)
|
||||
(lp)))))
|
||||
(write-char (csv-grammar-quote-char grammar) out)))
|
||||
|
||||
(define csv-writer
|
||||
(opt-lambda ((grammar default-csv-grammar))
|
||||
(opt-lambda (row (out (current-output-port)))
|
||||
(let lp ((ls row) (first? #t))
|
||||
(when (pair? ls)
|
||||
(unless first?
|
||||
(write-char (car (csv-grammar-separator-chars grammar)) out))
|
||||
(if (or (and (csv-grammar-quote-non-numeric? grammar)
|
||||
(not (number? (car ls))))
|
||||
(and (string? (car ls))
|
||||
(string-any
|
||||
(lambda (ch) (csv-grammar-char-needs-quoting? grammar ch))
|
||||
(car ls)))
|
||||
(and (not (string? (car ls)))
|
||||
(not (number? (car ls)))
|
||||
(not (symbol? (car ls)))))
|
||||
(csv-write-quoted (car ls) out grammar)
|
||||
(display (car ls) out))
|
||||
(lp (cdr ls) #f)))
|
||||
(write-string
|
||||
(case (csv-grammar-record-separator grammar)
|
||||
((crlf) "\r\n")
|
||||
((lf lax) "\n")
|
||||
((cr) "\r")
|
||||
(else (string (csv-grammar-record-separator grammar))))
|
||||
out))))
|
||||
|
||||
(define csv-write
|
||||
(opt-lambda ((writer (csv-writer)))
|
||||
(opt-lambda (rows (out (current-output-port)))
|
||||
(for-each
|
||||
(lambda (row) (writer row out))
|
||||
rows))))
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
(define-library (chibi csv)
|
||||
(import (scheme base) (srfi 227))
|
||||
(import (scheme base) (scheme write) (srfi 130) (srfi 227))
|
||||
(export csv-grammar csv-parser csv-grammar?
|
||||
default-csv-grammar default-tsv-grammar
|
||||
csv-read->list csv-read->vector csv-read->fixed-vector
|
||||
csv-read->sxml
|
||||
csv-fold csv-map csv->list csv-for-each csv->sxml)
|
||||
csv-fold csv-map csv->list csv-for-each csv->sxml
|
||||
csv-writer csv-write)
|
||||
(include "csv.scm"))
|
||||
|
|
Loading…
Add table
Reference in a new issue