File Coverage

blib/lib/List/Priority.pm
Criterion Covered Total %
statement 71 71 100.0
branch 18 24 75.0
condition 4 6 66.6
subroutine 16 16 100.0
pod 8 8 100.0
total 117 125 93.6


line stmt bran cond sub pod time code
1             package List::Priority;
2              
3 4     4   95378 use 5.006;
  4         12  
  4         128  
4 4     4   18 use strict;
  4         5  
  4         113  
5 4     4   25 use warnings;
  4         10  
  4         114  
6 4     4   23 use vars qw($VERSION);
  4         5  
  4         240  
7 4     4   17 use Carp;
  4         6  
  4         377  
8 4     4   32 use List::Util qw/min max/;
  4         8  
  4         2955  
9              
10             $VERSION = '0.05';
11              
12              
13             # Constructor. Enables Inheritance
14             sub new {
15 5     5 1 62 my $this = shift;
16 5   33     40 my $class = ref($this) || $this;
17 5         10 my $self = {};
18 5         14 bless $self, $class;
19 5 100       17 if (@_) {
20 2         6 my %options = @_;
21 2         9 $self->{options} = \%options;
22             }
23 5         40 $self->{size} = 0;
24 5         18 return $self;
25             }
26              
27             # Insert an element into the list
28             sub insert {
29             # Arguments check
30 150 50   150 1 529 croak 'List::Priority - Expected 3 arguments!' if (scalar(@_) != 3);
31             # Argument assignment
32 150         196 (my $self, my $priority, my $object) = @_;
33             # Check that priority is numeric - Thanks Randel/Joseph!
34 150 50       267 croak 'List::Priority - Priority must be numeric!'
35             if ((~$priority & $priority) ne '0');
36             # If the list is full
37 150 100 100     387 if (defined($self->{options}{capacity}) and
38             $self->{options}{capacity} <= $self->{size}) {
39 15         16 my ($bottom_priority) = min(keys %{$self->{queues}});
  15         73  
40             # And the object's priority is higher than the lowest on the list
41             # - remove the lowest one to insert it
42 15 100       29 if ($priority > $bottom_priority) {
43 14         27 $self->_extract($bottom_priority);
44             }
45             # Else, just return - the list is full.
46             else {
47 1         2 return 'List::Priority - Object denied, list is full';
48             }
49             }
50             # Insert
51 149         159 push(@{$self->{queues}{$priority}}, $object);
  149         359  
52 149         170 ++$self->{size};
53 149         269 return 1;
54             }
55              
56             # Helper method for pop() and shift()
57             # If $priority is defined, return the first-in element with that priority.
58             # Otherwise, use $minmax() to find the best priority in the set, and
59             # extract the first element with that priority.
60             sub _extract {
61 25     25   32 my ($self, $priority) = @_;
62 25 50       56 return undef if ($self->{size} == 0);
63 25 50       44 return undef unless (defined ($priority));
64             # Remove the queue's first element
65 25         22 my $object = CORE::shift (@{$self->{queues}{$priority}});
  25         47  
66             # If the queue is now empty - delete it
67 25         101 delete $self->{queues}{$priority}
68 25 100       27 if (scalar(@{$self->{queues}{$priority}}) == 0);
69             # Return the object I just shifted out of the queue
70 25         32 --$self->{size};
71 25         87 return $object;
72             }
73              
74             # Find out the extreme (top or bottom) priority
75             sub _extreme_priority {
76 11     11   31 my ($self, $minmax) = @_;
77 11         15 return $minmax->(keys %{$self->{queues}});
  11         97  
78             }
79              
80             sub highest_priority {
81 6     6 1 7 my $self = shift;
82 6         20 return $self->_extreme_priority(\&max);
83             }
84              
85             sub lowest_priority {
86 5     5 1 8 my $self = shift;
87 5         14 return $self->_extreme_priority(\&min);
88             }
89              
90             sub pop {
91             # Arguments check
92 6 50   6 1 25 croak 'List::Priority - pop expected 1 argument' if (scalar(@_) != 1);
93 6         8 my ($self) = @_;
94 6         18 return $self->_extract($self->highest_priority);
95             }
96              
97             sub shift {
98             # Arguments check
99 5 50   5 1 19 croak 'List::Priority - shift expected 1 argument' if (scalar(@_) != 1);
100 5         7 my ($self) = @_;
101 5         12 return $self->_extract($self->lowest_priority);
102             }
103              
104             sub size {
105 27     27 1 69 my ($self) = @_;
106 27         160 return $self->{size};
107             }
108              
109             sub capacity {
110 4     4 1 15 my ($self, $new_capacity) = @_;
111 4 100       15 if (@_ > 1) {
112 3         7 $self->{options}{capacity} = $new_capacity;
113 3 100       7 if (defined $new_capacity) {
114 2         6 while ($self->size > $new_capacity) {
115 2         6 $self->shift;
116             }
117             }
118             }
119 4         11 return $self->{options}{capacity};
120             }
121              
122             1;
123             __END__