File Coverage

blib/lib/Data/Iterator/SlidingWindow.pm
Criterion Covered Total %
statement 53 53 100.0
branch 11 12 91.6
condition 11 11 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 88 89 98.8


line stmt bran cond sub pod time code
1             package Data::Iterator::SlidingWindow;
2 2     2   56576 use strict;
  2         4  
  2         68  
3 2     2   10 use warnings;
  2         5  
  2         48  
4 2     2   43 use 5.008001;
  2         10  
  2         77  
5 2     2   1754 use parent 'Exporter';
  2         772  
  2         11  
6 2     2   106 use Carp qw(croak);
  2         3  
  2         165  
7             use overload
8 20     20   666 '<>' => sub { shift->next() },
9 2     2   7450 fallback => 1;
  2         3157  
  2         24  
10              
11             our $VERSION = '0.05';
12              
13             our @EXPORT = qw(iterator);
14              
15             sub _new {
16 7     7   12 my $class = shift;
17 7         21 my %args = @_;
18              
19 7         10 my $window_size = $args{window_size};
20 7         13 my $src_stuff = $args{data_source};
21              
22 7 100 100     85 if ( !defined $window_size || $window_size !~ /^[0-9]+$/ || $window_size == 0 ) {
      100        
23 3         546 croak "window size must be positive integer.";
24             }
25              
26 4   100     27 my $src_type = ref( $src_stuff || q{} ) || q{};
27 4 100 100     21 if ( !( $src_type eq 'CODE' || $src_type eq 'ARRAY' ) ) {
28 2         303 croak "data_source must be CODE reference or ARRAY refernce.";
29             }
30              
31 2         3 my $source;
32 2 100       6 if ( $src_type eq 'ARRAY' ) {
33             $source = sub {
34 22     22   31 shift @$src_stuff;
35 1         6 };
36             }
37             else {
38 1         4 $source = $src_stuff;
39             }
40              
41             # Initialize current window
42 2         3 my @current_window;
43 2         7 while ( @current_window < $window_size ) {
44 6         12 my $next = $source->();
45 6 50       19 last if !defined $next;
46 6         21 push @current_window, $next;
47             }
48              
49 2         9 my $self = {
50             _window_size => $window_size,
51             _source => $source,
52             _current_window => \@current_window,
53             };
54              
55 2         11 return bless $self, $class;
56             }
57              
58             sub next {
59 40     40 1 985 my $self = shift;
60 40         41 my $ret = [ @{ $self->{_current_window} } ];
  40         159  
61 40 100       101 return if @$ret != $self->{_window_size};
62 38         39 shift @{ $self->{_current_window} };
  38         62  
63 38         72 my $next = $self->{_source}->();
64 38 100       125 if ( defined $next ) {
65 36         109 push @{ $self->{_current_window} }, $next;
  36         71  
66             }
67 38         86 return $ret;
68             }
69              
70             sub iterator {
71 7     7 1 10382 my ( $window_size, $data_source ) = @_;
72 7         36 return __PACKAGE__->_new(
73             window_size => $window_size,
74             data_source => $data_source,
75             );
76             }
77              
78             1;
79             __END__