]> gitweb.factorcode.org Git - factor.git/blob - basis/csv/csv.factor
Remove trim-whitespace in favor of [ blank? ] trim.
[factor.git] / basis / csv / csv.factor
1 ! Copyright (C) 2007, 2008 Phil Dawes
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences io namespaces make combinators
4 unicode.categories io.files combinators.short-circuit
5 io.streams.string ;
6 IN: csv
7
8 SYMBOL: delimiter
9
10 CHAR: , delimiter set-global
11
12 <PRIVATE
13
14 : delimiter> ( -- delimiter ) delimiter get ; inline
15
16 DEFER: quoted-field ( -- endchar )
17
18 : skip-to-field-end ( -- endchar )
19   "\n" delimiter> suffix read-until nip ; inline
20
21 : not-quoted-field ( -- endchar )
22     "\"\n" delimiter> suffix read-until
23     dup {
24         { CHAR: "    [ 2drop quoted-field ] }
25         { delimiter> [ swap [ blank? ] trim % ] }
26         { CHAR: \n   [ swap [ blank? ] trim % ] }
27         { f          [ swap [ blank? ] trim % ] }
28     } case ;
29
30 : maybe-escaped-quote ( -- endchar )
31     read1 dup {
32         { CHAR: "    [ , quoted-field ] }
33         { delimiter> [ ] }
34         { CHAR: \n   [ ] }
35         [ 2drop skip-to-field-end ]
36     } case ;
37
38 : quoted-field ( -- endchar )
39     "\"" read-until
40     drop % maybe-escaped-quote ;
41
42 : field ( -- sep string )
43     [ not-quoted-field ] "" make  ;
44
45 : (row) ( -- sep )
46     field ,
47     dup delimiter> = [ drop (row) ] when ;
48
49 : row ( -- eof? array[string] )
50     [ (row) ] { } make ;
51
52 : (csv) ( -- )
53     row
54     dup [ empty? ] all? [ drop ] [ , ] if
55     [ (csv) ] when ;
56
57 PRIVATE>
58
59 : csv-row ( stream -- row )
60     [ row nip ] with-input-stream ;
61
62 : csv ( stream -- rows )
63     [ [ (csv) ] { } make ] with-input-stream
64     dup last { "" } = [ but-last ] when ;
65
66 : string>csv ( string -- csv )
67     <string-reader> csv ;
68
69 : file>csv ( path encoding -- csv )
70     <file-reader> csv ;
71
72 : with-delimiter ( ch quot -- )
73     [ delimiter ] dip with-variable ; inline
74
75 <PRIVATE
76
77 : needs-escaping? ( cell -- ? )
78     [ { [ "\n\"" member? ] [ delimiter> = ] } 1|| ] any? ; inline
79
80 : escape-quotes ( cell -- cell' )
81     [
82         [
83             [ , ]
84             [ dup CHAR: " = [ , ] [ drop ] if ] bi
85         ] each
86     ] "" make ; inline
87
88 : enclose-in-quotes ( cell -- cell' )
89     "\"" dup surround ; inline
90
91 : escape-if-required ( cell -- cell' )
92     dup needs-escaping?
93     [ escape-quotes enclose-in-quotes ] when ; inline
94
95 PRIVATE>
96
97 : write-row ( row -- )
98     [ delimiter> write1 ]
99     [ escape-if-required write ] interleave nl ; inline
100
101 <PRIVATE
102
103 : (write-csv) ( rows -- )
104     [ write-row ] each ;
105
106 PRIVATE>
107
108 : write-csv ( rows stream -- )
109     [ (write-csv) ] with-output-stream ;
110
111 : csv>string ( csv -- string )
112     [ (write-csv) ] with-string-writer ;
113
114 : csv>file ( rows path encoding -- ) <file-writer> write-csv ;