From 658743bb00c2a7e5357a4db2e3e7228f107a6d43 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Fri, 30 Jan 2009 17:13:12 -0600 Subject: [PATCH 1/5] add missing copyright to svg.factor --- extra/svg/svg.factor | 1 + 1 file changed, 1 insertion(+) diff --git a/extra/svg/svg.factor b/extra/svg/svg.factor index b5c5e96e90..6df7314653 100644 --- a/extra/svg/svg.factor +++ b/extra/svg/svg.factor @@ -1,3 +1,4 @@ +! (c)2009 Joe Groff, see BSD license USING: accessors arrays assocs fry kernel math math.affine-transforms math.constants math.functions math.parser math.vectors memoize peg.ebnf sequences sequences.squish splitting strings xml.data xml.utilities ; From 8b68e80254e35c3b5ef862b0aac9bcb255e8d2db Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Fri, 30 Jan 2009 17:13:40 -0600 Subject: [PATCH 2/5] load libblas before libcblas on openbsd --- basis/math/blas/cblas/cblas.factor | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/basis/math/blas/cblas/cblas.factor b/basis/math/blas/cblas/cblas.factor index 3914c5b2ec..54616d42de 100644 --- a/basis/math/blas/cblas/cblas.factor +++ b/basis/math/blas/cblas/cblas.factor @@ -3,13 +3,14 @@ IN: math.blas.cblas << : load-atlas ( -- ) - "atlas" "libatlas.so" "cdecl" add-library - "atlas" load-library drop ; + "atlas" "libatlas.so" "cdecl" add-library ; +: load-blas ( -- ) + "blas" "libblas.so" "cdecl" add-library ; "cblas" { { [ os macosx? ] [ "libblas.dylib" "cdecl" add-library ] } { [ os windows? ] [ "blas.dll" "cdecl" add-library ] } - { [ os openbsd? ] [ "libcblas.so" "cdecl" add-library ] } + { [ os openbsd? ] [ "libcblas.so" "cdecl" add-library load-blas ] } { [ os freebsd? ] [ "libcblas.so" "cdecl" add-library load-atlas ] } [ "libblas.so" "cdecl" add-library ] } cond From f1182ef800c429a68ff9afc370fabff3e161189d Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Fri, 30 Jan 2009 17:28:06 -0600 Subject: [PATCH 3/5] use CONSTANT: for cblas constants --- basis/math/blas/cblas/cblas.factor | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/basis/math/blas/cblas/cblas.factor b/basis/math/blas/cblas/cblas.factor index 54616d42de..11552d67bb 100644 --- a/basis/math/blas/cblas/cblas.factor +++ b/basis/math/blas/cblas/cblas.factor @@ -19,25 +19,25 @@ IN: math.blas.cblas LIBRARY: cblas TYPEDEF: int CBLAS_ORDER -: CblasRowMajor 101 ; inline -: CblasColMajor 102 ; inline +CONSTANT: CblasRowMajor 101 +CONSTANT: CblasColMajor 102 TYPEDEF: int CBLAS_TRANSPOSE -: CblasNoTrans 111 ; inline -: CblasTrans 112 ; inline -: CblasConjTrans 113 ; inline +CONSTANT: CblasNoTrans 111 +CONSTANT: CblasTrans 112 +CONSTANT: CblasConjTrans 113 TYPEDEF: int CBLAS_UPLO -: CblasUpper 121 ; inline -: CblasLower 122 ; inline +CONSTANT: CblasUpper 121 +CONSTANT: CblasLower 122 TYPEDEF: int CBLAS_DIAG -: CblasNonUnit 131 ; inline -: CblasUnit 132 ; inline +CONSTANT: CblasNonUnit 131 +CONSTANT: CblasUnit 132 TYPEDEF: int CBLAS_SIDE -: CblasLeft 141 ; inline -: CblasRight 142 ; inline +CONSTANT: CblasLeft 141 +CONSTANT: CblasRight 142 TYPEDEF: int CBLAS_INDEX From f1a1760e6ead33bef83ca823cf0f1e874e7a2aa8 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Fri, 30 Jan 2009 19:23:04 -0600 Subject: [PATCH 4/5] add csv>file and file>csv words, better docs for csv, a few cleanups --- basis/csv/csv-docs.factor | 48 ++++++++++++++----- basis/csv/csv-tests.factor | 16 ++++++- basis/csv/csv.factor | 95 ++++++++++++++++++++++---------------- 3 files changed, 106 insertions(+), 53 deletions(-) diff --git a/basis/csv/csv-docs.factor b/basis/csv/csv-docs.factor index e4741f4810..6ae75b6b2f 100644 --- a/basis/csv/csv-docs.factor +++ b/basis/csv/csv-docs.factor @@ -1,28 +1,52 @@ -USING: help.syntax help.markup kernel prettyprint sequences ; +USING: help.syntax help.markup kernel prettyprint sequences +io.pathnames ; IN: csv HELP: csv { $values { "stream" "an input stream" } { "rows" "an array of arrays of fields" } } -{ $description "parses a csv stream into an array of row arrays" -} ; +{ $description "Parses a csv stream into an array of row arrays." } ; + +HELP: file>csv +{ $values + { "path" pathname } { "encoding" "an encoding descriptor" } + { "csv" "csv" } +} +{ $description "Opens a file and parses it into a sequence of comma-separated-value fields." } ; + +HELP: csv>file +{ $values + { "rows" "a sequence of sequences of strings" } + { "path" pathname } { "encoding" "an encoding descriptor" } +} +{ $description "Writes a comma-separated-value structure to a file." } ; HELP: csv-row { $values { "stream" "an input stream" } { "row" "an array of fields" } } -{ $description "parses a row from a csv stream" -} ; +{ $description "parses a row from a csv stream" } ; HELP: write-csv -{ $values { "rows" "an sequence of sequences of strings" } +{ $values { "rows" "a sequence of sequences of strings" } { "stream" "an output stream" } } -{ $description "writes csv to the output stream, escaping where necessary" -} ; - +{ $description "Writes a sequence of sequences of comma-separated-values to the output stream, escaping where necessary." } ; HELP: with-delimiter -{ $values { "char" "field delimiter (e.g. CHAR: \t)" } +{ $values { "ch" "field delimiter (e.g. CHAR: \t)" } { "quot" "a quotation" } } -{ $description "Sets the field delimiter for csv or csv-row words " -} ; +{ $description "Sets the field delimiter for csv or csv-row words." } ; +ARTICLE: "csv" "Comma-separated-values parsing and writing" +"The " { $vocab-link "csv" } " vocabulary can read and write CSV (comma-separated-value) files." $nl +"Reading a csv file:" +{ $subsection file>csv } +"Writing a csv file:" +{ $subsection csv>file } +"Changing the delimiter from a comma:" +{ $subsection with-delimiter } +"Reading from a stream:" +{ $subsection csv } +"Writing to a stream:" +{ $subsection write-csv } ; + +ABOUT: "csv" diff --git a/basis/csv/csv-tests.factor b/basis/csv/csv-tests.factor index 8261ae104a..4d78c2af86 100644 --- a/basis/csv/csv-tests.factor +++ b/basis/csv/csv-tests.factor @@ -1,5 +1,7 @@ +USING: io.streams.string csv tools.test shuffle kernel strings +io.pathnames io.files.unique io.encodings.utf8 io.files +io.directories ; IN: csv.tests -USING: io.streams.string csv tools.test shuffle kernel strings ; ! I like to name my unit tests : named-unit-test ( name output input -- ) @@ -76,3 +78,15 @@ USING: io.streams.string csv tools.test shuffle kernel strings ; "escapes quotes commas and newlines when writing" [ "\"fo\"\"o1\",bar1\n\"fo\no2\",\"b,ar2\"\n" ] [ { { "fo\"o1" "bar1" } { "fo\no2" "b,ar2" } } tuck write-csv >string ] named-unit-test ! " + +[ { { "writing" "some" "csv" "tests" } } ] +[ + "writing,some,csv,tests" + "csv-test1-" unique-file utf8 + [ set-file-contents ] [ file>csv ] [ drop delete-file ] 2tri +] unit-test + +[ t ] [ + { { "writing,some,csv,tests" } } dup "csv-test2-" + unique-file utf8 [ csv>file ] [ file>csv ] 2bi = +] unit-test diff --git a/basis/csv/csv.factor b/basis/csv/csv.factor index bc3c25d347..7789f015d9 100755 --- a/basis/csv/csv.factor +++ b/basis/csv/csv.factor @@ -1,89 +1,104 @@ ! Copyright (C) 2007, 2008 Phil Dawes ! See http://factorcode.org/license.txt for BSD license. - -! Simple CSV Parser -! Phil Dawes phil@phildawes.net - -USING: kernel sequences io namespaces make -combinators unicode.categories ; +USING: kernel sequences io namespaces make combinators +unicode.categories io.files combinators.short-circuit ; IN: csv SYMBOL: delimiter CHAR: , delimiter set-global + ( -- delimiter ) delimiter get ; inline DEFER: quoted-field ( -- endchar ) -! trims whitespace from either end of string : trim-whitespace ( str -- str ) - [ blank? ] trim ; inline + [ blank? ] trim ; inline : skip-to-field-end ( -- endchar ) "\n" delimiter> suffix read-until nip ; inline : not-quoted-field ( -- endchar ) - "\"\n" delimiter> suffix read-until ! " - dup - { { CHAR: " [ drop drop quoted-field ] } ! " - { delimiter> [ swap trim-whitespace % ] } - { CHAR: \n [ swap trim-whitespace % ] } - { f [ swap trim-whitespace % ] } ! eof - } case ; + "\"\n" delimiter> suffix read-until + dup { + { CHAR: " [ 2drop quoted-field ] } + { delimiter> [ swap trim-whitespace % ] } + { CHAR: \n [ swap trim-whitespace % ] } + { f [ swap trim-whitespace % ] } + } case ; : maybe-escaped-quote ( -- endchar ) - read1 dup - { { CHAR: " [ , quoted-field ] } ! " is an escaped quote - { delimiter> [ ] } ! end of quoted field - { CHAR: \n [ ] } - [ 2drop skip-to-field-end ] ! end of quoted field + padding - } case ; + read1 dup { + { CHAR: " [ , quoted-field ] } + { delimiter> [ ] } + { CHAR: \n [ ] } + [ 2drop skip-to-field-end ] + } case ; : quoted-field ( -- endchar ) - "\"" read-until ! " - drop % maybe-escaped-quote ; + "\"" read-until + drop % maybe-escaped-quote ; : field ( -- sep string ) - [ not-quoted-field ] "" make ; ! trim-whitespace + [ not-quoted-field ] "" make ; : (row) ( -- sep ) - field , - dup delimiter get = [ drop (row) ] when ; + field , + dup delimiter get = [ drop (row) ] when ; : row ( -- eof? array[string] ) - [ (row) ] { } make ; + [ (row) ] { } make ; : append-if-row-not-empty ( row -- ) - dup { "" } = [ drop ] [ , ] if ; + dup { "" } = [ drop ] [ , ] if ; : (csv) ( -- ) - row append-if-row-not-empty - [ (csv) ] when ; + row append-if-row-not-empty + [ (csv) ] when ; +PRIVATE> + : csv-row ( stream -- row ) - [ row nip ] with-input-stream ; + [ row nip ] with-input-stream ; : csv ( stream -- rows ) - [ [ (csv) ] { } make ] with-input-stream ; + [ [ (csv) ] { } make ] with-input-stream ; -: with-delimiter ( char quot -- ) - delimiter swap with-variable ; inline +: file>csv ( path encoding -- csv ) + csv ; + +: with-delimiter ( ch quot -- ) + [ delimiter ] dip with-variable ; inline + + : write-row ( row -- ) - [ delimiter get write1 ] [ escape-if-required write ] interleave nl ; inline + [ delimiter get write1 ] + [ escape-if-required write ] interleave nl ; inline : write-csv ( rows stream -- ) - [ [ write-row ] each ] with-output-stream ; + [ [ write-row ] each ] with-output-stream ; + +: csv>file ( rows path encoding -- ) write-csv ; From 9c2a476d98751840a31ad3beb855eeafcca6694b Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Fri, 30 Jan 2009 19:24:35 -0600 Subject: [PATCH 5/5] minor cleanup --- basis/csv/csv.factor | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/basis/csv/csv.factor b/basis/csv/csv.factor index 7789f015d9..152b3dcbba 100755 --- a/basis/csv/csv.factor +++ b/basis/csv/csv.factor @@ -51,12 +51,8 @@ DEFER: quoted-field ( -- endchar ) : row ( -- eof? array[string] ) [ (row) ] { } make ; -: append-if-row-not-empty ( row -- ) - dup { "" } = [ drop ] [ , ] if ; - : (csv) ( -- ) - row append-if-row-not-empty - [ (csv) ] when ; + row harvest [ , ] unless-empty [ (csv) ] when ; PRIVATE>