File Coverage

blib/lib/Range/ArrayIter.pm
Criterion Covered Total %
statement 44 45 97.7
branch 18 20 90.0
condition 4 5 80.0
subroutine 8 8 100.0
pod 1 1 100.0
total 75 79 94.9


line stmt bran cond sub pod time code
1             package Range::ArrayIter;
2              
3             our $DATE = '2019-04-17'; # DATE
4             our $VERSION = '0.001'; # VERSION
5              
6 1     1   55208 use strict;
  1         11  
  1         26  
7 1     1   5 use warnings;
  1         1  
  1         26  
8              
9 1     1   5 use Exporter qw(import);
  1         1  
  1         415  
10             our @EXPORT_OK = qw(range_arrayiter);
11              
12             my $re_num = qr/\A[+-]?[0-9]+(\.[0-9]+)?\z/;
13              
14             sub range_arrayiter($$;$) {
15 7     7 1 2885 my ($start, $end, $step) = @_;
16              
17 7         26 tie my @ary, 'Range::ArrayIter::Tie', $start, $end, $step;
18 7         27 \@ary;
19             }
20              
21             package # hide from PAUSE
22             Range::ArrayIter::Tie;
23              
24             sub TIEARRAY {
25 7     7   10 my $class = shift;
26 7         14 my ($start, $end, $step) = @_;
27 7   100     27 $step //= 1;
28              
29 7         26 my $self = {
30             start => $start,
31             end => $end,
32             step => $step,
33              
34             _ended => 0,
35             _len => 0,
36             _cur => $start,
37             _buf => [],
38             };
39              
40 7 100 66     62 if ($start =~ $re_num && $end =~ $re_num) {
41 4         11 $self->{_num} = 1;
42 4 100       9 $self->{_ended}++ if $start > $end;
43             } else {
44 3 50       6 die "Cannot specify step != 1 for non-numeric range" if $step != 1;
45 3 100       9 $self->{_ended}++ if $start gt $end;
46             }
47 7         28 bless $self, $class;
48             }
49              
50             sub _next {
51 79     79   78 my $self = shift;
52              
53 79 100       108 if ($self->{_num}) {
54 22 100       35 $self->{_ended}++ if $self->{_cur} > $self->{end};
55 22 100       33 return if $self->{_ended};
56 9         10 push @{ $self->{_buf} }, $self->{_cur};
  9         17  
57 9         13 $self->{_cur} += $self->{step};
58             } else {
59 57 100       79 return if $self->{_ended};
60 27 100       38 $self->{_ended}++ if $self->{_cur} ge $self->{end};
61 27         28 push @{ $self->{_buf} }, $self->{_cur}++;
  27         50  
62             }
63             }
64              
65             sub FETCHSIZE {
66 43     43   70 my $self = shift;
67 43         66 $self->_next;
68 43         48 $self->{_len} + @{ $self->{_buf} };
  43         81  
69             }
70              
71             sub FETCH {
72 36     36   103 my $self = shift;
73 36         59 $self->_next;
74 36 50       36 if (@{ $self->{_buf} }) {
  36         43  
75 36         39 $self->{_len}++;
76 36         33 shift @{ $self->{_buf} };
  36         84  
77             } else {
78 0           undef;
79             }
80             }
81              
82             1;
83             # ABSTRACT: Generate a tied-array iterator for range
84              
85             __END__