File Coverage

blib/lib/Flat/Profile/Iterator.pm
Criterion Covered Total %
statement 45 50 90.0
branch 14 18 77.7
condition n/a
subroutine 9 9 100.0
pod 0 4 0.0
total 68 81 83.9


line stmt bran cond sub pod time code
1             package Flat::Profile::Iterator;
2              
3 12     12   85 use strict;
  12         28  
  12         468  
4 12     12   55 use warnings;
  12         50  
  12         768  
5              
6 12     12   71 use Carp qw(croak);
  12         22  
  12         622  
7 12     12   10347 use Text::CSV;
  12         267795  
  12         6319  
8              
9             sub new {
10 12     12 0 98 my ($class, %opts) = @_;
11              
12 12         45 for my $required (qw(fh delimiter has_header)) {
13 36 50       184 if (!exists $opts{$required}) {
14 0         0 croak "Iterator->new missing required argument: $required";
15             }
16             }
17              
18             my $csv = Text::CSV->new({
19             binary => 1,
20             sep_char => $opts{delimiter},
21 12         194 auto_diag => 0,
22             });
23              
24 12 50       3468 if (!$csv) {
25 0         0 croak "Failed to initialize Text::CSV";
26             }
27              
28             my $self = bless {
29             _fh => $opts{fh},
30             _csv => $csv,
31 12 100       156 _has_header => $opts{has_header} ? 1 : 0,
32              
33             # Row index counts *data rows returned* (header excluded).
34             _row_index => 0,
35              
36             # Header row (arrayref) if has_header enabled and header consumed.
37             _header => undef,
38              
39             # Internal: whether we've processed header (if any).
40             _started => 0,
41             }, $class;
42              
43 12         65 return $self;
44             }
45              
46             sub next_row {
47 37     37 0 6550 my ($self) = @_;
48              
49             # Lazily consume header if configured
50 37 100       194 if (!$self->{_started}) {
51 12         48 $self->{_started} = 1;
52              
53 12 100       135 if ($self->{_has_header}) {
54 10         103 my $header_row = $self->_read_row_raw();
55 10 50       43 if (!defined $header_row) {
56 0         0 return undef; # empty file
57             }
58 10         61 $self->{_header} = $header_row;
59             }
60             }
61              
62 37         125 my $row = $self->_read_row_raw();
63 37 100       132 if (defined $row) {
64 25         85 $self->{_row_index}++;
65             }
66              
67 37         160 return $row;
68             }
69              
70             sub _read_row_raw {
71 47     47   95 my ($self) = @_;
72              
73 47         99 my $fh = $self->{_fh};
74 47         96 my $csv = $self->{_csv};
75              
76 47         67 while (1) {
77 47         2902 my $row = $csv->getline($fh);
78              
79 47 100       443 if ($row) {
80 35         63 my @fields = @{$row};
  35         109  
81 35         129 return \@fields;
82             }
83              
84 12 50       124 if ($csv->eof) {
85 12         119 return undef;
86             }
87              
88 0         0 my $err = $csv->error_diag;
89 0         0 croak "CSV parse error: $err";
90             }
91             }
92              
93             sub get_Row_Index {
94 4     4 0 1230 my ($self) = @_;
95 4         29 return $self->{_row_index};
96             }
97              
98             sub get_Header {
99 11     11 0 40 my ($self) = @_;
100 11         57 return $self->{_header};
101             }
102              
103             1;