diff --git a/ext/bamfcsv/bamfcsv_ext.c b/ext/bamfcsv/bamfcsv_ext.c index 2eab1c8..83477e0 100644 --- a/ext/bamfcsv/bamfcsv_ext.c +++ b/ext/bamfcsv/bamfcsv_ext.c @@ -98,10 +98,7 @@ VALUE build_matrix(char *buf, int bufsize) { for (cur = buf; cur < buf+bufsize; cur++) { if (*cur == '"') { - if (in_quote) - in_quote = 0; - else - in_quote = 1; + in_quote = !in_quote; } if (!in_quote) { @@ -166,7 +163,7 @@ VALUE mm_parse(const char *file) { return matrix; } -VALUE do_the_parsing(VALUE self, VALUE file) { +VALUE read_path(VALUE self, VALUE file) { return mm_parse(RSTRING_PTR(file)); @@ -175,6 +172,6 @@ VALUE do_the_parsing(VALUE self, VALUE file) { void Init_bamfcsv() { VALUE module = rb_define_module("BAMFCSV"); - rb_define_module_function(module, "parse", do_the_parsing, 1); + rb_define_module_function(module, "read_path", read_path, 1); } diff --git a/ext/bamfcsv/bamfcsv_ext.h b/ext/bamfcsv/bamfcsv_ext.h index b1387d9..3b34570 100644 --- a/ext/bamfcsv/bamfcsv_ext.h +++ b/ext/bamfcsv/bamfcsv_ext.h @@ -13,10 +13,6 @@ struct s_Cell { struct s_Cell *next_cell; }; -VALUE mm_parse(const char *file); - -VALUE do_the_parsing(VALUE self, VALUE file); - void Init_bamfcsv(); #endif diff --git a/lib/bamfcsv.rb b/lib/bamfcsv.rb index 18242f0..33f424f 100644 --- a/lib/bamfcsv.rb +++ b/lib/bamfcsv.rb @@ -2,4 +2,11 @@ module BAMFCSV + def self.read(thing_to_read) + if String === thing_to_read + raise ArgumentError.new("#{thing_to_read} is not a flat file.") unless File.file? thing_to_read + read_path(thing_to_read) + end + end + end diff --git a/spec/fixtures/bamf-comma-comma.csv b/spec/fixtures/bamf-comma-comma.csv new file mode 100644 index 0000000..a463cfe --- /dev/null +++ b/spec/fixtures/bamf-comma-comma.csv @@ -0,0 +1 @@ +BAMF,,CSV diff --git a/spec/fixtures/double-quotes.csv b/spec/fixtures/double-quotes.csv new file mode 100644 index 0000000..b42a435 --- /dev/null +++ b/spec/fixtures/double-quotes.csv @@ -0,0 +1,3 @@ +this is a semicolon:, ; +this is a comma:," ," +this is a quote:," """ diff --git a/spec/fixtures/empty.csv b/spec/fixtures/empty.csv new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixtures/escapes.csv b/spec/fixtures/escapes.csv new file mode 100644 index 0000000..9b10e76 --- /dev/null +++ b/spec/fixtures/escapes.csv @@ -0,0 +1,2 @@ +this is a semicolon:, ; +this is a comma:," ," diff --git a/spec/fixtures/one-column.csv b/spec/fixtures/one-column.csv new file mode 100644 index 0000000..9671ad3 --- /dev/null +++ b/spec/fixtures/one-column.csv @@ -0,0 +1,2 @@ +BAMF +CSV diff --git a/spec/fixtures/terminated-with-cr.csv b/spec/fixtures/terminated-with-cr.csv new file mode 100644 index 0000000..422c2b7 --- /dev/null +++ b/spec/fixtures/terminated-with-cr.csv @@ -0,0 +1,2 @@ +a +b diff --git a/spec/lib/bamfcsv_spec.rb b/spec/lib/bamfcsv_spec.rb index e054b40..fa8d5f8 100644 --- a/spec/lib/bamfcsv_spec.rb +++ b/spec/lib/bamfcsv_spec.rb @@ -2,12 +2,48 @@ describe BAMFCSV do it "has a parse method" do - BAMFCSV.should respond_to(:parse) + BAMFCSV.should respond_to(:read) end - describe "#parse" do + describe "#read" do it "is a matrix given a filename" do - BAMFCSV.parse("spec/fixtures/test.csv").should be_instance_of Array + BAMFCSV.read("spec/fixtures/test.csv").should be_instance_of Array + end + + it "is an empty array passed an empty file" do + BAMFCSV.read("spec/fixtures/empty.csv").should == [] + end + + it "is a 1xn matrix with a one column csv file" do + BAMFCSV.read("spec/fixtures/one-column.csv").should == [["BAMF"],["CSV"]] + end + + it "interprets empty cells correctly" do + BAMFCSV.read("spec/fixtures/bamf-comma-comma.csv").should == [["BAMF","","CSV"]] + end + + it "escapes cells that are quoted" do + BAMFCSV.read("spec/fixtures/escapes.csv").should == [["this is a semicolon:", " ;"],["this is a comma:", " ,"]] + end + + it "escapes cells that are quoted" do + BAMFCSV.read("spec/fixtures/double-quotes.csv").should == [["this is a semicolon:", " ;"], ["this is a comma:", " ,"], ["this is quote:", " \""]] + end + + it "doesn't create a row when the file terminates with [CR]LF" do + BAMFCSV.read("spec/fixtures/terminated-with-cr.csv").should == [["a"],["b"]] + end + + it "raises Errno::ENOENT when the file does not exist" do + expect do + BAMFCSV.read("spec/fixtures/this-file-does-not-not-exist.csv") + end.should raise_error Errno::ENOENT + end + + it "raises Errno::EISDIR when the file is not a flat file" do + expect do + BAMFCSV.read("spec/fixtures/") + end.should raise_error Errno::EISDIR end end end