lib/rio/ext/csv.rb in rio-0.4.2 vs lib/rio/ext/csv.rb in rio-0.5.1
- old
+ new
@@ -1,8 +1,8 @@
#--
-# ===============================================================================
-# Copyright (c) 2005,2006,2007,2008 Christopher Kleckner
+# ===========================================================================
+# Copyright (c) 2005-2012 Christopher Kleckner
# All rights reserved
#
# This file is part of the Rio library for ruby.
#
# Rio is free software; you can redistribute it and/or modify
@@ -16,24 +16,13 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Rio; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-# ===============================================================================
+# ===========================================================================
#++
#
-# To create the documentation for Rio run the command
-# ruby build_doc.rb
-# from the distribution directory.
-#
-# Suggested Reading
-# * RIO::Doc::SYNOPSIS
-# * RIO::Doc::INTRO
-# * RIO::Doc::HOWTO
-# * RIO::Doc::EXAMPLES
-# * RIO::Rio
-#
# begin
# require 'faster_csv' # first choice--for speed
@@ -51,301 +40,33 @@
# end
# rescue LoadError
# require 'csv' # second choice--slower but standard
# end
-require 'csv'
-
-$EXTEND_CSV_RESULTS = false
-module RIO
- module Ext
- module CSV
- module Cx
- def csv(fs=',',rs=nil,&block)
- cx['csv_fs'] = fs
- cx['csv_rs'] = rs
- cxx('csv',true,&block)
- end
- def csv?() cxx?('csv') end
- def csv_(fs=',',rs=nil)
- cx['csv_fs'] = fs
- cx['csv_rs'] = rs
- cxx_('csv',true)
- end
- protected :csv_
- def columns(*ranges,&block)
- if skipping?
- cx['skipping'] = false
- skipcolumns(*args,&block)
- else
- @cnames = nil
- cx['col_args'] = ranges.flatten
- cxx('columns',true,&block)
- end
- end
- def skipcolumns(*ranges,&block)
- @cnames = nil
- cx['nocol_args'] = ranges.flatten
- cxx('columns',true,&block)
- end
- def columns?()
- cxx?('columns')
- end
+$USE_FASTER_CSV = false
+if RUBY_VERSION[0,3] >= '1.9'
+ require 'csv'
+ require 'rio/ext/csv/csv'
+ $USE_FASTER_CSV = true
+ # p 'FASTER CSV 1.9'
+else
+ begin
+ CSV.const_defined?('Reader')
+ require 'rio/ext/csv/csv-legacy'
+ # p 'LEGACY CSV'
+ rescue NameError
+ begin
+ require 'faster_csv'
+ class CSV < ::FasterCSV
end
+ require 'rio/ext/csv/csv'
+ $USE_FASTER_CSV = true
+ # p 'FASTER CSV'
+ rescue LoadError
+ require 'csv'
+ require 'rio/ext/csv/csv-legacy'
+ # p 'LEGACY CSV'
end
end
end
-module RIO
- module Ext
- module CSV
- module Ary
- attr_accessor :csv_rec_to_s
- def to_s()
- @csv_rec_to_s.call(self)
- end
- end
- module Str
- attr_accessor :csv_s_to_rec
- def to_a()
- @csv_s_to_rec.call(self)
- end
- end
- end
- end
-end
-
-module RIO
- module Ext
- module CSV
- module Input
-
- protected
-# def ior()
-# p cx['stream_itertype']
-# case cx['stream_itertype']
-# when 'lines',nil
-# self.ioh.iostack[-2]
-# else
-# self.ioh
-# end
-# end
-# def each_rec_(&block)
-# self.ior.each { |line|
-# yield line
-# }
-# self
-# end
-
- def to_rec_(raw_rec)
- #_init_cols_from_line(raw_rec) if @recno == 0
- #p "#{callstr('to_rec_',raw_rec.inspect,@recno)} ; itertype=#{cx['stream_itertype']}"
- case cx['stream_itertype']
- when 'lines'
- if $EXTEND_CSV_RESULTS
- unless copying_from?
- raw_rec.extend(RIO::Ext::CSV::Str)
- raw_rec.csv_s_to_rec = _s_to_rec_proc(cx['csv_fs'],cx['csv_rs'])
- end
- end
- raw_rec
- when 'records'
- _l2record(raw_rec,cx['csv_fs'],cx['csv_rs'])
- when 'rows'
- _l2row(raw_rec,cx['csv_fs'],cx['csv_rs'])
- else
- _l2record(raw_rec,cx['csv_fs'],cx['csv_rs'])
- end
- end
-
- private
-
- def trim(fields)
- ycols = cx['col_args']
- ncols = cx['nocol_args']
- return [] if ncols and ncols.empty?
- if ycols.nil? and ncols.nil?
- return fields
- end
- ncols = [] if ncols.nil?
- ycols = [(0...fields.size)] if ycols.nil? or ycols.empty?
- cols = []
- fields.each_index { |i|
- yes = nil
- no = nil
- ycols.each { |yc|
- if yc === i
- yes = true
- break
- end
- }
- ncols.each { |nc|
- if nc === i
- no = true
- break
- end
- }
-
- cols << i if yes and !no
- }
- tfields = []
- cols.each do |i|
- tfields << fields[i]
- end
- tfields
- end
- def parse_line_(line,fs,rs)
- ::CSV.parse_line(line,fs,rs)
- end
- def _l2a(line,fs,rs)
- parse_line_(line,fs,rs)
- end
- def _l2record(line,fs,rs)
- #p callstr('_l2record',line,fs,rs,cols)
- fields = trim(parse_line_(line,fs,rs))
- if $EXTEND_CSV_RESULTS
- unless copying_from?
- fields.extend(RIO::Ext::CSV::Ary)
- fields.csv_rec_to_s = _rec_to_s_proc(fs,rs)
- end
- end
-# p "csv#fields: #{fields}"
-# fields.each do |f|
-# p f
-# end
- fields.map{ |f| f.to_s }
- end
- def cnames(num)
- @cnames ||= trim((0...num).map { |n| "Col#{n}" })
- end
-
- def _l2row(line,fs,rs)
- dat = _l2a(line,fs,rs)
- names = cnames(dat.length)
- dat = trim(dat)
- rw = {}
- (0...names.length).each { |i|
- rw[names[i]] = dat[i]
- }
- rw
- end
-
- def _rec_to_s_proc(fs,rs)
- proc { |a|
- ::CSV.generate_line(a,fs,rs)
- }
- end
-
- def _s_to_rec_proc(fs,rs)
- proc { |s|
- ::CSV.parse_line(s,fs,rs)
- }
- end
-
- def _init_cols_from_line(line)
- ary = _l2record(line,cx['csv_fs'],cx['csv_rs'])
- _init_cols_from_ary(ary)
- end
-
- def _init_cols_from_num(num)
- fake_rec = (0...num).map { |n| "Column#{num}" }
- _init_cols_from_ary(fake_rec)
- end
- def _init_cols_from_hash(hash)
- _init_cols_from_ary(hash.keys)
- end
- def _init_cols_from_ary(ary)
- #p callstr('_init_cols_from_ary',ary)
- if columns?
- cx['col_names'] = []
- cx['col_nums'] = []
-
- ary.each_with_index do |cname,idx|
- cx['col_args'].each do |arg|
- if arg === ( arg.kind_of?(::Regexp) || arg.kind_of?(::String) ? cname : idx )
- cx['col_names'] << cname
- cx['col_nums'] << idx
- end
- end
- end
- else
- cx['col_names'] = ary
- end
- cx.values_at('col_nums','col_names')
- end
-
- end
- end
-
- module CSV
- module Output
-
- public
-
- def putrow(*argv)
- require 'csv'
- row = ( argv.length == 1 && argv[0].kind_of?(::Array) ? argv[0] : argv )
- self.puts(::CSV.generate_line(row,self.cx['csv_fs'],self.cx['csv_rs']))
- end
- def putrow!(*argv)
- putrow(*argv)
- close
- end
-
- protected
-
- def put_(arg,fs=cx['csv_fs'],rs=cx['csv_rs'])
- #p callstr('put_',arg.inspect,fs,rs)
- @header_line ||= _to_header_line(arg,fs,rs)
- puts(_to_line(arg,fs,rs))
- end
-
- def cpfrom_array_(ary)
- #p callstr('copy_from_array',ary.inspect)
- if ary.empty?
- super
- else
- if ary[0].kind_of? ::Array
- super
- else
- put_(ary)
- end
- end
- end
-
- private
-
- def _to_header_line(arg,fs=cx['csv_fs'],rs=nil)
- case arg
- when ::String
- arg
- when ::Array
- _ary_to_line(arg,fs,rs)
- when ::Hash
- _ary_to_line(arg.keys,fs,rs)
- else
- arg.to_s
- end
- end
-
- def _to_line(arg,fs=cx['csv_fs'],rs=cx['csv_rs'])
- #p callstr('_to_line',arg.inspect,fs,rs)
- case arg
- when ::Array
- _ary_to_line(arg,fs,rs)
- when ::Hash
- _ary_to_line(arg.values,fs,rs)
- else
- arg
- end
- end
-
- def _ary_to_line(ary,fs,rs)
- rs ||= $/
- ::CSV.generate_line(ary,fs,rs)
- end
- public
- end
- end
- end
-end
__END__