File Coverage

blib/lib/Iterator/Array/Jagged.pm
Criterion Covered Total %
statement 74 74 100.0
branch 16 16 100.0
condition n/a
subroutine 8 8 100.0
pod 4 4 100.0
total 102 102 100.0


line stmt bran cond sub pod time code
1            
2             package Iterator::Array::Jagged;
3            
4 1     1   37597 use strict;
  1         2  
  1         43  
5 1     1   6 use warnings 'all';
  1         1  
  1         877  
6             our $VERSION = '0.05';
7            
8            
9             #==============================================================================
10             sub new
11             {
12 1     1 1 513 my ($class, %args) = @_;
13            
14 4         10 my $s = bless {
15             idx => [
16 1         5 map { 0 } 0...scalar(@{$args{data}}) - 1
  4         10  
17             ],
18             sizes => [
19 1         3 map { scalar(@$_) - 1 } @{$args{data}}
  1         7  
20             ],
21             data => $args{data},
22 1         3 _max => scalar(@{$args{data}}),
23             _is_finished => 0,
24             }, $class;
25            
26 1         6 return $s;
27             }# end new()
28            
29            
30             #==============================================================================
31             sub _increment
32             {
33 340     340   562 my ($s, $index) = @_;
34            
35 340 100       904 if( $s->{idx}->[ $index ] < $s->{sizes}->[ $index ] )
36             {
37 255         542 $s->{idx}->[ $index ]++;
38             }
39             else
40             {
41 85         128 $s->{idx}->[ $index ] = 0;
42 85 100       185 if( $index + 1 < $s->{_max} )
43             {
44 84         200 $s->_increment( $index + 1 );
45             }
46             else
47             {
48 1         4 $s->{_is_finished} = 1;
49             }# end if()
50             }# end if()
51             }# end _increment()
52            
53            
54             #==============================================================================
55             sub next
56             {
57 257     257 1 171276 my ($s) = @_;
58            
59 257 100       1012 return if $s->{_is_finished};
60            
61             # Calculate and return the current value:
62 256         385 my @parts = ();
63 256         748 for( 0...$s->{_max} - 1 )
64             {
65 1024         1403 my $part_idx = $s->{idx}->[ $_ ];
66 1024         2260 push @parts, $s->{data}->[ $_ ]->[ $part_idx ];
67             }# end for()
68            
69 256         604 $s->_increment( 0 );
70            
71 256         1065 return @parts;
72             }# end next()
73            
74            
75             #==============================================================================
76             sub permute
77             {
78 1     1 1 16 my ($class, $func, @data) = @_;
79            
80 1         31 my @idx = map { 0 } 0...scalar(@data) - 1;
  4         12  
81 1         2 my @sizes = map { scalar(@$_) - 1 } @data;
  4         10  
82 1         2 my $max = scalar(@data);
83 1         4 PERMUTATION: while( 1 )
84             {
85             # Prepare a 'set':
86 256         361 my @parts = ();
87 256         570 for my $num ( 0...$max - 1 )
88             {
89 1024         2003 push @parts, $data[ $num ]->[ $idx[ $num ] ];
90             }# end for()
91            
92             # Execute 'func':
93 256         748 $func->( @parts );
94            
95             # Increment or finish:
96 256         170596 my $to_increment = 0;
97 256         294 INCR: while( 1 )
98             {
99 340 100       794 if( $idx[ $to_increment ] < $sizes[ $to_increment ] )
100             {
101 255         284 $idx[ $to_increment ]++;
102 255         359 last INCR;
103             }
104             else
105             {
106 85         118 $idx[ $to_increment ] = 0;
107 85 100       163 if( $to_increment + 1 < $max )
108             {
109 84         101 $to_increment += 1;
110 84         119 next INCR;
111             }
112             else
113             {
114 1         6 last PERMUTATION;
115             }# end if()
116             }# end if()
117             }# end while()
118            
119 255         438 next PERMUTATION;
120             }# end while()
121            
122             }# end permute()
123            
124            
125             #==============================================================================
126             sub get_iterator
127             {
128 1     1 1 16 my ($class, @data) = @_;
129            
130 1         7 my @idx = map { 0 } 0...scalar(@data) - 1;
  4         10  
131 1         4 my @sizes = map { scalar(@$_) - 1 } @data;
  4         9  
132 1         3 my $max = scalar(@data);
133 1         3 my $is_finished = 0;
134            
135             return sub {
136 257 100   257   149913 return if $is_finished;
137             # Prepare a 'set':
138 256         363 my @parts = ();
139 256         511 for my $num ( 0...$max - 1 )
140             {
141 1024         1780 push @parts, $data[ $num ]->[ $idx[ $num ] ];
142             }# end for()
143            
144             # Increment or finish:
145 256         312 my $to_increment = 0;
146 256         231 INCR: while( 1 )
147             {
148 341 100       606 if( $idx[ $to_increment ] < $sizes[ $to_increment ] )
149             {
150 256         252 $idx[ $to_increment ]++;
151 256         301 last INCR;
152             }
153             else
154             {
155 85         128 $idx[ $to_increment ] = 0;
156 85 100       154 if( $to_increment + 1 < $max )
157             {
158 84         93 $to_increment += 1;
159 84         135 next INCR;
160             }
161             else
162             {
163 1         2 $is_finished = 1;
164             }# end if()
165             }# end if()
166             }# end while()
167            
168             # Finally return the parts:
169 256         920 return @parts;
170 1         9 };# end sub{...}
171             }# end get_iterator()
172            
173             1; #return true:
174            
175             __END__