From bf7187f324f36ec7ce46d019721428ab995f3335 Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Fri, 8 Nov 2024 16:25:13 +0900 Subject: [PATCH] add csv-num-rows --- lib/chibi/csv-test.sld | 5 ++++- lib/chibi/csv.scm | 46 ++++++++++++++++++++++++++++++++++++++++++ lib/chibi/csv.sld | 5 +++-- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/chibi/csv-test.sld b/lib/chibi/csv-test.sld index 41bc5c05..d8d2a0cb 100644 --- a/lib/chibi/csv-test.sld +++ b/lib/chibi/csv-test.sld @@ -77,7 +77,10 @@ Paris,48°51′24″N,2°21′03″E")) (latitude "48°51′24″N") (longitude "2°21′03″E"))) ((csv->sxml 'city '(name latitude longitude)) - (open-input-string city-csv)))) + (open-input-string city-csv))) + (test 3 (csv-num-rows default-csv-grammar (open-input-string city-csv))) + (test 0 (csv-num-rows default-csv-grammar (open-input-string ""))) + (test 1 (csv-num-rows default-csv-grammar (open-input-string "x")))) (test "1997,Ford,E350\n" (csv->string '("1997" "Ford" "E350"))) (test "1997,Ford,E350,\"Super, luxurious truck\"\n" diff --git a/lib/chibi/csv.scm b/lib/chibi/csv.scm index a3a68354..8b50e73c 100644 --- a/lib/chibi/csv.scm +++ b/lib/chibi/csv.scm @@ -210,6 +210,52 @@ (write-char ch out) (lp)))))) +(define (csv-skip-quoted in grammar) + (let lp () + (let ((ch (read-char in))) + (cond + ((eof-object? ch) + (error "unterminated csv quote")) + ((eqv? ch (csv-grammar-quote-char grammar)) + (when (and (csv-grammar-quote-doubling-escapes? grammar) + (eqv? ch (peek-char in))) + (read-char in) + (lp))) + ((eqv? ch (csv-grammar-escape-char grammar)) + (read-char in) + (lp)) + (else + (lp)))))) + +;;> Returns the number of rows in the input. +(define csv-num-rows + (opt-lambda ((grammar default-csv-grammar) + (in (current-input-port))) + (let lp ((num-rows 0)) + (let ((ch (read-char in))) + (cond + ((eof-object? ch) num-rows) + ((eqv? ch (csv-grammar-quote-char grammar)) + (csv-skip-quoted in grammar) + (lp num-rows)) + ((eqv? ch (csv-grammar-record-separator grammar)) + (lp (+ num-rows 1))) + ((and (eqv? ch #\return) + (memq (csv-grammar-record-separator grammar) '(crlf lax))) + (cond + ((eqv? (peek-char in) #\newline) + (read-char in) + (lp (+ num-rows 1))) + ((eq? (csv-grammar-record-separator grammar) 'lax) + (lp (+ num-rows 1))) + (else + (lp num-rows)))) + ((and (eqv? ch #\newline) + (eq? (csv-grammar-record-separator grammar) 'lax)) + (lp (+ num-rows 1))) + (else + (lp num-rows))))))) + ;;> \section{CSV Readers} ;;> A CSV reader reads a single record, returning some representation diff --git a/lib/chibi/csv.sld b/lib/chibi/csv.sld index 6913f78c..f2450faf 100644 --- a/lib/chibi/csv.sld +++ b/lib/chibi/csv.sld @@ -4,7 +4,8 @@ (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-read->sxml csv-num-rows csv-fold csv-map csv->list csv-for-each csv->sxml - csv-writer csv-write) + csv-writer csv-write + csv-skip-line) (include "csv.scm"))