File Coverage

blib/lib/Iterator/GroupedRange.pm
Criterion Covered Total %
statement 61 65 93.8
branch 29 34 85.2
condition 7 10 70.0
subroutine 10 11 90.9
pod 7 7 100.0
total 114 127 89.7


line stmt bran cond sub pod time code
1             package Iterator::GroupedRange;
2              
3 4     4   169789 use strict;
  4         11  
  4         170  
4 4     4   21 use warnings;
  4         9  
  4         3271  
5              
6             our $VERSION = '0.08';
7              
8             sub new {
9 13     13 1 20616 my $class = shift;
10 13         28 my ( $code, $range, $opts ) = @_;
11              
12 13   100     53 $range ||= 1000;
13 13   50     82 $opts ||= {};
14              
15 13         58 %$opts = (
16             rows => undef,
17             %$opts,
18             );
19              
20 13 100       57 if ( ref $code eq 'ARRAY' ) {
21 7         40 my @ds = @$code;
22 7         15 $opts->{rows} = scalar @ds;
23             $code = sub {
24 37 100   37   202 @ds > 0 ? [ splice( @ds, 0, $range ) ] : undef;
25 7         29 };
26             }
27              
28 13         169 return bless {
29             code => $code,
30             range => $range,
31             is_last => 0,
32             rows => $opts->{rows},
33             _has_next => undef,
34             _buffer => [],
35             _append_buffer => [],
36             } => $class;
37             }
38              
39             sub has_next {
40 32     32 1 6065 my $self = shift;
41 32 100       129 return 0 if ( $self->{is_last} );
42 26 100       80 return 1 if ( $self->{_has_next} );
43 18         61 $self->{_buffer} = $self->{code}->();
44 18 50       85 if ( defined $self->{_buffer} ) {
45 18         32 $self->{_has_next} = 1;
46 18         53 return 1;
47             }
48             else {
49 0         0 return 0;
50             }
51             }
52              
53             sub next {
54 79     79 1 15341 my $self = shift;
55              
56 79 100       322 return if ( $self->{is_last} );
57 68 50       164 return unless ( defined $self->{_buffer} );
58              
59 68         85 my @buffer = @{ $self->{_buffer} };
  68         186  
60              
61 68         218 while ( @buffer < $self->{range} ) {
62 69         173 my $rv = $self->{code}->();
63 69 100       253 unless ( defined $rv ) {
64 14 100       24 if ( @{$self->{_append_buffer}} > 0 ) {
  14         45  
65 2         5 my @append_buffer = @{$self->{_append_buffer}};
  2         11  
66              
67             $self->{code} = sub {
68 6 100   6   31 return @append_buffer > 0 ?
69             [ splice( @append_buffer, 0, $self->{range} ) ] : undef;
70 2         13 };
71              
72 2         13 $self->{_buffer} = [ @buffer ];
73 2         8 $self->{_append_buffer} = [];
74              
75 2         14 return $self->next;
76             }
77             else {
78 12         27 $self->{is_last} = 1;
79 12         27 last;
80             }
81             }
82 55         235 push( @buffer, @$rv );
83             }
84              
85 66         231 my @rs = splice( @buffer, 0, $self->{range} );
86              
87 66         189 $self->{_buffer} = [ @buffer ];
88 66 100       265 $self->{_has_next} = @buffer > 0 ? 1 : 0;
89              
90 66 100       385 return @rs ? \@rs : ();
91             }
92              
93             sub append {
94 5     5 1 25 my $self = shift;
95 5 100 66     37 my $rows = ( @_ == 1 && ref $_[0] eq 'ARRAY' ) ? $_[0] : [ @_ ];
96              
97 5 100       29 if ( defined $self->{rows} ) {
98 3         6 $self->{rows} += scalar @$rows;
99             }
100              
101 5         10 push(@{$self->{_append_buffer}}, @$rows);
  5         21  
102              
103 5 100 66     22 if (!$self->{_has_next} && @{$self->{_append_buffer}}) {
  3         16  
104 3         7 $self->{_has_next} = 1;
105             }
106              
107 5         16 return scalar @$rows;
108             }
109              
110             sub is_last {
111 74     74 1 60677 $_[0]->{is_last};
112             }
113              
114             sub rows {
115 7 50   7 1 43 if ( @_ == 2 ) {
116 0         0 $_[0]->{rows} = $_[1];
117             }
118             else {
119 7         44 return $_[0]->{rows};
120             }
121             }
122              
123             sub range {
124 0 0   0 1   return $_[0]->{range} = $_[1] if @_ == 2;
125 0           shift->{range};
126             }
127              
128             1;
129             __END__