File Coverage

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


line stmt bran cond sub pod time code
1             package Tie::Array::CSV::HoldRow;
2              
3 2     2   2606 use strict;
  2         6  
  2         94  
4 2     2   11 use warnings;
  2         3  
  2         66  
5              
6 2     2   8 use Carp;
  2         4  
  2         157  
7              
8 2     2   2809 use Tie::File;
  2         53394  
  2         547  
9 2     2   635 use Text::CSV;
  2         6  
  2         24  
10              
11 2     2   116 use Scalar::Util qw/weaken/;
  2         4  
  2         158  
12              
13 2     2   1733 use Tie::Array::CSV;
  2         7  
  2         1745  
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   4420 my $class = shift;
20              
21 2         28 my $self = $class->SUPER::TIEARRAY(@_);
22              
23 2         18 $self->{active_rows} = {},
24              
25             # rebless
26             bless $self, $class;
27              
28 2         19 return $self;
29             }
30              
31             sub FETCH {
32 9     9   5100 my $self = shift;
33 9         15 my $index = shift;
34              
35 9 100       150 if ($self->{active_rows}{$index}) {
36 3         16 return $self->{active_rows}{$index}
37             }
38              
39 6         40 my $line_array = $self->SUPER::FETCH($index);
40              
41 6         29 weaken(
42             $self->{active_rows}{$index} = $line_array
43             );
44              
45 6         20 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   220 my $self = shift;
57 2         17 my $size = $self->FETCHSIZE;
58 2 50       130 my $offset = @_ ? shift : 0;
59 2 50       9 $offset += $size if $offset < 0;
60 2 50       8 my $length = @_ ? shift : $size-$offset;
61              
62 2         7 my @replace_rows = map { $self->_combine($_) } @_;
  1         10  
63              
64             ## reindex active_rows ##
65              
66             # assuming removing items
67 4         12 my @active_rows =
68 6         22 sort { $a <=> $b }
69 2         8 grep { defined $self->{active_rows}{$_} }
70 2         165 keys %{ $self->{active_rows} };
71 2         8 my $delta = @replace_rows - $length;
72              
73             # if instead adding items
74 2 100       6 if ($length < @replace_rows) {
75             # reverse ot avoid overwriting active items
76 1         2 @active_rows = reverse @active_rows;
77 1         9 $delta = @replace_rows + $length;
78             }
79              
80 2         6 foreach my $index (@active_rows) {
81             # skip lines before those affected
82 5 100       14 next if ($index < $offset);
83              
84 4 100 66     21 if ($index >= $offset and $index < ($offset + $length)) { #items that are being removed
85 1         3 tied(@{$self->{active_rows}{$index}})->{line_num} = undef;
  1         5  
86             } else { #shifting affected items
87 3         4 tied(@{$self->{active_rows}{$index}})->{line_num} = $index+$delta;
  3         10  
88 3         14 $self->{active_rows}{$index+$delta} = delete $self->{active_rows}{$index};
89             }
90             }
91              
92             ## end reindexing logic ##
93              
94 1         619 my @return = map { $self->_parse($_) }
  2         12  
95 2         6 splice(@{ $self->{file} },$offset,$length,@replace_rows);
96              
97             return @return
98              
99 2         528 }
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   16 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     0   0 sub EXTEND { }
129              
130             package Tie::Array::CSV::HoldRow::Row;
131              
132 2     2   15 use Carp;
  2         5  
  2         223  
133              
134 2     2   11 use Tie::Array::CSV;
  2         22  
  2         432  
135             our @ISA = ('Tie::Array::CSV::Row');
136              
137             sub TIEARRAY {
138 6     6   1629 my $class = shift;
139 6         45 my $self = $class->SUPER::TIEARRAY(@_);
140              
141             # rebless
142 6         16 bless $self, $class;
143              
144 6         272 $self->{need_update} = 0;
145              
146 6         21 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   2 my $self = shift;
157 1 50       14 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         10 $self->SUPER::_update();
163             }
164              
165             sub DESTROY {
166 6     6   2706 my $self = shift;
167 6 100       80 $self->_deferred_update if $self->{need_update} == 1;
168             }
169              
170             __END__