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
line = String.new
loop do
if read_line = @io.gets(@row_sep)
line += read_line
else
return nil
end
parse = line.dup
parse.sub!(@parsers[:line_end], "")
if parse.empty?
@lineno += 1
if @skip_blanks
line = ""
next
elsif @unconverted_fields
return add_unconverted_fields(Array.new, Array.new)
elsif @use_headers
return FasterCSV::Row.new(Array.new, Array.new)
else
return Array.new
end
end
csv = Array.new
current_field = String.new
field_quotes = 0
parse.split(@col_sep, -1).each do |match|
if current_field.empty? && match.count(@quote_and_newlines).zero?
csv << (match.empty? ? nil : match)
elsif (current_field.empty? ? match[0] : current_field[0]) ==
@quote_char[0]
current_field << match
field_quotes += match.count(@quote_char)
if field_quotes % 2 == 0
in_quotes = current_field[@parsers[:quoted_field], 1]
if !in_quotes || in_quotes[@parsers[:stray_quote]]
raise MalformedCSVError,
"Missing or stray quote in line #{lineno + 1}"
end
current_field = in_quotes
current_field.gsub!(@quote_char * 2, @quote_char)
csv << current_field
current_field = String.new
field_quotes = 0
else
current_field << @col_sep
end
elsif match.count("\r\n").zero?
raise MalformedCSVError, "Illegal quoting in line #{lineno + 1}."
else
raise MalformedCSVError, "Unquoted fields do not allow " +
"\\r or \\n (line #{lineno + 1})."
end
end
if field_quotes % 2 == 0
@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
if @io.eof?
raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}."
elsif @field_size_limit and current_field.size >= @field_size_limit
raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
end
end
end