File Coverage

blib/lib/IO/CSVHeaderFile.pm
Criterion Covered Total %
statement 84 97 86.6
branch 35 56 62.5
condition 2 5 40.0
subroutine 11 11 100.0
pod 3 3 100.0
total 135 172 78.4


line stmt bran cond sub pod time code
1             package IO::CSVHeaderFile;
2             # $Id: CSVHeaderFile.pm,v 1.2 2007/07/06 08:44:46 vasek Exp $
3              
4 1     1   6189 use strict;
  1         2  
  1         33  
5 1     1   1426 use Text::CSV_XS;
  1         10836  
  1         66  
6 1     1   872 use IO::File;
  1         11750  
  1         169  
7 1     1   9 use vars qw(@ISA @EXPORT $VERSION);
  1         2  
  1         68  
8 1     1   6 use Exporter;
  1         2  
  1         35  
9 1     1   6 use Carp;
  1         2  
  1         1152  
10              
11             @ISA = qw(IO::File Exporter);
12              
13             @EXPORT = qw(
14            
15             );
16              
17             $VERSION = '0.04';
18              
19             my $SUPPORTED_XS_ARGS;
20              
21             sub open {
22 2     2 1 425 my $self = shift;
23 2 100       5 my $args = {}; $args = pop @_ if ref($_[$#_]) eq 'HASH';
  2         10  
24 2         6 _init_supported_xs_args();
25 2 50       9 my %xs_args = ( 'eol' => "\n", map {exists $SUPPORTED_XS_ARGS->{$_} ? ($_ => $args->{$_}):()} keys %$args);
  1         7  
26 2         11 my $csv = Text::CSV_XS->new(\%xs_args);
27 2         174 my $mode;
28 2 50       7 if(@_ > 1){
29 0 0       0 croak 'usage: $fh->open(FILENAME [ ,< > >> ][,CSVOPT])' if $_[2] =~ /^\d+$/;
30 0         0 $mode = IO::Handle::_open_mode_string($_[1]);
31             }else{
32 2         3 $mode = $_[0];
33 2 50       19 $mode =~ s/^(\+?<|>>?)(.*)$/$1/
34             or croak 'usage: $fh->open(FILENAME [,< > >> ][,CSVOPT])';
35             }
36 2         4 my ($fh, $firstline);
37 2 100       12 if($mode =~ /^<$/){
    50          
38 1 50       121 $fh = $self->SUPER::open( @_ ) or return;
39 1 50       47 unless($args->{noheader}){
40 1 50       46 unless( $firstline = $self->getline ){
41 0         0 $self->close;
42 0         0 return;
43             }
44 1 50 50     51 $csv->parse($firstline) and $args->{col} = [ $csv->fields ]
45             unless $args->{col};
46             }
47 1 50       70 unless(${*$self}{io_csvheaderfile_cols} = $args->{col}){
  1         7  
48 0         0 $self->close;
49 0         0 croak "IO::CSVHeaderFile: Can't find the column names in '$_[0]'";
50 0         0 return;
51             }
52             }elsif( $mode =~ /^>>?$/){
53 1 50       3 unless(${*$self}{io_csvheaderfile_cols} = $args->{col}){
  1         16  
54 0         0 $self->close;
55 0         0 croak "IO::CSVHeaderFile: Can't find the column names in '$_[0]'";
56 0         0 return;
57             }
58 1 50       10 $fh = $self->SUPER::open( @_ ) or return;
59 1 50 33 1   11 $csv->print($self, $args->{col})
  1         2  
  1         13  
  1         225  
60             unless $mode =~ /^>>$/ or $args->{noheader};
61             }else{
62 0         0 croak "IO::CSVHeaderFile: Invalid mode '$mode'";
63 0         0 return;
64             }
65 2         65 ${*$self}{io_csvheaderfile_csv} = $csv;
  2         7  
66 2         8 $fh
67             }
68              
69             sub csv_read{
70 3     3 1 69 my $self = shift;
71 3 50       79 my $line = $self->getline() or return;
72 3         90 my @result = ();
73 3 50       4 if( ${*$self}{io_csvheaderfile_csv}->parse($line) ){
  3         13  
74 3         55 my @cols = ${*$self}{io_csvheaderfile_csv}->fields;
  3         12  
75 3         23 my $colnames = ${*$self}{io_csvheaderfile_cols};
  3         7  
76 3 50       10 my $avail_cols = (@cols > @$colnames)? @$colnames : @cols;
77 3         8 for(my $i = 0; $i < $avail_cols; $i++){
78 9         30 push @result, $colnames->[$i] => $cols[$i];
79             }
80             }
81 3 100       20 wantarray? @result : { @result }
82             }
83              
84             sub csv_print{
85 3     3 1 37 my $self = shift;
86 3 50       11 return undef unless @_;
87 3         6 my $rec = $_[0];
88 3         4 my @columns = ();
89 3         4 my $colnames = ${*$self}{io_csvheaderfile_cols};
  3         7  
90 3 100       17 unless( ref $rec ){
    100          
    50          
91 1         10 my %map = ();
92 1         6 for(my $i = 0; $i < @$colnames; $i++){
93 3 100       11 $map{$colnames->[$i]} = [] unless exists $map{$colnames->[$i]};
94 3         4 push @{$map{$colnames->[$i]}}, $i;
  3         10  
95             }
96 1         7 while ( my ($key, $value) = splice(@_, 0, 2) ) {
97 4 50       581 my $idx = $map{$key} or next;
98 4         9 $columns[$idx->[0]] = $value;
99 4 100       21 shift @$idx if @$idx > 1;
100             }
101             }elsif( ref ($rec) eq 'HASH' ){
102 1         7 push( @columns, $rec->{$_}) foreach (@$colnames);
103             }elsif( ref ($rec) eq 'ARRAY' ){
104 1         5 for( my $i = 0; $i < @$colnames; $i++){
105 3         9 push @columns, $rec->[$i];
106             }
107             }
108 3         4 ${*$self}{io_csvheaderfile_csv}->print($self,\@columns);
  3         25  
109             }
110              
111             sub _init_supported_xs_args {
112 2 100   2   7 return if defined $SUPPORTED_XS_ARGS;
113 1         10 my $tmpcsvxs = Text::CSV_XS->new();
114 0           $SUPPORTED_XS_ARGS = UNIVERSAL::isa($tmpcsvxs, "HASH")?
115 1 50       135 {%$tmpcsvxs}: {map {$_ => undef} qw(eol sep_char allow_whitespace quote_char
116             allow_loose_quotes escape_char allow_loose_escapes binary types always_quote
117             keep_meta_info)};
118             }
119              
120             1;
121             __END__