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 13     13   568654 use 5.010001;
  13         57  
4 13     13   100 use strict;
  13         43  
  13         334  
5 13     13   58 use warnings;
  13         24  
  13         758  
6              
7 13     13   692 use Role::Tiny;
  13         7694  
  13         98  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2024-05-14'; # DATE
11             our $DIST = 'TableDataRoles-Standard'; # DIST
12             our $VERSION = '0.025'; # VERSION
13              
14             with 'TableDataRole::Spec::Basic';
15              
16             sub new {
17 10     10 1 10168 require Text::CSV_XS;
18              
19 10         222348 my ($class, %args) = @_;
20              
21 10         61 my $fh;
22 10 100       70 if (defined(my $filename = delete $args{filename})) {
    50          
23 3 50       136 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 10 50       44 die "Unknown argument(s): ". join(", ", sort keys %args)
30             if keys %args;
31              
32 10         82 my $csv_parser = Text::CSV_XS->new({binary=>1, auto_diag=>9, diag_verbose=>1});
33              
34 10         1933 my $fhpos_data_begin = tell $fh;
35 10 50       397 my $columns = $csv_parser->getline($fh)
36             or die "Can't read columns from first row of CSV file";
37 10         37 my $fhpos_datarow_begin = tell $fh;
38              
39 10         177 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 3     3 1 19 my $self = shift;
51              
52 3         14 my $fh = $self->{fh};
53 3         8 my $oldpos = tell $fh;
54 3         30 seek $fh, $self->{fhpos_data_begin}, 0;
55 3         7 $self->{pos} = 0;
56 3         17 local $/;
57 3         111 scalar <$fh>;
58             }
59              
60             sub get_column_count {
61 3     3 0 8 my $self = shift;
62              
63 3         5 scalar @{ $self->{columns} };
  3         44  
64             }
65              
66             sub get_column_names {
67 109     109 0 683 my $self = shift;
68 109 100       296 wantarray ? @{ $self->{columns} } : $self->{columns};
  103         453  
69             }
70              
71             sub has_next_item {
72 463     463 0 1335 my $self = shift;
73 463         1599 my $fh = $self->{fh};
74 463         1668 !eof($fh);
75             }
76              
77             sub get_next_item {
78 447     447 0 1313 my $self = shift;
79 447         737 my $fh = $self->{fh};
80 447 50       1153 die "StopIteration" if eof($fh);
81 447         3757 my $row = $self->{csv_parser}->getline($fh);
82 447         1035 $self->{pos}++;
83 447         1191 $row;
84             }
85              
86             sub get_next_row_hashref {
87 4     4 0 10 my $self = shift;
88 4         8 my $fh = $self->{fh};
89 4 50       34 die "StopIteration" if eof($fh);
90 4         48 my $row = $self->{csv_parser}->getline($fh);
91 4         10 $self->{pos}++;
92 4         10 +{ map {($self->{columns}[$_] => $row->[$_])} 0..$#{$self->{columns}} };
  12         68  
  4         12  
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 20     20 0 103 my $self = shift;
102 20         53 my $fh = $self->{fh};
103 20         290 seek $fh, $self->{fhpos_datarow_begin}, 0;
104 20         80 $self->{pos} = 0;
105             }
106              
107             sub DESTROY {
108 10     10   14745 my $self = shift;
109 10         30 my $fh = $self->{fh};
110 10         1847 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__