File Coverage

blib/lib/Tie/Array/CSV/HoldRow.pm
Criterion Covered Total %
statement 78 97 80.4
branch 14 20 70.0
condition 2 3 66.6
subroutine 17 23 73.9
pod n/a
total 111 143 77.6


line stmt bran cond sub pod time code
1             package Tie::Array::CSV::HoldRow;
2              
3 2     2   1509 use strict;
  2         4  
  2         87  
4 2     2   9 use warnings;
  2         3  
  2         42  
5              
6 2     2   8 use Carp;
  2         3  
  2         110  
7              
8 2     2   1193 use Tie::File;
  2         33080  
  2         57  
9 2     2   15 use Text::CSV;
  2         3  
  2         115  
10              
11 2     2   12 use Scalar::Util qw/weaken/;
  2         4  
  2         91  
12              
13 2     2   877 use Tie::Array::CSV;
  2         5  
  2         1148  
14             our @ISA = ('Tie::Array::CSV');
15              
16             # This is essentially the same TIEARRAY method as T::A::CSV,
17             # but initializes active_rows. This isn't strictly necessary, thanks to autoviv
18             sub TIEARRAY {
19 2     2   1966 my $class = shift;
20              
21 2         14 my $self = $class->SUPER::TIEARRAY(@_);
22              
23             $self->{active_rows} = {},
24              
25             # rebless
26 2         16 bless $self, $class;
27              
28 2         20 return $self;
29             }
30              
31             sub FETCH {
32 9     9   3169 my $self = shift;
33 9         10 my $index = shift;
34              
35 9 100       23 if ($self->{active_rows}{$index}) {
36 3         9 return $self->{active_rows}{$index}
37             }
38              
39 6         18 my $line_array = $self->SUPER::FETCH($index);
40              
41             weaken(
42 6         19 $self->{active_rows}{$index} = $line_array
43             );
44              
45 6         16 return $line_array;
46             }
47              
48             sub STORE {
49 0     0   0 my $self = shift;
50 0         0 my ($index, $value) = @_;
51              
52 0         0 $self->{file}[$index] = $self->_combine($value);
53             }
54              
55             sub SPLICE {
56 2     2   6 my $self = shift;
57 2         6 my $size = $self->FETCHSIZE;
58 2 50       97 my $offset = @_ ? shift : 0;
59 2 50       4 $offset += $size if $offset < 0;
60 2 50       4 my $length = @_ ? shift : $size-$offset;
61              
62 2         4 my @replace_rows = map { $self->_combine($_) } @_;
  1         5  
63              
64             ## reindex active_rows ##
65              
66             # assuming removing items
67             my @active_rows =
68 5         9 sort { $a <=> $b }
69 6         15 grep { defined $self->{active_rows}{$_} }
70 2         34 keys %{ $self->{active_rows} };
  2         5  
71 2         3 my $delta = @replace_rows - $length;
72              
73             # if instead adding items
74 2 100       4 if ($length < @replace_rows) {
75             # reverse ot avoid overwriting active items
76 1         2 @active_rows = reverse @active_rows;
77 1         1 $delta = @replace_rows + $length;
78             }
79              
80 2         5 foreach my $index (@active_rows) {
81             # skip lines before those affected
82 5 100       17 next if ($index < $offset);
83              
84 4 100 66     15 if ($index >= $offset and $index < ($offset + $length)) { #items that are being removed
85 1         1 tied(@{$self->{active_rows}{$index}})->{line_num} = undef;
  1         3  
86             } else { #shifting affected items
87 3         5 tied(@{$self->{active_rows}{$index}})->{line_num} = $index+$delta;
  3         6  
88 3         8 $self->{active_rows}{$index+$delta} = delete $self->{active_rows}{$index};
89             }
90             }
91              
92             ## end reindexing logic ##
93              
94 1         409 my @return = map { $self->_parse($_) }
95 2         3 splice(@{ $self->{file} },$offset,$length,@replace_rows);
  2         7  
96              
97             return @return
98              
99 2         330 }
100              
101             sub SHIFT {
102 0     0   0 my $self = shift;
103 0         0 my ($return) = $self->SPLICE(0,1);
104 0         0 return $return;
105             }
106              
107 1     1   8 sub UNSHIFT { scalar shift->SPLICE(0,0,@_) }
108              
109             sub PUSH {
110 0     0   0 my $self = shift;
111 0         0 my $i = $self->FETCHSIZE;
112 0         0 $self->STORE($i++, shift) while (@_);
113             }
114              
115             sub POP {
116 0     0   0 my $self = shift;
117 0         0 my $newsize = $self->FETCHSIZE - 1;
118 0         0 my $val;
119 0 0       0 if ($newsize >= 0) {
120 0         0 $val = $self->FETCH($newsize);
121 0         0 $self->STORESIZE($newsize);
122             }
123 0         0 return $val;
124             }
125              
126 0     0   0 sub CLEAR { shift->STORESIZE(0) }
127              
128       0     sub EXTEND { }
129              
130             package Tie::Array::CSV::HoldRow::Row;
131              
132 2     2   14 use Carp;
  2         4  
  2         112  
133              
134 2     2   12 use Tie::Array::CSV;
  2         3  
  2         339  
135             our @ISA = ('Tie::Array::CSV::Row');
136              
137             sub TIEARRAY {
138 6     6   234 my $class = shift;
139 6         21 my $self = $class->SUPER::TIEARRAY(@_);
140              
141             # rebless
142 6         8 bless $self, $class;
143              
144 6         81 $self->{need_update} = 0;
145              
146 6         15 return $self;
147             }
148              
149             # _update now marks for deferred update
150             sub _update {
151 1     1   2 my $self = shift;
152 1         3 $self->{need_update} = 1;
153             }
154              
155             sub _deferred_update {
156 1     1   1 my $self = shift;
157 1 50       3 unless (defined $self->{line_num}) {
158 0         0 carp "Attempted to write out from a severed row";
159 0         0 return undef;
160             }
161              
162 1         4 $self->SUPER::_update();
163             }
164              
165             sub DESTROY {
166 6     6   1624 my $self = shift;
167 6 100       37 $self->_deferred_update if $self->{need_update} == 1;
168             }
169              
170             __END__