shift()
public
The primary read method for wrapped Strings
and IOs, a single row is pulled from the data source, parsed and returned
as an Array of fields (if header rows are not
used) or a CSV::Row (when header rows are
used).
The data source must be open for
reading.
Show source
def shift
if header_row? and @return_headers and
[Array, String].include? @use_headers.class
if @unconverted_fields
return add_unconverted_fields(parse_headers, Array.new)
else
return parse_headers
end
end
in_extended_col = false
csv = Array.new
loop do
unless parse = @io.gets(@row_sep)
return nil
end
parse.sub!(@parsers[:line_end], "")
if csv.empty?
if parse.empty?
@lineno += 1
if @skip_blanks
next
elsif @unconverted_fields
return add_unconverted_fields(Array.new, Array.new)
elsif @use_headers
return self.class::Row.new(Array.new, Array.new)
else
return Array.new
end
end
end
next if @skip_lines and @skip_lines.match parse
parts = parse.split(@col_sep, -1)
if parts.empty?
if in_extended_col
csv[-1] << @col_sep
else
csv << nil
end
end
parts.each do |part|
if in_extended_col
if part[-1] == @quote_char && part.count(@quote_char) % 2 != 0
csv.last << part[0..-2]
if csv.last =~ @parsers[:stray_quote]
raise MalformedCSVError,
"Missing or stray quote in line #{lineno + 1}"
end
csv.last.gsub!(@quote_char * 2, @quote_char)
in_extended_col = false
else
csv.last << part
csv.last << @col_sep
end
elsif part[0] == @quote_char
if part[-1] != @quote_char || part.count(@quote_char) % 2 != 0
csv << part[1..-1]
csv.last << @col_sep
in_extended_col = true
else
csv << part[1..-2]
if csv.last =~ @parsers[:stray_quote]
raise MalformedCSVError,
"Missing or stray quote in line #{lineno + 1}"
end
csv.last.gsub!(@quote_char * 2, @quote_char)
end
elsif part =~ @parsers[:quote_or_nl]
if part =~ @parsers[:nl_or_lf]
raise MalformedCSVError, "Unquoted fields do not allow " +
"\\r or \\n (line #{lineno + 1})."
else
raise MalformedCSVError, "Illegal quoting in line #{lineno + 1}."
end
else
csv << (part.empty? ? nil : part)
end
end
csv[-1][-1] = @row_sep if in_extended_col
if in_extended_col
if @io.eof?
raise MalformedCSVError,
"Unclosed quoted field on line #{lineno + 1}."
elsif @field_size_limit and csv.last.size >= @field_size_limit
raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
end
else
@lineno += 1
unconverted = csv.dup if @unconverted_fields
csv = convert_fields(csv) unless @use_headers or @converters.empty?
csv = parse_headers(csv) if @use_headers
if @unconverted_fields and not csv.respond_to? :unconverted_fields
add_unconverted_fields(csv, unconverted)
end
break csv
end
end
end