diff options
Diffstat (limited to 'lib/csv/fields_converter.rb')
-rw-r--r-- | lib/csv/fields_converter.rb | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb new file mode 100644 index 0000000000..c2fa5798ff --- /dev/null +++ b/lib/csv/fields_converter.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +class CSV + class FieldsConverter + include Enumerable + + def initialize(options={}) + @converters = [] + @nil_value = options[:nil_value] + @empty_value = options[:empty_value] + @empty_value_is_empty_string = (@empty_value == "") + @accept_nil = options[:accept_nil] + @builtin_converters = options[:builtin_converters] + @need_static_convert = need_static_convert? + end + + def add_converter(name=nil, &converter) + if name.nil? # custom converter + @converters << converter + else # named converter + combo = @builtin_converters[name] + case combo + when Array # combo converter + combo.each do |sub_name| + add_converter(sub_name) + end + else # individual named converter + @converters << combo + end + end + end + + def each(&block) + @converters.each(&block) + end + + def empty? + @converters.empty? + end + + def convert(fields, headers, lineno) + return fields unless need_convert? + + fields.collect.with_index do |field, index| + if field.nil? + field = @nil_value + elsif field.empty? + field = @empty_value unless @empty_value_is_empty_string + end + @converters.each do |converter| + break if field.nil? and @accept_nil + if converter.arity == 1 # straight field converter + field = converter[field] + else # FieldInfo converter + if headers + header = headers[index] + else + header = nil + end + field = converter[field, FieldInfo.new(index, lineno, header)] + end + break unless field.is_a?(String) # short-circuit pipeline for speed + end + field # final state of each field, converted or original + end + end + + private + def need_static_convert? + not (@nil_value.nil? and @empty_value_is_empty_string) + end + + def need_convert? + @need_static_convert or + (not @converters.empty?) + end + end +end |