method
shift
v1_9_1_378 -
Show latest stable
- Class:
CSV
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.
# File lib/csv.rb, line 1785
def shift
#########################################################################
### This method is purposefully kept a bit long as simple conditional ###
### checks are faster than numerous (expensive) method calls. ###
#########################################################################
# handle headers not based on document content
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
# begin with a blank line, so we can always add to it
line = ""
#
# it can take multiple calls to <tt>@io.gets()</tt> to get a full line,
# because of \r and/or \n characters embedded in quoted fields
#
loop do
# add another read to the line
(line += @io.gets(@row_sep)) rescue return nil
# copy the line so we can chop it up in parsing
parse = line.dup
parse.sub!(@parsers[:line_end], "")
#
# I believe a blank line should be an <tt>Array.new</tt>, not Ruby 1.8
# CSV's <tt>[nil]</tt>
#
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 self.class::Row.new(Array.new, Array.new)
else
return Array.new
end
end
#
# shave leading empty fields if needed, because the main parser chokes
# on these
#
csv = if parse.sub!(@parsers[:leading_fields], "")
[nil] * ($&.length / @col_sep.length)
else
Array.new
end
#
# then parse the main fields with a hyper-tuned Regexp from
# Mastering Regular Expressions, Second Edition
#
parse.gsub!(@parsers[:csv_row]) do
csv << if $1.nil? # we found an unquoted field
if $2.empty? # switch empty unquoted fields to +nil+...
nil # for Ruby 1.8 CSV compatibility
else
# I decided to take a strict approach to CSV parsing...
if $2.count(@parsers[:return_newline]).zero? # verify correctness
$2
else
# or throw an Exception
raise MalformedCSVError, "Unquoted fields do not allow " +
"\\r or \\n (line #{lineno + 1})."
end
end
else # we found a quoted field...
$1.gsub(@quote_char * 2, @quote_char) # unescape contents
end
"" # gsub!'s replacement, clear the field
end
# if parse is empty?(), we found all the fields on the line...
if parse.empty?
@lineno += 1
# save fields unconverted fields, if needed...
unconverted = csv.dup if @unconverted_fields
# convert fields, if needed...
csv = convert_fields(csv) unless @use_headers or @converters.empty?
# parse out header rows and handle CSV::Row conversions...
csv = parse_headers(csv) if @use_headers
# inject unconverted fields and accessor, if requested...
if @unconverted_fields and not csv.respond_to? :unconverted_fields
add_unconverted_fields(csv, unconverted)
end
# return the results
break csv
end
# if we're not empty?() but at eof?(), a quoted field wasn't closed...
if @io.eof?
raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}."
elsif parse =~ @parsers[:bad_field]
raise MalformedCSVError, "Illegal quoting on line #{lineno + 1}."
elsif @field_size_limit and parse.length >= @field_size_limit
raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
end
# otherwise, we need to loop and pull some more data to complete the row
end
end Related methods
- Instance methods
- <<
- add_row
- convert
- converters
- each
- force_quotes?
- gets
- header_convert
- header_converters
- header_row?
- headers
- inspect
- puts
- read
- readline
- readlines
- return_headers?
- rewind
- shift
- skip_blanks?
- unconverted_fields?
- write_headers?
- Class methods
- dump
- filter
- foreach
- generate
- generate_line
- instance
- load
- new
- open
- parse
- parse_line
- read
- readlines
- table
- Private methods
-
add_converter -
add_unconverted_fields -
convert_fields -
encode_re -
encode_str -
escape_re -
init_converters -
init_headers -
init_parsers -
init_separators -
parse_headers -
raw_encoding -
read_io -
read_to_char