commit 854fb170d04fef5a4fdddc61d2dc6a42b6c75077 jose <jose@linux-q5ep.lan> 2018-11-12 18:52:36 -0800 Pre-optimization.
src/csv.lisp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/src/csv.lisp b/src/csv.lisp new file mode 100644 index 0000000..4124ca8 --- /dev/null +++ b/src/csv.lisp @@ -0,0 +1,48 @@ +(in-package :csv) +(defun make-escape? (prev curr) + (char= #\" prev curr) + ;(char= #\\ prev) + ) +(defun end-token? (prev curr) + (declare (ignore curr)) + (char= #\" prev)) +(defun open? (prev curr) + (declare (ignore curr)) + (char= #\" prev)) +(define-modify-macro toggle () not) +(defun make-switches () + (let ((in nil) + (escape nil)) + (lambda (prev curr str) + (if (null curr) + (progn (setf in nil escape nil) str) + (if in + (if escape + (progn (toggle escape) (push-on prev str)) + (if (make-escape? prev curr) + (progn (toggle escape) str) + (if (end-token? prev curr) + (progn (toggle in) (push-on #\Nul str)) + (push-on prev str)))) + (if (open? prev curr) + (progn (toggle in) str) + str)))))) +(defun splice (str &optional acc!) + (if (string= "" str) + (nreverse acc!) + (let ((res (search (string #\Nul) str))) + (splice (subseq str (1+ res)) (push (subseq str 0 res) acc!))))) +(make-reader my-csv (stream #\# #\!) + (let ((switches (make-switches))) + (macrolet ((once (&body body) ``',,@body)) + (do ((prev #1= (read-char stream nil nil) curr) + (curr #1# #1#) + (str (make-array 0 :adjustable t :element-type 'character) + (funcall switches prev curr str))) + ((and (char= curr #\#) (char= prev #\!)) (once (splice (funcall switches nil nil str)))))))) +(defun read-to-string (stream) + (let ((str (make-array 0 :adjustable t :element-type 'character))) + (doread (ch stream) (push-on ch str)) str)) +(defun slurp-csv (path) + (with-open-file (s path) + (concatenate 'string "#!" (read-to-string s) "!#")))