File Coverage

blib/lib/Array/Circular.pm
Criterion Covered Total %
statement 67 75 89.3
branch 23 30 76.6
condition 2 3 66.6
subroutine 15 18 83.3
pod 12 12 100.0
total 119 138 86.2


line stmt bran cond sub pod time code
1 3     3   1382 use strict;
  3         17  
  3         83  
2 3     3   15 use warnings;
  3         5  
  3         102  
3             package Array::Circular;
4             # ABSTRACT: Provide an array data structure that can go around in circles
5              
6 3     3   14 use Carp;
  3         6  
  3         293  
7 3     3   19 use Scalar::Util qw/refaddr/;
  3         8  
  3         3183  
8              
9             my %DATA;
10              
11             sub new {
12 3     3 1 386 my ($class, @self) = @_;
13 3         9 my $self = bless \@self, $class;
14 3         19 $self->me( { current => 0, count => 0 } );
15 3         9 return $self;
16             }
17              
18             sub me {
19 2970     2970 1 5214 my ($self, $args) = @_;
20 2970         4562 my $loc = refaddr $self;
21 2970 100       4621 $DATA{$loc} = $args if $args;
22 2970         6205 return $DATA{$loc};
23             }
24              
25             sub current {
26 23     23 1 4857 my ($self) = @_;
27 23         56 return $self->[ $self->me->{current} ];
28             }
29              
30             *curr = \¤t;
31              
32             sub index {
33 110     110 1 361 my ($self, $idx) = @_;
34 110 50       203 $self->me->{current} = $idx if defined $idx;
35 110         163 return $self->me->{current};
36             }
37              
38             sub loops {
39 19     19 1 45 my ($self, $new_ct) = @_;
40 19 50       49 $self->me->{count} = $new_ct if defined $new_ct;
41 19         38 return $self->me->{count};
42             }
43              
44             sub next {
45 595     595 1 32689 my ($self, $num) = @_;
46 595 100       1061 return unless @$self;
47 585 50 66     1261 return $self->current if defined $num && $num == 0; # undefined just goes next. zero gives current.
48 585 100       949 if ($num) {
49 102 100       194 croak "Calls to next with a count of how many to go forward must be a positive number" if $num < 0;
50 101         124 $num--;
51 101         287 $self->next for 1 .. $num; # This is inefficient but simple. Could use $self->me to compute where we are as optimisation
52             }
53              
54              
55 584         716 my $last_index = $#{$self};
  584         874  
56 584 100       974 if ( $self->me->{current} == $last_index ) {
57 125         208 $self->me->{current} = -1;
58 125         212 $self->me->{count}++;
59             }
60 584         968 return $self->[ ++ $self->me->{current} ];
61             }
62              
63             sub previous {
64 566     566 1 4128 my ($self, $num) = @_;
65 566 50       932 return unless @$self;
66              
67 566 100       902 if ($num) {
68 101 50       187 croak "Calls to next with a count of how many to go forward must be a positive number" if $num < 0;
69 101         126 $num--;
70 101         228 $self->previous for 1 .. $num; # This is inefficient but simple. Could use $self->me to compute where we are as optimisation
71             }
72              
73 566 100       849 if ( $self->me->{current} == 0 ) {
74 115         187 $self->me->{current} = scalar(@$self);
75 115         190 $self->me->{count}--;
76              
77             }
78 566         888 return $self->[ -- $self->me->{current} ];
79             }
80              
81             *prev = \&previous;
82              
83             sub reset {
84 2     2 1 9 my ($self) = @_;
85 2         5 $self->me->{current} = 0;
86 2         5 $self->me->{count} = 0;
87 2         5 return $self->current;
88             }
89              
90             sub _current_and_action {
91 0     0   0 my ($self, $action) = @_;
92 0         0 my $c = $self->current;
93 0         0 $self->$action;
94 0         0 return $c
95             }
96              
97             sub current_and_next {
98 0     0 1 0 my ($self) = @_;
99 0         0 return $self->_current_and_action('next');
100             }
101              
102             *curr_and_next = \¤t_and_next;
103              
104             sub current_and_previous {
105 0     0 1 0 my ($self) = @_;
106 0         0 return $self->_current_and_action('previous');
107             }
108              
109             *curr_and_prev = \&curr_and_prev;
110              
111             sub peek {
112 110     110 1 58037 my ($self, $count) = @_;
113 110 100       296 return $self->current if $count == 0;
114 100 50       207 my $meth = $count > 0 ? 'next': 'prev';
115 100 50       183 my $undo = $count > 0 ? 'prev': 'next';
116 100         142 $count = abs $count;
117 100         261 my $val = $self->$meth($count);
118 100         276 $self->$undo($count);
119 100         254 return $val;
120             }
121              
122             sub size {
123 121     121 1 7441 my ($self ) = @_;
124 121         277 return scalar @$self;
125             }
126              
127              
128              
129             sub DESTROY {
130 3     3   5387 my $self = shift;
131 3         393 delete $DATA{refaddr $self};
132             }
133              
134             1;
135              
136             __END__