File Coverage

blib/lib/AnyData/Format/CSV.pm
Criterion Covered Total %
statement 50 51 98.0
branch 10 14 71.4
condition 16 29 55.1
subroutine 7 7 100.0
pod 0 3 0.0
total 83 104 79.8


line stmt bran cond sub pod time code
1             #########################################################
2             package AnyData::Format::CSV;
3             #########################################################
4             # copyright (c) 2000, Jeff Zucker
5             #########################################################
6              
7             =head1 NAME
8              
9             AnyData::Format::CSV - tiedhash & DBI/SQL access to CSV data
10              
11             =head1 SYNOPSIS
12              
13             use AnyData;
14             my $table = adTable( 'CSV', $filename,'r',$flags );
15             while (my $row = each %$table) {
16             print $row->{name},"\n" if $row->{country} =~ /us|mx|ca/;
17             }
18             # ... other tied hash operations
19              
20             OR
21              
22             use DBI
23             my $dbh = DBI->connect('dbi:AnyData:');
24             $dbh->func('table1','CSV', $filename,$flags,'ad_catalog');
25             my $hits = $dbh->selectall_arrayref( qq{
26             SELECT name FROM table1 WHERE country = 'us'
27             });
28             # ... other DBI/SQL operations
29              
30             =head1 DESCRIPTION
31              
32             This is a plug-in format parser for the AnyData and DBD::AnyData modules. It will read column names from the first row of the file, or accept names passed by the user. In addition to column names, the user may set other options as follows:
33              
34             col_names : a comma separated list of column names
35             eol : the end of record mark, \n by default
36             quote_char : the character used to quote fields " by default
37             escape_char : the character used to escape the quote char, " by default
38              
39             If you are using this with DBD::AnyData, put ad_ in front of the flags, e.g.
40             ad_eol.
41              
42             Please refer to the documentation for AnyData.pm and DBD::AnyData.pm
43             for further details.
44              
45             =head1 AUTHOR & COPYRIGHT
46              
47             copyright 2000, Jeff Zucker
48             all rights reserved
49              
50              
51             =cut
52              
53              
54 3     3   26 use strict;
  3         4  
  3         102  
55 3     3   16 use warnings;
  3         4  
  3         131  
56 3     3   1320 use AnyData::Format::Base;
  3         8  
  3         99  
57 3     3   16 use vars qw( @ISA $VERSION);
  3         6  
  3         2139  
58             @AnyData::Format::CSV::ISA = qw( AnyData::Format::Base );
59              
60             $VERSION = '0.05';
61              
62             sub new {
63 7     7 0 12 my $class = shift;
64 7   50     19 my $self = shift || {};
65 7   100     44 my $s = ${self}->{field_rsep} || ${self}->{field_sep} || q(,);
66 7         10 my $s1 = $s;
67             #$s1 =~ s/\\/\\\\/ if $s1 =~ /\+$/;
68             #$s1 =~ s/\+$//;
69             #die $s1;
70 7   100     25 ${self}->{field_sep} ||= q(,);
71 7   50     27 my $q = ${self}->{quote} ||= q(");
72 7   50     28 my $e = ${self}->{escape} ||= q(");
73 7   100     32 ${self}->{record_sep} ||= qq(\n);
74             $self->{regex} = [
75 7         349 qr/$q((?:(?:$e$q)|[^$q])*)$q$s?|([^$s1]+)$s?|$s/,
76             "$e$q",
77             $q
78             ];
79 7         35 return bless $self, $class;
80             }
81              
82             sub read_fields {
83 38     38 0 34 my $self = shift;
84 38   50     66 my $str = shift || return undef;
85 38         45 my @fields = ();
86 38         34 my $captured;
87 38   33     93 my $field_wsep = $self->{field_wsep} || $self->{field_sep};
88 38 50       64 if ($self->{trim}) {
89 0         0 $str =~ s/\s*($field_wsep)\s*/$1/g;
90             }
91 38         223 while ($str =~ m#$self->{regex}->[0]#g) {
92 96         137 $captured = $+;
93 96 100       238 $captured =~ s/$self->{regex}[1]/$self->{regex}[2]/g if $captured;
94 96 50 66     319 last if $captured && $captured eq "\n";
95 96         430 push(@fields,$captured);
96             };
97 38 100       84 push(@fields, undef) if substr($str,-1,1) eq $field_wsep;
98 38         174 return @fields;
99             }
100              
101             sub write_fields {
102 24     24 0 21 my $self = shift;
103 24         45 my @fields = @_;
104 24         23 my $str = '';
105 24   33     69 my $field_rsep = $self->{field_rsep} || $self->{field_sep};
106 24         31 $field_rsep = quotemeta($field_rsep);
107 24         27 my $field_wsep = $self->{field_sep};
108 24         45 $field_wsep =~ s/\\//g;
109             # if ($self->{ChopBlanks}) {
110             # $field_wsep =~ " $field_wsep ";
111             # }
112 24         40 for (@fields) {
113 72 50       114 $_ = '' if !defined $_;
114 72 100       117 if ($self->{field_sep} eq ',') {
115 36         39 s/"/""/g;
116 36 50 33     242 s/^(.*)$/"$1"/s if /,/ or /\n/s or /"/;
      33        
117             }
118 72         116 $str .= $_ . $field_wsep;
119             }
120 24         214 $str =~ s/$self->{field_sep}$/$self->{record_sep}/;
121 24         124 return $str;
122             }
123             1;
124              
125              
126