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   18 use strict;
  3         6  
  3         110  
55 3     3   16 use warnings;
  3         5  
  3         98  
56 3     3   1593 use AnyData::Format::Base;
  3         10  
  3         83  
57 3     3   19 use vars qw( @ISA $VERSION);
  3         5  
  3         2173  
58             @AnyData::Format::CSV::ISA = qw( AnyData::Format::Base );
59              
60             $VERSION = '0.05';
61              
62             sub new {
63 7     7 0 14 my $class = shift;
64 7   50     24 my $self = shift || {};
65 7   100     57 my $s = ${self}->{field_rsep} || ${self}->{field_sep} || q(,);
66 7         11 my $s1 = $s;
67             #$s1 =~ s/\\/\\\\/ if $s1 =~ /\+$/;
68             #$s1 =~ s/\+$//;
69             #die $s1;
70 7   100     32 ${self}->{field_sep} ||= q(,);
71 7   50     31 my $q = ${self}->{quote} ||= q(");
72 7   50     30 my $e = ${self}->{escape} ||= q(");
73 7   100     77 ${self}->{record_sep} ||= qq(\n);
74 7         362 $self->{regex} = [
75             qr/$q((?:(?:$e$q)|[^$q])*)$q$s?|([^$s1]+)$s?|$s/,
76             "$e$q",
77             $q
78             ];
79 7         50 return bless $self, $class;
80             }
81              
82             sub read_fields {
83 38     38 0 47 my $self = shift;
84 38   50     82 my $str = shift || return undef;
85 38         52 my @fields = ();
86 38         36 my $captured;
87 38   33     149 my $field_wsep = $self->{field_wsep} || $self->{field_sep};
88 38 50       85 if ($self->{trim}) {
89 0         0 $str =~ s/\s*($field_wsep)\s*/$1/g;
90             }
91 38         245 while ($str =~ m#$self->{regex}->[0]#g) {
92 96         171 $captured = $+;
93 96 100       275 $captured =~ s/$self->{regex}[1]/$self->{regex}[2]/g if $captured;
94 96 50 66     382 last if $captured && $captured eq "\n";
95 96         515 push(@fields,$captured);
96             };
97 38 100       101 push(@fields, undef) if substr($str,-1,1) eq $field_wsep;
98 38         189 return @fields;
99             }
100              
101             sub write_fields {
102 24     24 0 26 my $self = shift;
103 24         55 my @fields = @_;
104 24         32 my $str = '';
105 24   33     95 my $field_rsep = $self->{field_rsep} || $self->{field_sep};
106 24         32 $field_rsep = quotemeta($field_rsep);
107 24         29 my $field_wsep = $self->{field_sep};
108 24         43 $field_wsep =~ s/\\//g;
109             # if ($self->{ChopBlanks}) {
110             # $field_wsep =~ " $field_wsep ";
111             # }
112 24         38 for (@fields) {
113 72 50       122 $_ = '' if !defined $_;
114 72 100       147 if ($self->{field_sep} eq ',') {
115 36         40 s/"/""/g;
116 36 50 33     233 s/^(.*)$/"$1"/s if /,/ or /\n/s or /"/;
      33        
117             }
118 72         135 $str .= $_ . $field_wsep;
119             }
120 24         167 $str =~ s/$self->{field_sep}$/$self->{record_sep}/;
121 24         124 return $str;
122             }
123             1;
124              
125              
126