File Coverage

blib/lib/TableDataRole/Source/CSVInFile.pm
Criterion Covered Total %
statement 59 62 95.1
branch 10 16 62.5
condition n/a
subroutine 13 14 92.8
pod 2 9 22.2
total 84 101 83.1


line stmt bran cond sub pod time code
1             package TableDataRole::Source::CSVInFile;
2              
3 6     6   2814 use 5.010001;
  6         23  
4 6     6   31 use strict;
  6         14  
  6         129  
5 6     6   28 use warnings;
  6         12  
  6         148  
6              
7 6     6   37 use Role::Tiny;
  6         25  
  6         29  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2023-02-24'; # DATE
11             our $DIST = 'TableDataRoles-Standard'; # DIST
12             our $VERSION = '0.015'; # VERSION
13              
14             with 'TableDataRole::Spec::Basic';
15              
16             sub new {
17 8     8 1 6275 require Text::CSV_XS;
18              
19 8         119921 my ($class, %args) = @_;
20              
21 8         19 my $fh;
22 8 100       47 if (defined(my $filename = delete $args{filename})) {
    50          
23 3 50       142 open $fh, "<", $filename
24             or die "Can't open file '$filename': $!";
25             } elsif (defined($fh = delete $args{filehandle})) {
26             } else {
27 0         0 die "Please specify 'filename' or 'filehandle'";
28             }
29 8 50       44 die "Unknown argument(s): ". join(", ", sort keys %args)
30             if keys %args;
31              
32 8         52 my $csv_parser = Text::CSV_XS->new({binary=>1, auto_diag=>9, diag_verbose=>1});
33              
34 8         1278 my $fhpos_data_begin = tell $fh;
35 8 50       341 my $columns = $csv_parser->getline($fh)
36             or die "Can't read columns from first row of CSV file";
37 8         430 my $fhpos_datarow_begin = tell $fh;
38              
39 8         95 bless {
40             fh => $fh,
41             fhpos_data_begin => $fhpos_data_begin,
42             fhpos_datarow_begin => $fhpos_datarow_begin,
43             csv_parser => $csv_parser,
44             columns => $columns,
45             pos => 0, # iterator
46             }, $class;
47             }
48              
49             sub as_csv {
50 2     2 1 12 my $self = shift;
51              
52 2         9 my $fh = $self->{fh};
53 2         6 my $oldpos = tell $fh;
54 2         27 seek $fh, $self->{fhpos_data_begin}, 0;
55 2         8 $self->{pos} = 0;
56 2         9 local $/;
57 2         59 scalar <$fh>;
58             }
59              
60             sub get_column_count {
61 3     3 0 8 my $self = shift;
62              
63 3         19 scalar @{ $self->{columns} };
  3         22  
64             }
65              
66             sub get_column_names {
67 10     10 0 42 my $self = shift;
68 10 100       48 wantarray ? @{ $self->{columns} } : $self->{columns};
  4         37  
69             }
70              
71             sub has_next_item {
72 327     327 0 614 my $self = shift;
73 327         504 my $fh = $self->{fh};
74 327         1144 !eof($fh);
75             }
76              
77             sub get_next_item {
78 312     312 0 758 my $self = shift;
79 312         485 my $fh = $self->{fh};
80 312 50       678 die "StopIteration" if eof($fh);
81 312         6035 my $row = $self->{csv_parser}->getline($fh);
82 312         7706 $self->{pos}++;
83 312         725 $row;
84             }
85              
86             sub get_next_row_hashref {
87 4     4 0 27 my $self = shift;
88 4         9 my $fh = $self->{fh};
89 4 50       34 die "StopIteration" if eof($fh);
90 4         121 my $row = $self->{csv_parser}->getline($fh);
91 4         115 $self->{pos}++;
92 4         11 +{ map {($self->{columns}[$_] => $row->[$_])} 0..$#{$self->{columns}} };
  12         69  
  4         14  
93             }
94              
95             sub get_iterator_pos {
96 0     0 0 0 my $self = shift;
97 0         0 $self->{pos};
98             }
99              
100             sub reset_iterator {
101 19     19 0 83 my $self = shift;
102 19         43 my $fh = $self->{fh};
103 19         235 seek $fh, $self->{fhpos_datarow_begin}, 0;
104 19         83 $self->{pos} = 0;
105             }
106              
107             sub DESTROY {
108 8     8   8712 my $self = shift;
109 8         62 my $fh = $self->{fh};
110 8         1265 seek $fh, $self->{fhpos_data_begin}, 0;
111             }
112              
113             1;
114             # ABSTRACT: Role to access table data from CSV in a file/filehandle
115              
116             __END__