File Coverage

blib/lib/Tie/Array/Iterable.pm
Criterion Covered Total %
statement 129 190 67.8
branch 26 40 65.0
condition 5 19 26.3
subroutine 23 36 63.8
pod 10 10 100.0
total 193 295 65.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2              
3             package Tie::Array::Iterable;
4              
5             #=============================================================================
6             #
7             # $Id: Iterable.pm,v 0.03 2001/11/16 02:27:56 mneylon Exp $
8             # $Revision: 0.03 $
9             # $Author: mneylon $
10             # $Date: 2001/11/16 02:27:56 $
11             # $Log: Iterable.pm,v $
12             # Revision 0.03 2001/11/16 02:27:56 mneylon
13             # Fixed packing version variables
14             #
15             # Revision 0.01.01.2 2001/11/16 02:12:14 mneylon
16             # Added code to clean up iterators after use
17             # clear_iterators() now not needed, simply returns 1;
18             #
19             # Revision 0.01.01.1 2001/11/15 01:41:19 mneylon
20             # Branch from 0.01 for new features
21             #
22             # Revision 0.01 2001/11/11 18:36:10 mneylon
23             # Initial Release
24             #
25             #
26             #=============================================================================
27              
28 2     2   4264 use 5.006;
  2         17  
  2         666  
29 2     2   15 use strict;
  2         2  
  2         85  
30 2     2   2580 use Tie::Array;
  2         2894  
  2         50  
31              
32 2     2   2039 use Tie::Array::Iterable::ForwardIterator;
  2         6  
  2         122  
33 2     2   2621 use Tie::Array::Iterable::BackwardIterator;
  2         7  
  2         156  
34              
35             BEGIN {
36 2     2   15 use Exporter ();
  2         4  
  2         229  
37 2     2   13 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  2         4  
  2         616  
38 2     2   13 ( $VERSION ) = '$Revision: 0.03 $ ' =~ /\$Revision:\s+([^\s]+)/;
39 2         42 @ISA = qw( Exporter Tie::StdArray );
40 2         5 @EXPORT = qw( );
41 2         5 @EXPORT_OK = qw( iterate_from_start iterate_from_end );
42 2         4526 %EXPORT_TAGS = ( quick=>[ qw( iterate_from_start iterate_from_end ) ] );
43             }
44              
45             sub new {
46 2     2 1 36 my $class = shift;
47 2         4 my @self;
48 2         36 tie @self, $class, \@_;
49 2         8 return bless \@self, $class;
50             }
51              
52             sub TIEARRAY {
53 2     2   4 my $class = shift;
54 2   50     8 my $arrayref = shift || [];
55 2         12 my %data = (
56             array => $arrayref,
57             forward_iters => [],
58             backward_iters => [] );
59 2         10 return bless \%data, $class;
60             }
61              
62             sub FETCH {
63 124     124   157 my $self = shift;
64 124         135 my $index = shift;
65 124         642 return $self->{ array }->[ $index ];
66             }
67              
68             sub STORE {
69 8     8   14 my $self = shift;
70 8         10 my $index = shift;
71 8         9 my $value = shift;
72 8         28 $self->{ array }->[ $index ] = $value;
73             }
74              
75             sub FETCHSIZE {
76 167     167   242 my $self = shift;
77 167         176 return scalar @{ $self->{ array } };
  167         591  
78             }
79              
80             sub STORESIZE {
81 0     0   0 my $self = shift;
82 0         0 my $count = shift;
83 0 0       0 if ( $count > $self->FETCHSIZE() ) {
    0          
84 0         0 foreach ( $count - $self->FETCHSIZE() .. $count ) {
85 0         0 $self->STORE( $_, '' );
86             }
87             } elsif ( $count < $self->FETCHSIZE() ) {
88 0         0 foreach ( 0 .. $self->FETCHSIZE() - $count - 2 ) {
89 0         0 $self->POP();
90             }
91             }
92             }
93              
94             sub EXTEND {
95 0     0   0 my $self = shift;
96 0         0 my $count = shift;
97 0         0 $self->STORESIZE( $count );
98             }
99              
100             sub EXISTS {
101 0     0   0 my $self = shift;
102 0         0 my $index = shift;
103 0         0 return exists $self->{ array }->[ $index ];
104             }
105              
106             sub CLEAR {
107 0     0   0 my $self = shift;
108 0         0 $self->{ array } = [];
109 0         0 foreach my $iter ( $self->_get_forward_iters() ) {
110 0         0 $iter->set_index( 0 );
111             }
112 0         0 foreach my $iter ( $self->_get_backward_iters() ) {
113 0         0 $iter->set_index( 0 );
114             }
115 0         0 return 1;
116             }
117              
118             sub PUSH {
119 4     4   10 my $self = shift;
120 4         9 my @list = @_;
121 4         13 my $last = $self->FETCHSIZE();
122 4         25 $self->STORE( $last + $_, $list[$_] ) foreach 0 .. $#list;
123 4         13 foreach my $iter ( $self->_get_forward_iters() ) {
124 2 100       6 if ( $iter->index() == $last ) {
125 1         6 $iter->set_index( $last + scalar @list );
126             }
127             }
128 4         14 foreach my $iter ( $self->_get_backward_iters() ) {
129 2 100       8 if ( $iter->index() == $last ) {
130 1         3 $iter->set_index( $last + scalar @list );
131             }
132             }
133 4         10 return $self->FETCHSIZE();
134             }
135              
136             sub POP {
137 4     4   7 my $self = shift;
138 4         21 foreach my $iter ( $self->_get_forward_iters() ) {
139 2 100       8 if ( $iter->index() >= $self->FETCHSIZE() ) {
140 1         4 $iter->set_index( $iter->index()-1 );
141             }
142             }
143 4         12 foreach my $iter ( $self->_get_backward_iters() ) {
144 2 100       7 if ( $iter->index() >= $self->FETCHSIZE() ) {
145 1         3 $iter->set_index( $iter->index()-1 );
146             }
147             }
148              
149 4         8 return pop @{ $self->{ array } };
  4         13  
150             }
151              
152             sub UNSHIFT {
153 4     4   37 my $self = shift;
154 4         10 my @list = @_;
155 4         10 my $size = scalar( @list );
156             # make room for our list
157 4         17 @{$self->{ array }}[ $size .. $#{$self->{ array }} + $size ]
  4         12  
158 4         6 = @{$self->{ array }};
  4         13  
159 4         25 $self->STORE( $_, $list[$_] ) foreach 0 .. $#list;
160 4         14 foreach my $iter ( $self->_get_forward_iters() ) {
161 2 100       7 if ( $iter->index() > 0 ) {
162 1         4 $iter->set_index( $iter->index() + scalar @list );
163             }
164             }
165 4         11 foreach my $iter ( $self->_get_backward_iters() ) {
166 2 100       6 if ( $iter->index() > 0 ) {
167 1         4 $iter->set_index( $iter->index() + scalar @list );
168             }
169             }
170              
171             }
172              
173             sub SHIFT {
174 4     4   7 my $self = shift;
175 4         15 foreach my $iter ( $self->_get_forward_iters() ) {
176 2 100       8 if ( $iter->index() > 0 ) {
177 1         5 $iter->set_index( $iter->index()-1 );
178             }
179             }
180 4         57 foreach my $iter ( $self->_get_backward_iters() ) {
181 2 100       7 if ( $iter->index() > 0 ) {
182 1         4 $iter->set_index( $iter->index()-1 );
183             }
184             }
185 4         9 return shift @{ $self->{ array } };
  4         15  
186             }
187              
188             sub SPLICE {
189 16     16   30 my $self = shift;
190 16   100     69 my $offset = shift || 0;
191 16 50       39 if ( $offset < 0 ) {
192 0         0 $offset = $self->FETCHSIZE() + $offset + 1;
193             }
194 16         27 my $length = shift;
195 16 50 66     83 if ( $length == 0 && $length ne "0" ) {
196 0         0 $length = $self->FETCHSIZE() - $offset;
197             }
198 16         36 my @list = @_;
199              
200             # Do the splice first:
201 16         23 my @data = splice @{ $self->{ array } }, $offset, $length, @list;
  16         104  
202              
203 16         48 foreach my $iter ( $self->_get_forward_iters() ) {
204             # If beyond the splice point...
205 8 100       32 if ( $iter->index() > $offset ) {
206             # If outside of the offset boundary
207 3 100       13 if ( $iter->index() > $offset + $length ) {
208             # Simply adjust the counter
209 2         9 $iter->set_index( $iter->index() +
210             ( scalar @list - $length ) );
211             } else {
212             # Push the iter back to the offset point
213 1         6 $iter->set_index( $offset );
214             }
215             }
216             }
217 16         49 foreach my $iter ( $self->_get_backward_iters() ) {
218             # If beyond the splice point...
219 8 100       23 if ( $iter->index() > $offset ) {
220             # If outside of the offset boundary
221 6 100       13 if ( $iter->index() > $offset + $length ) {
222             # Simply adjust the counter
223 4         11 $iter->set_index( $iter->index() +
224             ( scalar @list - $length ) );
225             } else {
226             # Push the iter back to the offset point
227 2         6 $iter->set_index( $offset + scalar @list + 1 );
228             }
229             }
230             }
231 16         78 return splice @data;
232             }
233              
234             sub from_start () {
235 1     1 1 6 my $self = shift;
236 1         10 my $iter = new Tie::Array::Iterable::ForwardIterator( $self, 0 );
237 1         2 push @{ tied(@$self)->{ forward_iters } }, $iter->_id();
  1         12  
238 1         2 return $iter;
239             }
240              
241             sub forward_from {
242 0     0 1 0 my $self = shift;
243 0         0 my $pos = shift;
244 0 0 0     0 if ( $pos == 0 && $pos ne "0" ) {
245 0         0 $pos = 0;
246             }
247 0 0 0     0 die "Position must be in array bounds"
248             unless $pos >= 0 && $pos < scalar @$self;
249 0         0 my $iter = new Tie::Array::Iterable::ForwardIterator( $self, $pos );
250 0         0 push @{ tied(@$self)->{ forward_iters } }, $iter->_id();
  0         0  
251 0         0 return $iter;
252             }
253              
254             sub from_end () {
255 1     1 1 6 my $self = shift;
256 1         15 my $iter = new Tie::Array::Iterable::BackwardIterator( $self,
257             scalar @$self );
258 1         1 push @{ tied(@$self)->{ backward_iters } }, $iter->_id();
  1         7  
259 1         4 return $iter;
260             }
261              
262             sub backward_from {
263 0     0 1 0 my $self = shift;
264 0         0 my $pos = shift;
265 0 0 0     0 if ( $pos == 0 && $pos ne "0" ) {
266 0         0 $pos = scalar @$self;
267             }
268 0 0 0     0 die "Position must be in array bounds"
269             unless $pos >= 0 && $pos <= scalar @$self;
270 0         0 my $iter = new Tie::Array::Iterable::BackwardIterator( $self, $pos );
271 0         0 push @{ tied(@$self)->{ backward_iters } }, $iter->_id();
  0         0  
272 0         0 return $iter;
273             }
274              
275             # This function is no longer necessary
276              
277             sub clear_iterators {
278 0     0 1 0 1;
279             }
280              
281              
282             sub iterate_from_start {
283 0     0 1 0 my $array = new Tie::Array::Iterable( @_ );
284 0         0 return $array->from_start();
285             }
286              
287             sub iterate_from_end {
288 0     0 1 0 my $array = new Tie::Array::Iterable( @_ );
289 0         0 return $array->from_end();
290             }
291              
292             sub iterate_forward_from {
293 0     0 1 0 my $pos = shift;
294 0         0 my $array = new Tie::Array::Iterable( @_ );
295 0         0 return $array->forward_from( $pos );
296             }
297              
298             sub iterate_backward_from {
299 0     0 1 0 my $pos = shift;
300 0         0 my $array = new Tie::Array::Iterable( @_ );
301 0         0 return $array->backward_from( $pos );
302             }
303              
304             sub _get_forward_iters {
305 32     32   47 my $self = shift;
306 16         96 return grep { $_ }
  16         64  
307             map { Tie::Array::Iterable::ForwardIterator::_lookup( $_ ) }
308 32         49 @{ $self->{ forward_iters } };
  32         123  
309             }
310              
311             sub _get_backward_iters {
312 32     32   46 my $self = shift;
313 16         43 return grep { $_ }
  16         42  
314             map { Tie::Array::Iterable::BackwardIterator::_lookup( $_ ) }
315 32         39 @{ $self->{ backward_iters } };
  32         93  
316             }
317              
318             sub _remove_forward_iterator {
319 0     0     my $self = shift;
320 0           my $id = shift;
321 2     2   4710 use Data::Dumper;
  2         40203  
  2         516  
322             tied(@$self)->{ forward_iters } = [
323 0           grep { $_ != $id }
324 0           @{ tied(@$self)->{ forward_iters } } ];
  0            
325             }
326              
327             sub _remove_backward_iterator {
328 0     0     my $self = shift;
329 0           my $id = shift;
330             tied(@$self)->{ backward_iters } = [
331 0           grep { $_ != $id }
332 0           @{ tied(@$self)->{ backward_iters } } ];
  0            
333             }
334              
335             1;
336             __END__