File Coverage

blib/lib/List/DoubleLinked.pm
Criterion Covered Total %
statement 95 105 90.4
branch 20 40 50.0
condition 4 12 33.3
subroutine 20 22 90.9
pod 15 15 100.0
total 154 194 79.3


line stmt bran cond sub pod time code
1             #
2             # This file is part of List-DoubleLinked
3             #
4             # This software is copyright (c) 2011 by Leon Timmermans.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9             package List::DoubleLinked;
10             BEGIN {
11 1     1   88180 $List::DoubleLinked::VERSION = '0.003';
12             }
13              
14 1     1   10 use strict;
  1         2  
  1         46  
15 1     1   10 use warnings FATAL => 'all';
  1         2  
  1         57  
16              
17 1     1   12 use Carp qw/carp/;
  1         2  
  1         55  
18 1     1   6 use Scalar::Util 'weaken';
  1         2  
  1         50  
19 1     1   1369 use namespace::clean 0.20;
  1         27887  
  1         8  
20             #no autovivication;
21              
22             sub new {
23 1     1 1 13 my ($class, @items) = @_;
24 1         6 my $self = bless {
25             head => undef,
26             tail => undef,
27             size => 0,
28             }, $class;
29 1         6 $self->push(@items);
30 1         3 return $self;
31             }
32              
33             ## no critic (Subroutines::ProhibitBuiltinHomonyms, ControlStructures::ProhibitCStyleForLoops)
34              
35             sub push {
36 3     3 1 1333 my ($self, @items) = @_;
37 3         10 for my $item (@items) {
38 4         236 my $new_tail = {
39             item => $item,
40             prev => $self->{tail},
41             next => undef,
42             };
43 4 100       21 $self->{tail}{next} = $new_tail if defined $self->{tail};
44 4         8 $self->{tail} = $new_tail;
45 4 100       14 $self->{head} = $new_tail if not defined $self->{head};
46 4         10 $self->{size}++;
47             }
48 3         8 return;
49             }
50              
51             sub pop {
52 1     1 1 2 my $self = shift;
53 1         3 my $ret = $self->{tail};
54 1 50       6 return if not defined $ret;
55 1         4 $self->{tail} = $ret->{prev};
56 1 50       6 $self->{tail}{next} = undef if defined $self->{tail};
57 1         3 $self->{size}--;
58 1         8 return $ret->{item};
59             }
60              
61             sub unshift {
62 1     1 1 4 my ($self, @items) = @_;
63 1         6 for my $item (reverse @items) {
64 1         6 my $new_head = {
65             item => $item,
66             prev => undef,
67             next => $self->{head},
68             };
69 1 50       7 $self->{head}{prev} = $new_head if defined $self->{head};
70 1         3 $self->{head} = $new_head;
71 1 50       4 $self->{tail} = $new_head if not defined $self->{tail};
72 1         5 $self->{size}++;
73             }
74 1         3 return;
75             }
76              
77             sub shift {
78 0     0 1 0 my $self = CORE::shift;
79 0         0 my $ret = $self->{head};
80 0 0       0 return if not defined $ret;
81 0         0 $self->{head} = $ret->{next};
82 0 0       0 $self->{head}{prev} = undef if defined $self->{tail};
83 0         0 $self->{size}--;
84 0         0 return $ret->{item};
85             }
86              
87             sub flatten {
88 7     7 1 23 my $self = CORE::shift;
89 7         10 my @ret;
90 7         31 for (my $current = $self->{head} ; defined $current ; $current = $current->{next}) {
91 23         76 CORE::push @ret, $current->{item};
92             }
93 7         78 return @ret;
94             }
95              
96             sub front {
97 1     1 1 3 my $self = CORE::shift;
98 1 50       10 return defined $self->{head} ? $self->{head}{item} : undef;
99             }
100              
101             sub back {
102 1     1 1 3 my $self = CORE::shift;
103 1 50       14 return defined $self->{tail} ? $self->{tail}{item} : undef;
104             }
105              
106             sub empty {
107 2     2 1 8 my $self = CORE::shift;
108 2         19 return not $self->{size};
109             }
110              
111             sub size {
112 2     2 1 5 my $self = CORE::shift;
113 2         14 return $self->{size};
114             }
115              
116             sub insert_before {
117 1     1 1 2 my ($self, $iter, @items) = @_;
118 1         7 my $node = $iter->[0];
119 1         3 for my $item (@items) {
120 2         9 my $new_node = {
121             item => $item,
122             prev => $node->{prev},
123             next => $node,
124             };
125 2 50       8 $node->{prev}{next} = $new_node if defined $node->{prev};
126 2         4 $node->{prev} = $new_node;
127              
128 2 50 33     14 $self->{head} = $node->{next} if defined $self->{head} and $self->{head} == $node;
129 2         6 $self->{size}++;
130             }
131 1         4 return;
132             }
133              
134             sub insert_after {
135 1     1 1 10 my ($self, $iter, @items) = @_;
136 1         9 my $node = $iter->[0];
137 1         9 for my $item (@items) {
138 2         14 my $new_node = {
139             item => $item,
140             prev => $node,
141             next => $node->{next},
142             };
143 2 50       14 $node->{next}{prev} = $new_node if defined $node->{next};
144 2         6 $node->{next} = $new_node;
145              
146 2 50 33     28 $self->{tail} = $new_node if defined $self->{tail} and $self->{tail} == $node;
147 2         5 $node = $new_node;
148 2         9 $self->{size}++;
149             }
150 1         9 return;
151             }
152              
153             sub erase {
154 1     1 1 2 my ($self, $node) = @_;
155              
156 1 50       6 $node->{prev}{next} = $node->{next} if defined $node->{prev};
157 1 50       4 $node->{next}{prev} = $node->{prev} if defined $node->{next};
158              
159 1 50 33     9 $self->{head} = $node->{next} if defined $self->{head} and $self->{head} == $node;
160 1 50 33     8 $self->{tail} = $node->{previous} if defined $self->{tail} and $self->{tail} == $node;
161              
162 1         2 $self->{size}--;
163 1         5 weaken $node;
164 1 50       3 carp 'Node may be leaking' if $node;
165              
166 1         2 return;
167             }
168              
169             sub begin {
170 1     1 1 3 my $self = CORE::shift;
171 1         1184 require List::DoubleLinked::Iterator;
172              
173 1         11 return List::DoubleLinked::Iterator->new($self, $self->{head});
174             }
175              
176             sub end {
177 0     0 1 0 my $self = CORE::shift;
178 0         0 require List::DoubleLinked::Iterator;
179              
180 0         0 return List::DoubleLinked::Iterator->new($self->{tail});
181             }
182              
183             sub DESTROY {
184 1     1   13 my $self = CORE::shift;
185 1         4 my $current = $self->{head};
186 1         6 while ($current) {
187 7         19 delete $current->{prev};
188 7         13 $current = delete $current->{next};
189 7         16 $self->{size}--;
190             }
191 1 50       8 warn "Size of Linked List is $self->{size}, should be 0 after DESTROY" if $self->{size} != 0;
192 1         12 return;
193             }
194              
195             # ABSTRACT: Double Linked Lists for Perl
196              
197             1;
198              
199              
200             __END__