summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog63
-rw-r--r--lib/csv.rb694
-rw-r--r--lib/logger.rb16
-rw-r--r--test/csv/test_csv.rb677
-rw-r--r--test/ruby/test_float.rb18
5 files changed, 782 insertions, 686 deletions
diff --git a/ChangeLog b/ChangeLog
index 68e9a51019..4b18521373 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
+Thu May 27 23:15:18 2004 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/logger.rb: leading 0 padding of timestamp usec part.
+
+ * lib/csv.rb (CSV.parse): [CAUTION] behavior changed. in the past,
+ CSV.parse accepts a filename to be read-opened (it was just a
+ shortcut of CSV.open(filename, 'r')). now CSV.parse accepts a
+ string or a stream to be parsed e.g.
+ CSV.parse("1,2\n3,r") #=> [['1', '2'], ['3', '4']]
+
+ * lib/csv.rb: CSV::Row and CSV::Cell are deprecated. these classes
+ are removed in the future. in the new csv.rb, row is represented
+ as just an Array. since CSV::Row was a subclass of Array, it won't
+ hurt almost all programs except one which depended CSV::Row#match.
+ and a cell is represented as just a String or nil(NULL). this
+ change will cause widespread destruction.
+
+ CSV.open("foo.csv", "r") do |row|
+ row.each do |cell|
+ if cell.is_null # using Cell#is_null
+ p "(NULL)"
+ else
+ p cell.data # using Cell#data
+ end
+ end
+ end
+
+ must be just;
+
+ CSV.open("foo.csv", "r") do |row|
+ row.each do |cell|
+ if cell.nil?
+ p "(NULL)"
+ else
+ p cell
+ end
+ end
+ end
+
+ * lib/csv.rb: [CAUTION] record separator(CR, LF, CR+LF) behavior
+ change. CSV.open, CSV.parse, and CSV,generate now do not force
+ opened file binmode. formerly it set binmode explicitly.
+
+ with CSV.open, binmode of opened file depends the given mode
+ parameter "r", "w", "rb", and "wb". CSV.parse and CSV.generate open
+ file with "r" and "w".
+
+ setting mode properly is user's responsibility now.
+
+ * lib/csv.rb: accepts String as a fs (field separator/column separator)
+ and rs (record separator/row separator)
+
+ * lib/csv.rb (CSV.read, CSV.readlines): added. works as IO.read and
+ IO.readlines in CSV format.
+
+ * lib/csv.rb: added CSV.foreach(path, rs = nil, &block). CSV.foreach
+ now does not handle "| cmd" as a path different from IO.foreach.
+ needed?
+
+ * test/csv/test_csv.rb: updated.
+
+ * test/ruby/test_float.rb: added test_strtod to test Float("0").
+
Thu May 27 21:37:50 2004 Tanaka Akira <akr@m17n.org>
* lib/pathname.rb (Pathname#initialize): refine pathname initialization
diff --git a/lib/csv.rb b/lib/csv.rb
index 3eb13192fe..f6c12fa285 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -1,110 +1,42 @@
# CSV -- module for generating/parsing CSV data.
-
+# Copyright (C) 2000-2004 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>.
+
# $Id$
-
+
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
-
-
+
+
class CSV
+ class IllegalFormatError < RuntimeError; end
- # Describes a cell of CSV.
- class Cell
- # Datum as string.
- attr_accessor :data
-
- # Is this datum NULL?
- attr_accessor :is_null
-
- # If is_null is true, datum is stored in the instance created but it
- # should be treated as 'NULL'.
- def initialize(data = '', is_null = true)
- @data = data
- @is_null = is_null
- end
-
- # Compares another cell with self. Bear in mind NULL matches with NULL.
- # Use CSV::Cell#== if you don't want NULL matches with NULL.
- # rhs: an instance of CSV::Cell to be compared.
- def match(rhs)
- if @is_null and rhs.is_null
- true
- elsif @is_null or rhs.is_null
- false
- else
- @data == rhs.data
- end
- end
-
- # Compares another cell with self. Bear in mind NULL does not match with
- # NULL. Use CSV::Cell#match if you want NULL matches with NULL.
- # rhs: an instance of CSV::Cell to be compared.
- def ==(rhs)
- if @is_null or rhs.is_null
- false
- else
- @data == rhs.data
- end
- end
-
- def to_str
- content.to_str
- end
-
- def to_s
- content.to_s
+ # deprecated
+ class Cell < String
+ def initialize(data = "", is_null = false)
+ super(is_null ? "" : data)
end
- private
-
- def content
- @is_null ? nil : data
+ def data
+ to_s
end
end
-
- # Describes a row of CSV. Each element must be a CSV::Cell.
+ # deprecated
class Row < Array
-
- # Returns the strings contained in the row's cells.
- def to_a
- self.collect { |cell| cell.is_null ? nil : cell.data }
- end
-
- # Compares another row with self.
- # rhs: an Array of cells. Each cell should be a CSV::Cell.
- def match(rhs)
- if self.size != rhs.size
- return false
- end
- for idx in 0...(self.size)
- unless self[idx].match(rhs[idx])
- return false
- end
- end
- true
- end
end
-
- class IllegalFormatError < RuntimeError; end
-
-
- def CSV.open(filename, mode, col_sep = ?,, row_sep = nil, &block)
- if mode == 'r' or mode == 'rb'
- open_reader(filename, col_sep, row_sep, &block)
- elsif mode == 'w' or mode == 'wb'
- open_writer(filename, col_sep, row_sep, &block)
- else
- raise ArgumentError.new("'mode' must be 'r', 'rb', 'w', or 'wb'")
- end
- end
-
- # Open a CSV formatted file for reading.
+ # Open a CSV formatted file for reading or writing.
+ #
+ # For reading.
#
# EXAMPLE 1
- # reader = CSV.parse('csvfile.csv')
+ # CSV.open('csvfile.csv', 'r') do |row|
+ # p row
+ # end
+ #
+ # EXAMPLE 2
+ # reader = CSV.open('csvfile.csv', 'r')
# row1 = reader.shift
# row2 = reader.shift
# if row2.empty?
@@ -112,11 +44,6 @@ class CSV
# end
# reader.close
#
- # EXAMPLE 2
- # CSV.parse('csvfile.csv') do |row|
- # p row
- # end
- #
# ARGS
# filename: filename to parse.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -127,24 +54,21 @@ class CSV
# RETURNS
# reader instance. To get parse result, see CSV::Reader#each.
#
- def CSV.parse(filename, col_sep = ?,, row_sep = nil, &block)
- open_reader(filename, col_sep, row_sep, &block)
- end
-
- # Open a CSV formatted file for writing.
#
- # EXAMPLE 1
- # writer = CSV.generate('csvfile.csv')
- # writer << ['r1c1', 'r1c2'] << ['r2c1', 'r2c2'] << [nil, nil]
- # writer.close
+ # For writing.
#
- # EXAMPLE 2
- # CSV.generate('csvfile.csv') do |writer|
+ # EXAMPLE 1
+ # CSV.open('csvfile.csv', 'w') do |writer|
# writer << ['r1c1', 'r1c2']
# writer << ['r2c1', 'r2c2']
# writer << [nil, nil]
# end
#
+ # EXAMPLE 2
+ # writer = CSV.open('csvfile.csv', 'w')
+ # writer << ['r1c1', 'r1c2'] << ['r2c1', 'r2c2'] << [nil, nil]
+ # writer.close
+ #
# ARGS
# filename: filename to generate.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -156,8 +80,52 @@ class CSV
# writer instance. See CSV::Writer#<< and CSV::Writer#add_row to know how
# to generate CSV string.
#
- def CSV.generate(filename, col_sep = ?,, row_sep = nil, &block)
- open_writer(filename, col_sep, row_sep, &block)
+ def CSV.open(path, mode, fs = nil, rs = nil, &block)
+ if mode == 'r' or mode == 'rb'
+ open_reader(path, mode, fs, rs, &block)
+ elsif mode == 'w' or mode == 'wb'
+ open_writer(path, mode, fs, rs, &block)
+ else
+ raise ArgumentError.new("'mode' must be 'r', 'rb', 'w', or 'wb'")
+ end
+ end
+
+ def CSV.foreach(path, rs = nil, &block)
+ open_reader(path, 'r', ',', rs, &block)
+ end
+
+ def CSV.read(path, length = nil, offset = nil)
+ CSV.parse(IO.read(path, length, offset))
+ end
+
+ def CSV.readlines(path, rs = nil)
+ reader = open_reader(path, 'r', ',', rs)
+ begin
+ reader.collect { |row| row }
+ ensure
+ reader.close
+ end
+ end
+
+ def CSV.generate(path, fs = nil, rs = nil, &block)
+ open_writer(path, 'w', fs, rs, &block)
+ end
+
+ # Parse lines from given string or stream. Return rows as an Array of Arrays.
+ def CSV.parse(str_or_readable, fs = nil, rs = nil, &block)
+ if File.exist?(str_or_readable)
+ STDERR.puts("CSV.parse(filename) is deprecated." +
+ " Use CSV.open(filename, 'r') instead.")
+ return open_reader(str_or_readable, 'r', fs, rs, &block)
+ end
+ if block
+ CSV::Reader.parse(str_or_readable, fs, rs) do |row|
+ yield(row)
+ end
+ nil
+ else
+ CSV::Reader.create(str_or_readable, fs, rs).collect { |row| row }
+ end
end
# Parse a line from given string. Bear in mind it parses ONE LINE. Rest of
@@ -166,47 +134,54 @@ class CSV
#
# If you don't know whether a target string to parse is exactly 1 line or
# not, use CSV.parse_row instead of this method.
- def CSV.parse_line(src, col_sep = ?,, row_sep = nil)
+ def CSV.parse_line(src, fs = nil, rs = nil)
+ fs ||= ','
+ if fs.is_a?(Fixnum)
+ fs = fs.chr
+ end
+ if !rs.nil? and rs.is_a?(Fixnum)
+ rs = rs.chr
+ end
idx = 0
res_type = :DT_COLSEP
- cells = Row.new
+ row = []
begin
- while (res_type.equal?(:DT_COLSEP))
- cell = Cell.new
- res_type, idx = parse_body(src, idx, cell, col_sep, row_sep)
- cells.push(cell.is_null ? nil : cell.data)
+ while res_type == :DT_COLSEP
+ res_type, idx, cell = parse_body(src, idx, fs, rs)
+ row << cell
end
rescue IllegalFormatError
- return Row.new
+ return []
end
- cells
+ row
end
# Create a line from cells. each cell is stringified by to_s.
- def CSV.generate_line(cells, col_sep = ?,, row_sep = nil)
- if (cells.size == 0)
+ def CSV.generate_line(row, fs = nil, rs = nil)
+ if row.size == 0
return ''
end
+ fs ||= ','
+ if fs.is_a?(Fixnum)
+ fs = fs.chr
+ end
+ if !rs.nil? and rs.is_a?(Fixnum)
+ rs = rs.chr
+ end
res_type = :DT_COLSEP
result_str = ''
idx = 0
while true
- cell = if (cells[idx].nil?)
- Cell.new('', true)
- else
- Cell.new(cells[idx].to_s, false)
- end
- generate_body(cell, result_str, col_sep, row_sep)
+ generate_body(row[idx], result_str, fs, rs)
idx += 1
- if (idx == cells.size)
+ if (idx == row.size)
break
end
- generate_separator(:DT_COLSEP, result_str, col_sep, row_sep)
+ generate_separator(:DT_COLSEP, result_str, fs, rs)
end
result_str
end
-
-
+
# Parse a line from string. Consider using CSV.parse_line instead.
# To parse lines in CSV string, see EXAMPLE below.
#
@@ -226,7 +201,7 @@ class CSV
# src[](idx_out_of_bounds) must return nil. A String satisfies this
# requirement.
# idx: index of parsing location of 'src'. 0 origin.
- # out_dev: buffer for parsed cells. Must respond '<<(CSV::Cell)'.
+ # out_dev: buffer for parsed cells. Must respond '<<(aString)'.
# col_sep: Column separator. ?, by default. If you want to separate
# fields with semicolon, give ?; here.
# row_sep: Row separator. nil by default. nil means "\r\n or \n". If you
@@ -236,16 +211,22 @@ class CSV
# parsed_cells: num of parsed cells.
# idx: index of next parsing location of 'src'.
#
- def CSV.parse_row(src, idx, out_dev, col_sep = ?,, row_sep = nil)
+ def CSV.parse_row(src, idx, out_dev, fs = nil, rs = nil)
+ fs ||= ','
+ if fs.is_a?(Fixnum)
+ fs = fs.chr
+ end
+ if !rs.nil? and rs.is_a?(Fixnum)
+ rs = rs.chr
+ end
idx_backup = idx
parsed_cells = 0
res_type = :DT_COLSEP
begin
- while (!res_type.equal?(:DT_ROWSEP))
- cell = Cell.new
- res_type, idx = parse_body(src, idx, cell, col_sep, row_sep)
- if res_type.equal?(:DT_EOS)
- if idx == idx_backup #((parsed_cells == 0) && (cell.is_null))
+ while res_type != :DT_ROWSEP
+ res_type, idx, cell = parse_body(src, idx, fs, rs)
+ if res_type == :DT_EOS
+ if idx == idx_backup #((parsed_cells == 0) and cell.nil?)
return 0, 0
end
res_type = :DT_ROWSEP
@@ -258,19 +239,14 @@ class CSV
end
return parsed_cells, idx
end
-
-
+
# Convert a line from cells data to string. Consider using CSV.generate_line
# instead. To generate multi-row CSV string, see EXAMPLE below.
#
# EXAMPLE
- # def d(str)
- # CSV::Cell.new(str, false)
- # end
- #
- # row1 = [d('a'), d('b')]
- # row2 = [d('c'), d('d')]
- # row3 = [d('e'), d('f')]
+ # row1 = ['a', 'b']
+ # row2 = ['c', 'd']
+ # row3 = ['e', 'f']
# src = [row1, row2, row3]
# buf = ''
# src.each do |row|
@@ -280,8 +256,8 @@ class CSV
# p buf
#
# ARGS
- # src: an Array of CSV::Cell to be converted to CSV string. Must respond to
- # 'size' and '[](idx)'. src[idx] must return CSV::Cell.
+ # src: an Array of String to be converted to CSV string. Must respond to
+ # 'size' and '[](idx)'. src[idx] must return String.
# cells: num of cells in a line.
# out_dev: buffer for generated CSV string. Must respond to '<<(string)'.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -292,39 +268,47 @@ class CSV
# RETURNS
# parsed_cells: num of converted cells.
#
- def CSV.generate_row(src, cells, out_dev, col_sep = ?,, row_sep = nil)
+ def CSV.generate_row(src, cells, out_dev, fs = nil, rs = nil)
+ fs ||= ','
+ if fs.is_a?(Fixnum)
+ fs = fs.chr
+ end
+ if !rs.nil? and rs.is_a?(Fixnum)
+ rs = rs.chr
+ end
src_size = src.size
if (src_size == 0)
if cells == 0
- generate_separator(:DT_ROWSEP, out_dev, col_sep, row_sep)
+ generate_separator(:DT_ROWSEP, out_dev, fs, rs)
end
return 0
end
res_type = :DT_COLSEP
parsed_cells = 0
- generate_body(src[parsed_cells], out_dev, col_sep, row_sep)
+ generate_body(src[parsed_cells], out_dev, fs, rs)
parsed_cells += 1
- while ((parsed_cells < cells) && (parsed_cells != src_size))
- generate_separator(:DT_COLSEP, out_dev, col_sep, row_sep)
- generate_body(src[parsed_cells], out_dev, col_sep, row_sep)
+ while ((parsed_cells < cells) and (parsed_cells != src_size))
+ generate_separator(:DT_COLSEP, out_dev, fs, rs)
+ generate_body(src[parsed_cells], out_dev, fs, rs)
parsed_cells += 1
end
if (parsed_cells == cells)
- generate_separator(:DT_ROWSEP, out_dev, col_sep, row_sep)
+ generate_separator(:DT_ROWSEP, out_dev, fs, rs)
else
- generate_separator(:DT_COLSEP, out_dev, col_sep, row_sep)
+ generate_separator(:DT_COLSEP, out_dev, fs, rs)
end
parsed_cells
end
-
+
+ # Private class methods.
class << self
private
- def open_reader(filename, col_sep, row_sep, &block)
- file = File.open(filename, 'rb')
+ def open_reader(path, mode, fs, rs, &block)
+ file = File.open(path, mode)
if block
begin
- CSV::Reader.parse(file, col_sep, row_sep) do |row|
+ CSV::Reader.parse(file, fs, rs) do |row|
yield(row)
end
ensure
@@ -332,17 +316,17 @@ class CSV
end
nil
else
- reader = CSV::Reader.create(file, col_sep, row_sep)
+ reader = CSV::Reader.create(file, fs, rs)
reader.close_on_terminate
reader
end
end
- def open_writer(filename, col_sep, row_sep, &block)
- file = File.open(filename, 'wb')
+ def open_writer(path, mode, fs, rs, &block)
+ file = File.open(path, mode)
if block
begin
- CSV::Writer.generate(file, col_sep, row_sep) do |writer|
+ CSV::Writer.generate(file, fs, rs) do |writer|
yield(writer)
end
ensure
@@ -350,147 +334,177 @@ class CSV
end
nil
else
- writer = CSV::Writer.create(file, col_sep, row_sep)
+ writer = CSV::Writer.create(file, fs, rs)
writer.close_on_terminate
writer
end
end
- def parse_body(src, idx, cell, col_sep, row_sep)
- row_sep_end = row_sep || ?\n
- cell.is_null = false
+ def parse_body(src, idx, fs, rs)
+ fs_str = fs
+ fs_size = fs_str.size
+ rs_str = rs || "\n"
+ rs_size = rs_str.size
+ fs_idx = rs_idx = 0
+ cell = Cell.new
state = :ST_START
- quoted = false
- cr = false
+ quoted = cr = false
c = nil
- while (c = src[idx])
- idx += 1
- result_state = :DT_UNKNOWN
- if (c == col_sep)
- if state.equal?(:ST_DATA)
- if cr
- raise IllegalFormatError.new
+ last_idx = idx
+ while c = src[idx]
+ unless quoted
+ fschar = (c == fs_str[fs_idx])
+ rschar = (c == rs_str[rs_idx])
+ # simple 1 char backtrack
+ if !fschar and c == fs_str[0]
+ fs_idx = 0
+ fschar = true
+ if state == :ST_START
+ state = :ST_DATA
+ elsif state == :ST_QUOTE
+ raise IllegalFormatError
end
- if (!quoted)
- state = :ST_END
- result_state = :DT_COLSEP
- else
- cell.data << c.chr
- end
- elsif state.equal?(:ST_QUOTE)
- if cr
- raise IllegalFormatError.new
- end
- state = :ST_END
- result_state = :DT_COLSEP
- else # :ST_START
- cell.is_null = true
- state = :ST_END
- result_state = :DT_COLSEP
end
- elsif (c == ?") # " for vim syntax hilighting.
- if state.equal?(:ST_DATA)
- if cr
- raise IllegalFormatError.new
+ if !rschar and c == rs_str[0]
+ rs_idx = 0
+ rschar = true
+ if state == :ST_START
+ state = :ST_DATA
+ elsif state == :ST_QUOTE
+ raise IllegalFormatError
end
+ end
+ end
+ if c == ?"
+ fs_idx = rs_idx = 0
+ if cr
+ raise IllegalFormatError
+ end
+ cell << src[last_idx, (idx - last_idx)]
+ last_idx = idx
+ if state == :ST_DATA
if quoted
+ last_idx += 1
quoted = false
state = :ST_QUOTE
else
- raise IllegalFormatError.new
+ raise IllegalFormatError
end
- elsif state.equal?(:ST_QUOTE)
- cell.data << c.chr
+ elsif state == :ST_QUOTE
+ cell << c.chr
+ last_idx += 1
quoted = true
state = :ST_DATA
else # :ST_START
quoted = true
+ last_idx += 1
state = :ST_DATA
end
- elsif row_sep.nil? and c == ?\r
+ elsif fschar or rschar
+ if fschar
+ fs_idx += 1
+ end
+ if rschar
+ rs_idx += 1
+ end
+ sep = nil
+ if fs_idx == fs_size
+ if state == :ST_START and rs_idx > 0 and fs_idx < rs_idx
+ state = :ST_DATA
+ end
+ cell << src[last_idx, (idx - last_idx - (fs_size - 1))]
+ last_idx = idx
+ fs_idx = rs_idx = 0
+ if cr
+ raise IllegalFormatError
+ end
+ sep = :DT_COLSEP
+ elsif rs_idx == rs_size
+ if state == :ST_START and fs_idx > 0 and rs_idx < fs_idx
+ state = :ST_DATA
+ end
+ if !(rs.nil? and cr)
+ cell << src[last_idx, (idx - last_idx - (rs_size - 1))]
+ last_idx = idx
+ end
+ fs_idx = rs_idx = 0
+ sep = :DT_ROWSEP
+ end
+ if sep
+ if state == :ST_DATA
+ return sep, idx + 1, cell;
+ elsif state == :ST_QUOTE
+ return sep, idx + 1, cell;
+ else # :ST_START
+ return sep, idx + 1, nil
+ end
+ end
+ elsif rs.nil? and c == ?\r
+ # special \r treatment for backward compatibility
+ fs_idx = rs_idx = 0
if cr
- raise IllegalFormatError.new
+ raise IllegalFormatError
end
+ cell << src[last_idx, (idx - last_idx)]
+ last_idx = idx
if quoted
- cell.data << c.chr
state = :ST_DATA
else
cr = true
end
- elsif c == row_sep_end
- if state.equal?(:ST_DATA)
- if cr
- state = :ST_END
- result_state = :DT_ROWSEP
- cr = false
- else
- if quoted
- cell.data << c.chr
- state = :ST_DATA
- else
- state = :ST_END
- result_state = :DT_ROWSEP
- end
- end
- elsif state.equal?(:ST_QUOTE)
- state = :ST_END
- result_state = :DT_ROWSEP
- if cr
- cr = false
- end
- else # :ST_START
- cell.is_null = true
- state = :ST_END
- result_state = :DT_ROWSEP
- end
else
- if state.equal?(:ST_DATA) || state.equal?(:ST_START)
+ fs_idx = rs_idx = 0
+ if state == :ST_DATA or state == :ST_START
if cr
- raise IllegalFormatError.new
+ raise IllegalFormatError
end
- cell.data << c.chr
state = :ST_DATA
else # :ST_QUOTE
- raise IllegalFormatError.new
+ raise IllegalFormatError
end
end
- if state.equal?(:ST_END)
- return result_state, idx;
- end
+ idx += 1
end
- if state.equal?(:ST_START)
- cell.is_null = true
- elsif state.equal?(:ST_QUOTE)
- true # dummy for coverate; only a data
+ if state == :ST_START
+ if fs_idx > 0 or rs_idx > 0
+ state = :ST_DATA
+ else
+ return :DT_EOS, idx, nil
+ end
elsif quoted
- raise IllegalFormatError.new
+ raise IllegalFormatError
elsif cr
- raise IllegalFormatError.new
+ raise IllegalFormatError
end
- return :DT_EOS, idx
+ cell << src[last_idx, (idx - last_idx)]
+ last_idx = idx
+ return :DT_EOS, idx, cell
end
-
- def generate_body(cells, out_dev, col_sep, row_sep)
- row_data = cells.data.dup
- if (!cells.is_null)
- if (row_data.gsub!('"', '""') ||
- row_data.include?(col_sep) ||
- (row_sep && row_data.index(row_sep)) ||
- (/[\r\n]/ =~ row_data) ||
- (cells.data.empty?))
+
+ def generate_body(cell, out_dev, fs, rs)
+ if cell.nil?
+ # empty
+ else
+ cell = cell.to_s
+ row_data = cell.dup
+ if (row_data.gsub!('"', '""') or
+ row_data.index(fs) or
+ (rs and row_data.index(rs)) or
+ (/[\r\n]/ =~ row_data) or
+ (cell.empty?))
out_dev << '"' << row_data << '"'
else
out_dev << row_data
end
end
end
-
- def generate_separator(type, out_dev, col_sep, row_sep)
+
+ def generate_separator(type, out_dev, fs, rs)
case type
when :DT_COLSEP
- out_dev << col_sep.chr
+ out_dev << fs
when :DT_ROWSEP
- out_dev << (row_sep ? row_sep.chr : "\r\n")
+ out_dev << (rs || "\n")
end
end
end
@@ -499,7 +513,7 @@ class CSV
# CSV formatted string/stream reader.
#
# EXAMPLE
- # read CSV lines until the first column is 'stop'.
+ # read CSV lines untill the first column is 'stop'.
#
# CSV::Reader.parse(File.open('bigdata', 'rb')) do |row|
# p row
@@ -511,30 +525,34 @@ class CSV
# Parse CSV data and get lines. Given block is called for each parsed row.
# Block value is always nil. Rows are not cached for performance reason.
- def Reader.parse(str_or_readable, col_sep = ?,, row_sep = nil)
- reader = create(str_or_readable, col_sep, row_sep)
- reader.each do |row|
- yield(row)
+ def Reader.parse(str_or_readable, fs = ',', rs = nil, &block)
+ reader = Reader.create(str_or_readable, fs, rs)
+ if block
+ reader.each do |row|
+ yield(row)
+ end
+ reader.close
+ nil
+ else
+ reader
end
- reader.close
- nil
end
# Returns reader instance.
- def Reader.create(str_or_readable, col_sep = ?,, row_sep = nil)
+ def Reader.create(str_or_readable, fs = ',', rs = nil)
case str_or_readable
when IO
- IOReader.new(str_or_readable, col_sep, row_sep)
+ IOReader.new(str_or_readable, fs, rs)
when String
- StringReader.new(str_or_readable, col_sep, row_sep)
+ StringReader.new(str_or_readable, fs, rs)
else
- IOReader.new(str_or_readable, col_sep, row_sep)
+ IOReader.new(str_or_readable, fs, rs)
end
end
def each
while true
- row = Row.new
+ row = []
parsed_cells = get_row(row)
if parsed_cells == 0
break
@@ -545,7 +563,7 @@ class CSV
end
def shift
- row = Row.new
+ row = []
parsed_cells = get_row(row)
row
end
@@ -557,25 +575,23 @@ class CSV
private
def initialize(dev)
- raise RuntimeError.new('do not instantiate this class directly')
+ raise RuntimeError.new('Do not instanciate this class directly.')
end
def get_row(row)
- raise NotImplementedError.new(
- 'method get_row must be defined in a derived class')
+ raise NotImplementedError.new('Method get_row must be defined in a derived class.')
end
def terminate
# Define if needed.
end
end
-
+
class StringReader < Reader
-
- def initialize(string, col_sep = ?,, row_sep = nil)
- @col_sep = col_sep
- @row_sep = row_sep
+ def initialize(string, fs = ',', rs = nil)
+ @fs = fs
+ @rs = rs
@dev = string
@idx = 0
if @dev[0, 3] == "\xef\xbb\xbf"
@@ -586,9 +602,8 @@ class CSV
private
def get_row(row)
- parsed_cells, next_idx =
- CSV.parse_row(@dev, @idx, row, @col_sep, @row_sep)
- if parsed_cells == 0 && next_idx == 0 && @idx != @dev.size
+ parsed_cells, next_idx = CSV.parse_row(@dev, @idx, row, @fs, @rs)
+ if parsed_cells == 0 and next_idx == 0 and @idx != @dev.size
raise IllegalFormatError.new
end
@idx = next_idx
@@ -598,12 +613,10 @@ class CSV
class IOReader < Reader
-
- def initialize(io, col_sep = ?,, row_sep = nil)
+ def initialize(io, fs = ',', rs = nil)
@io = io
- @io.binmode if @io.respond_to?(:binmode)
- @col_sep = col_sep
- @row_sep = row_sep
+ @fs = fs
+ @rs = rs
@dev = CSV::IOBuf.new(@io)
@idx = 0
if @dev[0] == 0xef and @dev[1] == 0xbb and @dev[2] == 0xbf
@@ -621,9 +634,8 @@ class CSV
private
def get_row(row)
- parsed_cells, next_idx =
- CSV.parse_row(@dev, @idx, row, @col_sep, @row_sep)
- if parsed_cells == 0 && next_idx == 0 && !@dev.is_eos?
+ parsed_cells, next_idx = CSV.parse_row(@dev, @idx, row, @fs, @rs)
+ if parsed_cells == 0 and next_idx == 0 and !@dev.is_eos?
raise IllegalFormatError.new
end
dropped = @dev.drop(next_idx)
@@ -651,56 +663,36 @@ class CSV
# outfile = File.open('csvout', 'wb')
# CSV::Writer.generate(outfile) do |csv|
# csv << ['c1', nil, '', '"', "\r\n", 'c2']
- # # or
- # csv.add_row [
- # CSV::Cell.new('c1', false),
- # CSV::Cell.new('dummy', true),
- # CSV::Cell.new('', false),
- # CSV::Cell.new('"', false),
- # CSV::Cell.new("\r\n", false)
- # CSV::Cell.new('c2', false)
- # ]
- # ...
# ...
# end
#
# outfile.close
#
class Writer
-
- # Generate CSV. Given block is called with the writer instance.
- def Writer.generate(str_or_writable, col_sep = ?,, row_sep = nil)
- writer = Writer.create(str_or_writable, col_sep, row_sep)
- yield(writer)
- writer.close
- nil
+ # Given block is called with the writer instance. str_or_writable must
+ # handle '<<(string)'.
+ def Writer.generate(str_or_writable, fs = ',', rs = nil, &block)
+ writer = Writer.create(str_or_writable, fs, rs)
+ if block
+ yield(writer)
+ writer.close
+ nil
+ else
+ writer
+ end
end
# str_or_writable must handle '<<(string)'.
- def Writer.create(str_or_writable, col_sep = ?,, row_sep = nil)
- BasicWriter.new(str_or_writable, col_sep, row_sep)
+ def Writer.create(str_or_writable, fs = ',', rs = nil)
+ BasicWriter.new(str_or_writable, fs, rs)
end
# dump CSV stream to the device. argument must be an Array of String.
- def <<(ary)
- row = ary.collect { |item|
- if item.is_a?(Cell)
- item
- elsif (item.nil?)
- Cell.new('', true)
- else
- Cell.new(item.to_s, false)
- end
- }
- CSV.generate_row(row, row.size, @dev, @col_sep, @row_sep)
- self
- end
-
- # dump CSV stream to the device. argument must be an Array of CSV::Cell.
- def add_row(row)
- CSV.generate_row(row, row.size, @dev, @col_sep, @row_sep)
+ def <<(row)
+ CSV.generate_row(row, row.size, @dev, @fs, @rs)
self
end
+ alias add_row <<
def close
terminate
@@ -709,7 +701,7 @@ class CSV
private
def initialize(dev)
- raise RuntimeError.new('do not instantiate this class directly')
+ raise RuntimeError.new('Do not instanciate this class directly.')
end
def terminate
@@ -719,12 +711,10 @@ class CSV
class BasicWriter < Writer
-
- def initialize(str_or_writable, col_sep = ?,, row_sep = nil)
- @col_sep = col_sep
- @row_sep = row_sep
+ def initialize(str_or_writable, fs = ',', rs = nil)
+ @fs = fs
+ @rs = rs
@dev = str_or_writable
- @dev.binmode if @dev.respond_to?(:binmode)
@close_on_terminate = false
end
@@ -743,6 +733,7 @@ class CSV
end
end
+private
# Buffered stream.
#
@@ -756,7 +747,7 @@ class CSV
# end
#
# # define my own 'read' method.
- # # CAUTION: Returning nil means EndOfStream.
+ # # CAUTION: Returning nil means EnfOfStream.
# def read(size)
# @s.read(size)
# end
@@ -801,8 +792,7 @@ class CSV
# end
# end
#
- class StreamBuf # pure virtual. (do not instantiate it directly)
-
+ class StreamBuf
# get a char or a partial string from the stream.
# idx: index of a string to specify a start point of a string to get.
# unlike String instance, idx < 0 returns nil.
@@ -810,7 +800,7 @@ class CSV
# returns char at idx if n == nil.
# returns a partial string, from idx to (idx + n) if n != nil. at EOF,
# the string size could not equal to arg n.
- def [](idx, n = nil)
+ def [](idx, n = nil)
if idx < 0
return nil
end
@@ -838,11 +828,11 @@ class CSV
end
loc = my_offset + next_idx
if !n
- return @buf_list[my_buf][loc] # Fixnum of char code.
+ return @buf_list[my_buf][loc] # Fixnum of char code.
elsif (loc + n - 1 < buf_size(my_buf))
- return @buf_list[my_buf][loc, n] # String.
+ return @buf_list[my_buf][loc, n] # String.
else # should do loop insted of (tail) recursive call...
- res = @buf_list[my_buf][loc, BufSize]
+ res = @buf_list[my_buf][loc, BufSize]
size_added = buf_size(my_buf) - loc
if size_added > 0
idx += size_added
@@ -856,7 +846,7 @@ class CSV
end
end
alias get []
-
+
# drop a string from the stream.
# returns dropped size. at EOF, dropped size might not equals to arg n.
# Once you drop the head of the stream, access to the dropped part via []
@@ -867,7 +857,7 @@ class CSV
end
size_dropped = 0
while (n > 0)
- if (!@is_eos || (@cur_buf != @buf_tail_idx))
+ if !@is_eos or (@cur_buf != @buf_tail_idx)
if (@offset + n < buf_size(@cur_buf))
size_dropped += n
@offset += n
@@ -888,11 +878,11 @@ class CSV
end
size_dropped
end
-
+
def is_eos?
return idx_is_eos?(0)
end
-
+
# WARN: Do not instantiate this class directly. Define your own class
# which derives this class and define 'read' instance method.
def initialize
@@ -903,24 +893,23 @@ class CSV
add_buf
@cur_buf = @buf_tail_idx
end
-
+
protected
def terminate
while (rel_buf); end
end
-
+
# protected method 'read' must be defined in derived classes.
# CAUTION: Returning a string which size is not equal to 'size' means
- # EndOfStream. When it is not at EOS, you must block the callee, try to
+ # EnfOfStream. When it is not at EOS, you must block the callee, try to
# read and return the sized string.
def read(size) # raise EOFError
- raise NotImplementedError.new(
- 'method read must be defined in a derived class')
+ raise NotImplementedError.new('Method read must be defined in a derived class.')
end
-
+
private
-
+
def buf_size(idx)
@buf_list[idx].size
end
@@ -948,7 +937,7 @@ class CSV
true
end
end
-
+
def rel_buf
if (@cur_buf < 0)
return false
@@ -962,15 +951,14 @@ class CSV
return true
end
end
-
+
def idx_is_eos?(idx)
- (@is_eos && ((@cur_buf < 0) || (@cur_buf == @buf_tail_idx)))
+ (@is_eos and ((@cur_buf < 0) or (@cur_buf == @buf_tail_idx)))
end
-
+
BufSize = 1024 * 8
end
-
# Buffered IO.
#
# EXAMPLE
@@ -986,7 +974,7 @@ class CSV
@s = s
super()
end
-
+
def close
terminate
end
@@ -996,7 +984,7 @@ class CSV
def read(size)
@s.read(size)
end
-
+
def terminate
super()
end
diff --git a/lib/logger.rb b/lib/logger.rb
index 6c1e492f4e..363e9774b4 100644
--- a/lib/logger.rb
+++ b/lib/logger.rb
@@ -167,7 +167,7 @@
# I, [Wed Mar 03 02:34:24 JST 1999 895701 #19074] INFO -- Main: info.
#
# You may change the date and time format in this manner:
-#
+#
# logger.datetime_format = "%Y-%m-%d %H:%M:%S"
# # e.g. "2004-01-03 00:54:26"
#
@@ -259,7 +259,7 @@ class Logger
#
# === Synopsis
- #
+ #
# Logger#add(severity, message = nil, progname = nil) { ... }
#
# === Args
@@ -355,18 +355,18 @@ class Logger
#
# === Examples
#
- # logger.info("MainApp") { "Received connection from #{ip}" }
+ # logger.info("MainApp") { "Received connection from #{ip}" }
# # ...
# logger.info "Waiting for input from user"
# # ...
# logger.info { "User typed #{input}" }
#
# You'll probably stick to the second form above, unless you want to provide a
- # program name (which you can do with <tt>Logger#progname=</tt> as well).
+ # program name (which you can do with <tt>Logger#progname=</tt> as well).
#
# === Return
#
- # See #add.
+ # See #add.
#
def info(progname = nil, &block)
add(INFO, nil, progname, &block)
@@ -427,7 +427,7 @@ private
def format_datetime(datetime)
if @datetime_format.nil?
- datetime.strftime("%Y-%m-%dT%H:%M:%S.") << "%6d " % datetime.usec
+ datetime.strftime("%Y-%m-%dT%H:%M:%S.") << "%06d " % datetime.usec
else
datetime.strftime(@datetime_format)
end
@@ -487,7 +487,7 @@ private
# IO object). The beginning of each file created by this class is tagged
# with a header message.
#
- # This class is unlikely to be used directly; it is a backend for Logger.
+ # This class is unlikely to be used directly; it is a backend for Logger.
#
def initialize(log = nil, opt = {})
@dev = @filename = @shift_age = @shift_size = nil
@@ -517,7 +517,7 @@ private
end
end
- @dev.write(message)
+ @dev.write(message)
end
#
diff --git a/test/csv/test_csv.rb b/test/csv/test_csv.rb
index 7092470915..1db540921b 100644
--- a/test/csv/test_csv.rb
+++ b/test/csv/test_csv.rb
@@ -1,5 +1,4 @@
-require 'test/unit/testsuite'
-require 'test/unit/testcase'
+require 'test/unit'
require 'tempfile'
require 'fileutils'
@@ -15,174 +14,20 @@ end
module CSVTestSupport
- def d(data, is_null = false)
- CSV::Cell.new(data.to_s, is_null)
- end
-end
-
-
-class TestCSVCell < Test::Unit::TestCase
- @@colData = ['', nil, true, false, 'foo', '!' * 1000]
-
- def test_Cell_EQUAL # '=='
- d1 = CSV::Cell.new('d', false)
- d2 = CSV::Cell.new('d', false)
- d3 = CSV::Cell.new('d', true)
- d4 = CSV::Cell.new('d', true)
- assert(d1 == d2, "Normal case.")
- assert(d1 != d3, "RHS is null.")
- assert(d4 != d1, "LHS is null.")
- assert(d3 != d4, "Either is null.")
- end
-
- def test_Cell_match
- d1 = CSV::Cell.new('d', false)
- d2 = CSV::Cell.new('d', false)
- d3 = CSV::Cell.new('d', true)
- d4 = CSV::Cell.new('d', true)
- assert(d1.match(d2), "Normal case.")
- assert(!d1.match(d3), "RHS is null.")
- assert(!d4.match(d1), "LHS is null.")
- assert(d3.match(d4), "Either is null.")
- end
-
- def test_Cell_data
- d = CSV::Cell.new()
- @@colData.each do |v|
- d.data = v
- assert_equal(d.data, v, "Case: #{ v }.")
- end
- end
-
- def test_Cell_data=
- d = CSV::Cell.new()
- @@colData.each do |v|
- d.data = v
- assert_equal(d.data, v, "Case: #{ v }.")
- end
- end
-
- def test_Cell_is_null
- d = CSV::Cell.new()
- d.is_null = true
- assert_equal(d.is_null, true, "Case: true.")
- d.is_null = false
- assert_equal(d.is_null, false, "Case: false.")
- end
-
- def test_Cell_is_null=
- d = CSV::Cell.new()
- d.is_null = true
- assert_equal(d.is_null, true, "Case: true.")
- d.is_null = false
- assert_equal(d.is_null, false, "Case: false.")
- end
-
- def test_Cell_s_new
- d1 = CSV::Cell.new()
- assert_equal(d1.data, '', "Default: data.")
- assert_equal(d1.is_null, true, "Default: is_null.")
-
- @@colData.each do |v|
- d = CSV::Cell.new(v)
- assert_equal(d.data, v, "Data: #{ v }.")
- end
-
- d2 = CSV::Cell.new(nil, true)
- assert_equal(d2.is_null, true, "Data: true.")
- d3 = CSV::Cell.new(nil, false)
- assert_equal(d3.is_null, false, "Data: false.")
- end
-
- def test_to_str
- d = CSV::Cell.new("foo", false)
- assert_equal("foo", d.to_str)
- assert(/foo/ =~ d)
- d = CSV::Cell.new("foo", true)
- begin
- d.to_str
- assert(false)
- rescue
- # NoMethodError or NameError
- assert(true)
- end
- end
-
- def test_to_s
- d = CSV::Cell.new("foo", false)
- assert_equal("foo", d.to_s)
- assert_equal("foo", "#{d}")
- d = CSV::Cell.new("foo", true)
- assert_equal("", d.to_s)
- assert_equal("", "#{d}")
- end
-end
-
-
-class TestCSVRow < Test::Unit::TestCase
- include CSVTestSupport
-
- def test_Row_s_match
- c1 = CSV::Row[d(1), d(2), d(3)]
- c2 = CSV::Row[d(1, false), d(2, false), d(3, false)]
- assert(c1.match(c2), "Normal case.")
-
- c1 = CSV::Row[d(1), d('foo', true), d(3)]
- c2 = CSV::Row[d(1, false), d('bar', true), d(3, false)]
- assert(c1.match(c2), "Either is null.")
-
- c1 = CSV::Row[d(1), d('foo', true), d(3)]
- c2 = CSV::Row[d(1, false), d('bar', false), d(3, false)]
- assert(!c1.match(c2), "LHS is null.")
-
- c1 = CSV::Row[d(1), d('foo'), d(3)]
- c2 = CSV::Row[d(1, false), d('bar', true), d(3, false)]
- assert(!c1.match(c2), "RHS is null.")
-
- c1 = CSV::Row[d(1), d('', true), d(3)]
- c2 = CSV::Row[d(1, false), d('', true), d(3, false)]
- assert(c1.match(c2), "Either is null(empty data).")
-
- c1 = CSV::Row[d(1), d('', true), d(3)]
- c2 = CSV::Row[d(1, false), d('', false), d(3, false)]
- assert(!c1.match(c2), "LHS is null(empty data).")
-
- c1 = CSV::Row[d(1), d(''), d(3)]
- c2 = CSV::Row[d(1, false), d('', true), d(3, false)]
- assert(!c1.match(c2), "RHS is null(empty data).")
-
- c1 = CSV::Row[]
- c2 = CSV::Row[]
- assert(c1.match(c2))
-
- c1 = CSV::Row[]
- c2 = CSV::Row[d(1)]
- assert(!c1.match(c2))
- end
-
- def test_Row_to_a
- r = CSV::Row[d(1), d(2), d(3)]
- assert_equal(['1', '2', '3'], r.to_a, 'Normal case')
-
- r = CSV::Row[d(1)]
- assert_equal(['1'], r.to_a, '1 item')
-
- r = CSV::Row[d(nil, true), d(2), d(3)]
- assert_equal([nil, '2', '3'], r.to_a, 'Null in data')
-
- r = CSV::Row[d(nil, true), d(nil, true), d(nil, true)]
- assert_equal([nil, nil, nil], r.to_a, 'Nulls')
-
- r = CSV::Row[d(nil, true)]
- assert_equal([nil], r.to_a, '1 Null')
-
- r = CSV::Row[]
- assert_equal([], r.to_a, 'Empty')
+ def d(data)
+ data
end
end
class TestCSV < Test::Unit::TestCase
+ file = Tempfile.new("crlf")
+ file << "\n"
+ file.open
+ file.binmode
+ RSEP = file.read
+ file.close
+
include CSVTestSupport
class << self
@@ -221,17 +66,17 @@ class TestCSV < Test::Unit::TestCase
}
@@fullCSVData = {
- [d('', true)] => '',
+ [d(nil)] => '',
[d('')] => '""',
- [d('', true), d('', true)] => ',',
- [d('', true), d('', true), d('', true)] => ',,',
+ [d(nil), d(nil)] => ',',
+ [d(nil), d(nil), d(nil)] => ',,',
[d('foo')] => 'foo',
[d('foo'), d('bar')] => 'foo,bar',
[d('foo'), d('"bar"'), d('baz')] => 'foo,"""bar""",baz',
[d('foo'), d('foo,bar'), d('baz')] => 'foo,"foo,bar",baz',
[d('foo'), d('""'), d('baz')] => 'foo,"""""",baz',
[d('foo'), d(''), d('baz')] => 'foo,"",baz',
- [d('foo'), d('', true), d('baz')] => 'foo,,baz',
+ [d('foo'), d(nil), d('baz')] => 'foo,,baz',
[d('foo'), d("\r"), d('baz')] => "foo,\"\r\",baz",
[d('foo'), d("\n"), d('baz')] => "foo,\"\n\",baz",
[d('foo'), d("\r\n"), d('baz')] => "foo,\"\r\n\",baz",
@@ -259,7 +104,7 @@ class TestCSV < Test::Unit::TestCase
end
def sepConv(srcStr, srcSep, destSep, row_sep = nil)
- rows = CSV::Row.new
+ rows = []
cols, idx = CSV.parse_row(srcStr, 0, rows, srcSep, row_sep)
destStr = ''
cols = CSV.generate_row(rows, rows.size, destStr, destSep, row_sep)
@@ -278,13 +123,13 @@ public
@bomfile = File.join(@tmpdir, "bom.csv")
@macfile = File.join(@tmpdir, "mac.csv")
- CSV.open(@infile, "w") do |writer|
+ CSV.open(@infile, "wb") do |writer|
@@fullCSVDataArray.each do |row|
writer.add_row(row)
end
end
- CSV.open(@infiletsv, "w", ?\t) do |writer|
+ CSV.open(@infiletsv, "wb", ?\t) do |writer|
@@fullCSVDataArray.each do |row|
writer.add_row(row)
end
@@ -317,11 +162,11 @@ public
first = true
ret = reader.each { |row|
if first
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
first = false
end
expected = expectedArray.shift
- assert(row.match(expected))
+ assert_equal(expected, row)
}
assert_nil(ret, "Return is nil")
assert(expectedArray.empty?)
@@ -352,10 +197,10 @@ public
@@fullCSVDataArray.each do |expected|
actual = reader.shift
if first
- assert_instance_of(CSV::Row, actual)
+ assert_instance_of(Array, actual)
first = false
end
- assert(actual.match(expected))
+ assert_equal(expected, actual)
checked += 1
end
assert(checked == @@fullCSVDataArray.size)
@@ -445,7 +290,7 @@ public
file << "\"\r\n\",\"\r\",\"\n\"\r1,2,3"
file.close
- file = File.open(@outfile, "r") # not "rb"
+ file = File.open(@outfile, "rb")
begin
reader = CSV::IOReader.new(file, ?,, ?\r)
assert_equal(["\r\n", "\r", "\n"], reader.shift.to_a)
@@ -454,23 +299,34 @@ public
ensure
file.close
end
+
+ file = File.open(@outfile, "r") # not "rb"
+ begin
+ lfincell = (RSEP == "\n" ? "\r\n" : "\n")
+ reader = CSV::IOReader.new(file, ?,, ?\r)
+ assert_equal([lfincell, "\r", "\n"], reader.shift.to_a)
+ assert_equal(["1", "2", "3"], reader.shift.to_a)
+ reader.close
+ ensure
+ file.close
+ end
end
def test_Reader_s_parse
ret = CSV::Reader.parse("a,b,c") { |row|
- assert_instance_of(CSV::Row, row, "Block parameter")
+ assert_instance_of(Array, row, "Block parameter")
}
assert_nil(ret, "Return is nil")
ret = CSV::Reader.parse("a;b;c", ?;) { |row|
- assert_instance_of(CSV::Row, row, "Block parameter")
+ assert_instance_of(Array, row, "Block parameter")
}
file = Tempfile.new("in.csv")
file << "a,b,c"
file.open
ret = CSV::Reader.parse(file) { |row|
- assert_instance_of(CSV::Row, row, "Block parameter")
+ assert_instance_of(Array, row, "Block parameter")
}
assert_nil(ret, "Return is nil")
@@ -478,7 +334,7 @@ public
file << "a,b,c"
file.open
ret = CSV::Reader.parse(file, ?,) { |row|
- assert_instance_of(CSV::Row, row, "Block parameter")
+ assert_instance_of(Array, row, "Block parameter")
}
# Illegal format.
@@ -536,38 +392,38 @@ public
file.open
file.binmode
str = file.read
- assert_equal("a,b,c\r\n,e,f\r\n,,\"\"\r\n", str, 'Normal')
+ assert_equal("a,b,c#{RSEP},e,f#{RSEP},,\"\"#{RSEP}", str, 'Normal')
file = Tempfile.new("out2.csv")
CSV::Writer.generate(file) do |writer|
ret = writer << [d('a'), d('b'), d('c')]
assert_instance_of(CSV::BasicWriter, ret, 'Return is self')
- writer << [d(nil, true), d('e'), d('f')] << [d(nil, true), d(nil, true), d('')]
+ writer << [d(nil), d('e'), d('f')] << [d(nil), d(nil), d('')]
end
file.open
file.binmode
str = file.read
- assert_equal("a,b,c\r\n,e,f\r\n,,\"\"\r\n", str, 'Normal')
+ assert_equal("a,b,c#{RSEP},e,f#{RSEP},,\"\"#{RSEP}", str, 'Normal')
end
def test_Writer_add_row
file = Tempfile.new("out.csv")
CSV::Writer.generate(file) do |writer|
ret = writer.add_row(
- [d('a', false), d('b', false), d('c', false)])
+ [d('a'), d('b'), d('c')])
assert_instance_of(CSV::BasicWriter, ret, 'Return is self')
writer.add_row(
- [d('dummy', true), d('e', false), d('f', false)]
+ [d(nil), d('e'), d('f')]
).add_row(
- [d('a', true), d('b', true), d('', false)]
+ [d(nil), d(nil), d('')]
)
end
file.open
file.binmode
str = file.read
- assert_equal("a,b,c\r\n,e,f\r\n,,\"\"\r\n", str, 'Normal')
+ assert_equal("a,b,c#{RSEP},e,f#{RSEP},,\"\"#{RSEP}", str, 'Normal')
end
def test_Writer_close
@@ -606,7 +462,7 @@ public
file = File.open(@outfile, "rb")
str = file.read
file.close
- assert_equal("\"\r\n\",\"\r\",\"\n\"\r1,2,3\r", str)
+ assert_equal("\"\r#{RSEP}\",\"\r\",\"#{RSEP}\"\r1,2,3\r", str)
end
#### CSV unit test
@@ -633,12 +489,12 @@ public
reader.close
CSV.open(@infile, "r") do |row|
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
break
end
CSV.open(@infiletsv, "r", ?\t) do |row|
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
break
end
@@ -673,39 +529,40 @@ public
end
def test_s_parse
- reader = CSV.parse(@infile)
- assert_instance_of(CSV::IOReader, reader)
- reader.close
+ result = CSV.parse(File.read(@infile))
+ assert_instance_of(Array, result)
+ assert_instance_of(Array, result[0])
- reader = CSV.parse(@infile)
- assert_instance_of(CSV::IOReader, reader)
- reader.close
+ result = CSV.parse(File.read(@infile))
+ assert_instance_of(Array, result)
+ assert_instance_of(Array, result[0])
- reader = CSV.parse(@infile, ?;)
- assert_instance_of(CSV::IOReader, reader)
- reader.close
+ assert_equal([], CSV.parse(""))
+ assert_equal([[nil]], CSV.parse("\n"))
- CSV.parse(@infile) do |row|
- assert_instance_of(CSV::Row, row)
+ CSV.parse(File.read(@infile)) do |row|
+ assert_instance_of(Array, row)
break
end
- CSV.parse(@infiletsv, ?\t) do |row|
- assert_instance_of(CSV::Row, row)
+ CSV.parse(File.read(@infiletsv), ?\t) do |row|
+ assert_instance_of(Array, row)
break
end
- assert_raises(Errno::ENOENT) do
- CSV.parse("NoSuchFileOrDirectory")
+ CSV.parse("") do |row|
+ assert(false)
end
- assert_raises(Errno::ENOENT) do
- CSV.parse("NoSuchFileOrDirectory", ?;)
+ count = 0
+ CSV.parse("\n") do |row|
+ assert_equal([nil], row)
+ count += 1
end
+ assert_equal(1, count)
- CSV.parse(@emptyfile) do |row|
- assert_fail("Must not reach here")
- end
+ assert_equal([["a|b-c|d"]], CSV.parse("a|b-c|d"))
+ assert_equal([["a", "b"], ["c", "d"]], CSV.parse("a|b-c|d", "|", "-"))
end
def test_s_open_writer
@@ -776,30 +633,36 @@ public
@@simpleCSVData.each do |col, str|
buf = CSV.generate_line(col, ?;)
- assert_equal(str + "\r\n", ssv2csv(buf))
+ assert_equal(str + "\n", ssv2csv(buf))
end
@@simpleCSVData.each do |col, str|
buf = CSV.generate_line(col, ?\t)
- assert_equal(str + "\r\n", tsv2csv(buf))
+ assert_equal(str + "\n", tsv2csv(buf))
end
+
+ str = CSV.generate_line(['a', 'b'], nil, ?|)
+ assert_equal('a,b', str)
+
+ str = CSV.generate_line(['a', 'b'], nil, "a")
+ assert_equal('"a",b', str)
end
def test_s_generate_row
buf = ''
cols = CSV.generate_row([], 0, buf)
assert_equal(0, cols)
- assert_equal("\r\n", buf, "Extra boundary check.")
+ assert_equal("\n", buf, "Extra boundary check.")
buf = ''
cols = CSV.generate_row([], 0, buf, ?;)
assert_equal(0, cols)
- assert_equal("\r\n", buf, "Extra boundary check.")
+ assert_equal("\n", buf, "Extra boundary check.")
buf = ''
cols = CSV.generate_row([], 0, buf, ?\t)
assert_equal(0, cols)
- assert_equal("\r\n", buf, "Extra boundary check.")
+ assert_equal("\n", buf, "Extra boundary check.")
buf = ''
cols = CSV.generate_row([], 0, buf, ?\t, ?|)
@@ -807,64 +670,64 @@ public
assert_equal("|", buf, "Extra boundary check.")
buf = ''
- cols = CSV.generate_row([d(1)], 2, buf)
+ cols = CSV.generate_row([d('1')], 2, buf)
assert_equal('1,', buf)
buf = ''
- cols = CSV.generate_row([d(1)], 2, buf, ?;)
+ cols = CSV.generate_row([d('1')], 2, buf, ?;)
assert_equal('1;', buf)
buf = ''
- cols = CSV.generate_row([d(1)], 2, buf, ?\t)
+ cols = CSV.generate_row([d('1')], 2, buf, ?\t)
assert_equal("1\t", buf)
buf = ''
- cols = CSV.generate_row([d(1)], 2, buf, ?\t, ?|)
+ cols = CSV.generate_row([d('1')], 2, buf, ?\t, ?|)
assert_equal("1\t", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf)
- assert_equal("1\r\n", buf)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf)
+ assert_equal("1\n", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf, ?;)
- assert_equal("1\r\n", buf)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf, ?;)
+ assert_equal("1\n", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf, ?\t)
- assert_equal("1\r\n", buf)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf, ?\t)
+ assert_equal("1\n", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf, ?\t, ?\n)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf, ?\t, ?\n)
assert_equal("1\n", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf, ?\t, ?\r)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf, ?\t, ?\r)
assert_equal("1\r", buf)
buf = ''
- cols = CSV.generate_row([d(1), d(2)], 1, buf, ?\t, ?|)
+ cols = CSV.generate_row([d('1'), d('2')], 1, buf, ?\t, ?|)
assert_equal("1|", buf)
@@fullCSVData.each do |col, str|
buf = ''
cols = CSV.generate_row(col, col.size, buf)
assert_equal(col.size, cols)
- assert_equal(str + "\r\n", buf)
+ assert_equal(str + "\n", buf)
end
@@fullCSVData.each do |col, str|
buf = ''
cols = CSV.generate_row(col, col.size, buf, ?;)
assert_equal(col.size, cols)
- assert_equal(str + "\r\n", ssv2csv(buf))
+ assert_equal(str + "\n", ssv2csv(buf))
end
@@fullCSVData.each do |col, str|
buf = ''
cols = CSV.generate_row(col, col.size, buf, ?\t)
assert_equal(col.size, cols)
- assert_equal(str + "\r\n", tsv2csv(buf))
+ assert_equal(str + "\n", tsv2csv(buf))
end
# row separator
@@ -889,7 +752,7 @@ public
colsToBe = 0
@@fullCSVData.each do |col, str|
cols += CSV.generate_row(col, col.size, buf)
- toBe << str << "\r\n"
+ toBe << str << "\n"
colsToBe += col.size
end
assert_equal(colsToBe, cols)
@@ -902,8 +765,8 @@ public
@@fullCSVData.each do |col, str|
lineBuf = ''
cols += CSV.generate_row(col, col.size, lineBuf, ?;)
- buf << ssv2csv(lineBuf) << "\r\n"
- toBe << ssv2csv(lineBuf) << "\r\n"
+ buf << ssv2csv(lineBuf) << "\n"
+ toBe << ssv2csv(lineBuf) << "\n"
colsToBe += col.size
end
assert_equal(colsToBe, cols)
@@ -916,8 +779,8 @@ public
@@fullCSVData.each do |col, str|
lineBuf = ''
cols += CSV.generate_row(col, col.size, lineBuf, ?\t)
- buf << tsv2csv(lineBuf) << "\r\n"
- toBe << tsv2csv(lineBuf) << "\r\n"
+ buf << tsv2csv(lineBuf) << "\n"
+ toBe << tsv2csv(lineBuf) << "\n"
colsToBe += col.size
end
assert_equal(colsToBe, cols)
@@ -941,7 +804,7 @@ public
def test_s_parse_line
@@simpleCSVData.each do |col, str|
row = CSV.parse_line(str)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(col.size, row.size)
assert_equal(col, row)
end
@@ -949,214 +812,233 @@ public
@@simpleCSVData.each do |col, str|
str = csv2ssv(str)
row = CSV.parse_line(str, ?;)
- assert_instance_of(CSV::Row, row)
- assert_equal(col.size, row.size)
- assert_equal(col, row)
+ assert_instance_of(Array, row)
+ assert_equal(col.size, row.size, str.inspect)
+ assert_equal(col, row, str.inspect)
end
@@simpleCSVData.each do |col, str|
str = csv2tsv(str)
row = CSV.parse_line(str, ?\t)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(col.size, row.size)
assert_equal(col, row)
end
+ assert_equal(['a', 'b', 'c'], CSV.parse_line("a,b,c", nil, nil))
+ assert_equal(['a', nil], CSV.parse_line("a,b,c", nil, ?b))
+ assert_equal(['a', 'b', nil], CSV.parse_line("a,b,c", nil, "c"))
+ assert_equal([nil], CSV.parse_line(""))
+ assert_equal([nil], CSV.parse_line("\n"))
+ assert_equal([""], CSV.parse_line("\"\"\n"))
+
# Illegal format.
- buf = CSV::Row.new
+ buf = []
row = CSV.parse_line("a,b,\"c\"\ra")
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
- buf = CSV::Row.new
+ buf = Array.new
row = CSV.parse_line("a;b;\"c\"\ra", ?;)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
- buf = CSV::Row.new
+ buf = Array.new
row = CSV.parse_line("a\tb\t\"c\"\ra", ?\t)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("a,b\"")
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("a;b\"", ?;)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("a\tb\"", ?\t)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a,b\"\r,")
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a;b\"\r;", ?;)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a\tb\"\r\t", ?\t)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a,b\"\r\"")
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a;b\"\r\"", ?;)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
row = CSV.parse_line("\"a\tb\"\r\"", ?\t)
- assert_instance_of(CSV::Row, row)
+ assert_instance_of(Array, row)
assert_equal(0, row.size)
end
def test_s_parse_row
@@fullCSVData.each do |col, str|
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str + "\r\n", 0, buf)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf, str.inspect)
- buf = CSV::Row.new
- cols, idx = CSV.parse_row(str + "\n", 0, buf)
+ buf = Array.new
+ cols, idx = CSV.parse_row(str + "\n", 0, buf, ?,, ?\n)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf, str.inspect)
# separator: |
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str + "|", 0, buf, ?,)
- assert(!buf.match(col))
- buf = CSV::Row.new
+ assert_not_equal(col, buf)
+ buf = Array.new
cols, idx = CSV.parse_row(str + "|", 0, buf, ?,, ?|)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf, str.inspect)
end
@@fullCSVData.each do |col, str|
str = csv2ssv(str)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str + "\r\n", 0, buf, ?;)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf, str)
end
@@fullCSVData.each do |col, str|
str = csv2tsv(str)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str + "\r\n", 0, buf, ?\t)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf, str)
end
@@fullCSVData.each do |col, str|
str = csv2tsv(str, ?|)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str + "|", 0, buf, ?\t, ?|)
assert_equal(cols, buf.size, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col), str)
+ assert_equal(col, buf, str)
end
- buf = CSV::Row.new
+ buf = []
+ CSV.parse_row("a,b,c", 0, buf, nil, nil)
+ assert_equal(['a', 'b', 'c'], buf)
+
+ buf = []
+ CSV.parse_row("a,b,c", 0, buf, nil, ?b)
+ assert_equal(['a', nil], buf)
+
+ buf = []
+ CSV.parse_row("a,b,c", 0, buf, nil, "c")
+ assert_equal(['a', 'b', nil], buf)
+
+ buf = Array.new
cols, idx = CSV.parse_row("a,b,\"c\r\"", 0, buf)
assert_equal(["a", "b", "c\r"], buf.to_a)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a;b;\"c\r\"", 0, buf, ?;)
assert_equal(["a", "b", "c\r"], buf.to_a)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\tb\t\"c\r\"", 0, buf, ?\t)
assert_equal(["a", "b", "c\r"], buf.to_a)
- buf = CSV::Row.new
- cols, idx = CSV.parse_row("a,b,c\n", 0, buf)
+ buf = Array.new
+ cols, idx = CSV.parse_row("a,b,c\n", 0, buf, ?,, ?\n)
assert_equal(["a", "b", "c"], buf.to_a)
- buf = CSV::Row.new
- cols, idx = CSV.parse_row("a\tb\tc\n", 0, buf, ?\t)
+ buf = Array.new
+ cols, idx = CSV.parse_row("a\tb\tc\n", 0, buf, ?\t, ?\n)
assert_equal(["a", "b", "c"], buf.to_a)
# Illegal format.
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a,b,c\"", 0, buf)
assert_equal(0, cols, "Illegal format; unbalanced double-quote.")
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a;b;c\"", 0, buf, ?;)
assert_equal(0, cols, "Illegal format; unbalanced double-quote.")
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a,b,\"c\"\ra", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a,b,\"c\"\ra", 0, buf, ?;)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a,b\"", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a;b\"", 0, buf, ?;)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("\"a,b\"\r,", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\r,", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\r", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\rbc", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\r\"\"", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("a\r\rabc,", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("\"a;b\"\r;", 0, buf, ?;)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("\"a,b\"\r\"", 0, buf)
assert_equal(0, cols)
assert_equal(0, idx)
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row("\"a;b\"\r\"", 0, buf, ?;)
assert_equal(0, cols)
assert_equal(0, idx)
@@ -1168,11 +1050,11 @@ public
# String "" is not allowed.
next
end
- buf = CSV::Row.new
+ buf = Array.new
cols, idx = CSV.parse_row(str, 0, buf)
assert_equal(col.size, cols, "Reported size.")
assert_equal(col.size, buf.size, "Size.")
- assert(buf.match(col))
+ assert_equal(col, buf)
end
end
@@ -1185,7 +1067,7 @@ public
end
idx = 0
cols = 0
- parsed = CSV::Row.new
+ parsed = Array.new
parsedCols = 0
begin
cols, idx = CSV.parse_row(buf, idx, parsed)
@@ -1193,7 +1075,7 @@ public
end while cols > 0
assert_equal(toBe.size, parsedCols)
assert_equal(toBe.size, parsed.size)
- assert(parsed.match(toBe))
+ assert_equal(toBe, parsed)
buf = ''
toBe = []
@@ -1203,15 +1085,15 @@ public
end
idx = 0
cols = 0
- parsed = CSV::Row.new
+ parsed = Array.new
parsedCols = 0
begin
- cols, idx = CSV.parse_row(buf, idx, parsed)
+ cols, idx = CSV.parse_row(buf, idx, parsed, ?,, ?\n)
parsedCols += cols
end while cols > 0
assert_equal(toBe.size, parsedCols)
assert_equal(toBe.size, parsed.size)
- assert(parsed.match(toBe))
+ assert_equal(toBe, parsed)
buf = ''
toBe = []
@@ -1223,15 +1105,15 @@ public
end
idx = 0
cols = 0
- parsed = CSV::Row.new
+ parsed = Array.new
parsedCols = 0
begin
- cols, idx = CSV.parse_row(buf, idx, parsed)
+ cols, idx = CSV.parse_row(buf, idx, parsed, ?,, ?\n)
parsedCols += cols
end while cols > 0
assert_equal(toBe.size, parsedCols)
assert_equal(toBe.size, parsed.size)
- assert(parsed.match(toBe))
+ assert_equal(toBe, parsed)
buf = ''
toBe = []
@@ -1241,7 +1123,7 @@ public
end
idx = 0
cols = 0
- parsed = CSV::Row.new
+ parsed = []
parsedCols = 0
begin
cols, idx = CSV.parse_row(buf, idx, parsed, ?,, ?|)
@@ -1249,7 +1131,7 @@ public
end while cols > 0
assert_equal(toBe.size, parsedCols)
assert_equal(toBe.size, parsed.size)
- assert(parsed.match(toBe))
+ assert_equal(toBe, parsed)
end
def test_utf8
@@ -1278,26 +1160,34 @@ public
rows = []
assert_raises(CSV::IllegalFormatError) do
CSV.open(@macfile, "r") do |row|
- rows << row.to_a
+ rows << row.to_a
end
+ assert_equal([["Avenches", "aus Umgebung\r\"Bad Hersfeld", "Ausgrabung"]], rows)
end
rows = []
file = File.open(@macfile)
- CSV::Reader.parse(file, ?,, ?\r) do |row|
- rows << row.to_a
+ begin
+ CSV::Reader.parse(file, ?,, ?\r) do |row|
+ rows << row.to_a
+ end
+ assert_equal([["Avenches", "aus Umgebung"], ["Bad Hersfeld", "Ausgrabung"]], rows)
+ ensure
+ file.close
end
- assert_equal([["Avenches", "aus Umgebung"], ["Bad Hersfeld", "Ausgrabung"]], rows)
- file.close
rows = []
file = File.open(@macfile)
- assert_raises(CSV::IllegalFormatError) do
- CSV::Reader.parse(file, ?,) do |row|
- rows << row.to_a
+ begin
+ assert_raises(CSV::IllegalFormatError) do
+ CSV::Reader.parse(file, ?,) do |row|
+ rows << row.to_a
+ end
+ assert_equal([["Avenches", "aus Umgebung\r\"Bad Hersfeld", "Ausgrabung"]], rows)
end
+ ensure
+ file.close
end
- file.close
end
@@ -1678,8 +1568,8 @@ public
#
def test_s_parseAndCreate
colSize = 8
- csvStr = "foo,!!!foo!!!,!foo,bar!,!!!!!!,!!,,!\r!,!\r\n!\r\nNaHi,!!!Na!!!,!Na,Hi!,!\r.\n!,!\r\n\n!,!!!!,!\n!,!\r\n!".gsub!('!', '"')
- csvStrTerminated = csvStr + "\r\n"
+ csvStr = "foo,!!!foo!!!,!foo,bar!,!!!!!!,!!,,!\r!,!\r\n!\nNaHi,!!!Na!!!,!Na,Hi!,!\r.\n!,!\r\n\n!,!!!!,!\n!,!\r\n!".gsub!('!', '"')
+ csvStrTerminated = csvStr + "\n"
myStr = csvStr.dup
res1 = []; res2 = []
@@ -1708,19 +1598,156 @@ public
buf = ''
CSV::Writer.generate(buf) do |writer|
parsed.each do |row|
- writer << row.collect { |e| e.is_null ? nil : e.data }
+ writer << row
end
end
assert_equal(csvStrTerminated, buf)
end
-end
+ def test_writer_fs_rs_generate
+ buf = ''
+ CSV::Writer.generate(buf, ",,") do |writer|
+ writer << []
+ end
+ assert_equal("\n", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, ",,") do |writer|
+ writer << [] << []
+ end
+ assert_equal("\n\n", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, ",,") do |writer|
+ writer << [1]
+ end
+ assert_equal("1\n", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, ",,") do |writer|
+ writer << [1, 2, 3]
+ writer << [4, ",,", 5]
+ end
+ assert_equal("1,,2,,3\n4,,\",,\",,5\n", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, ",,:", ",,;") do |writer|
+ writer << [nil, nil, nil]
+ writer << [nil, ",,", nil]
+ end
+ assert_equal(",,:,,:,,;,,:,,,,:,,;", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, "---") do |writer|
+ writer << [1, 2, 3]
+ writer << [4, "---\"---", 5]
+ end
+ assert_equal("1---2---3\n4---\"---\"\"---\"---5\n", buf)
+
+ buf = ''
+ CSV::Writer.generate(buf, nil) do |writer|
+ writer << [1, 2, 3]
+ writer << [4, ",\",", 5]
+ end
+ assert_equal("1,2,3\n4,\",\"\",\",5\n", buf)
+ end
+
+ def test_writer_fs_rs_parse
+ reader = CSV::Reader.create('a||b--c||d', '||', '--')
+ assert_equal(['a', 'b'], reader.shift)
+ assert_equal(['c', 'd'], reader.shift)
+
+ reader = CSV::Reader.create("a@|b@-c@|d", "@|", "@-")
+ assert_equal(['a', 'b'], reader.shift)
+ assert_equal(['c', 'd'], reader.shift)
+
+ reader = CSV::Reader.create("ababfsababrs", "abfs", "abrs")
+ assert_equal(['ab', 'ab'], reader.shift)
+
+ reader = CSV::Reader.create('"ab"abfsababrs', "abfs", "abrs")
+ assert_equal(['ab', 'ab'], reader.shift)
+
+ reader = CSV::Reader.create('"ab"aabfsababrs', "abfs", "abrs")
+ assert_raises(CSV::IllegalFormatError) do
+ reader.shift
+ end
+
+ # fs match while matching rs progress
+ reader = CSV::Reader.create("ab,ababrs", nil, "abrs")
+ assert_equal(['ab', 'ab'], reader.shift)
+
+ reader = CSV::Reader.create(',ababrs', nil, "abrs")
+ assert_equal([nil, 'ab'], reader.shift)
-if $0 == __FILE__
- suite = Test::Unit::TestSuite.new('CSV')
- ObjectSpace.each_object(Class) do |klass|
- suite << klass.suite if (Test::Unit::TestCase > klass)
+ reader = CSV::Reader.create('"",ababrs', nil, "abrs")
+ assert_equal(['', 'ab'], reader.shift)
+
+ reader = CSV::Reader.create('ab,"ab"abrs', nil, "abrs")
+ assert_equal(['ab', 'ab'], reader.shift)
+
+ reader = CSV::Reader.create('ab,"ab"aabrs', nil, "abrs")
+ assert_raises(CSV::IllegalFormatError) do
+ reader.shift
+ end
+
+ # rs match while matching fs progress
+ reader = CSV::Reader.create("ab|abc", 'ab-', "ab|")
+ assert_equal([nil], reader.shift)
+ assert_equal(['abc'], reader.shift)
+
+ reader = CSV::Reader.create("ab\ncdabcef", "abc", "\n")
+ assert_equal(['ab'], reader.shift)
+ assert_equal(['cd', "ef"], reader.shift)
+
+ # EOF while fs/rs matching
+ reader = CSV::Reader.create("ab", 'ab-', "xyz")
+ assert_equal(['ab'], reader.shift)
+
+ reader = CSV::Reader.create("ab", 'xyz', "ab|")
+ assert_equal(['ab'], reader.shift)
+
+ reader = CSV::Reader.create("ab", 'ab-', "ab|")
+ assert_equal(['ab'], reader.shift)
+
+ reader = CSV::Reader.create(",,:,,:,,;,,:,,,,:,,;", ",,:", ",,;")
+ assert_equal([nil, nil, nil], reader.shift)
+ assert_equal([nil, ",,", nil], reader.shift)
+ end
+
+ def test_s_foreach
+ File.open(@outfile, "w") do |f|
+ f << "1,2,3\n4,5,6"
+ end
+ row = []
+ CSV.foreach(@outfile) { |line|
+ row << line
+ }
+ assert_equal([['1', '2', '3'], ['4', '5', '6']], row)
+
+ File.open(@outfile, "w") do |f|
+ f << "1,2,3\r4,5,6"
+ end
+ row = []
+ CSV.foreach(@outfile, "\r") { |line|
+ row << line
+ }
+ assert_equal([['1', '2', '3'], ['4', '5', '6']], row)
+ end
+
+ def test_s_readlines
+ File.open(@outfile, "w") do |f|
+ f << "1,2,3\n4,5,6"
+ end
+ assert_equal([["1", "2", "3"], ["4", "5", "6"]], CSV.readlines(@outfile))
+ assert_equal([["1", "2", nil], [nil, "5", "6"]], CSV.readlines(@outfile, "3\n4"))
+ end
+
+ def test_s_read
+ File.open(@outfile, "w") do |f|
+ f << "1,2,3\n4,5,6"
+ end
+ assert_equal([["1", "2", "3"], ["4", "5", "6"]], CSV.read(@outfile))
+ assert_equal([["1", "2"]], CSV.read(@outfile, 3))
+ assert_equal([[nil], ["4", nil]], CSV.read(@outfile, 3, 5))
end
- require 'test/unit/ui/console/testrunner'
- Test::Unit::UI::Console::TestRunner.run(suite).passed?
end
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 568c56181a..92c2062948 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -51,4 +51,22 @@ class TestFloat < Test::Unit::TestCase
b = 100000000000000000000000.0
assert_equal(a == b, b == a)
end
+
+ def test_strtod
+ a = Float("0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("+0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("-0.0")
+ assert(a.abs < Float::EPSILON)
+ a = Float("0." + "00" * Float::DIG + "1")
+ assert(a != 0.0)
+ a = Float("+0." + "00" * Float::DIG + "1")
+ assert(a != 0.0)
+ a = Float("-0." + "00" * Float::DIG + "1")
+ assert(a != 0.0)
+ # add expected behaviour here.
+ end
end