File Coverage

blib/lib/Doubly/Linked/PP.pm
Criterion Covered Total %
statement 155 161 96.2
branch 40 48 83.3
condition 6 12 50.0
subroutine 27 27 100.0
pod 0 23 0.0
total 228 271 84.1


line stmt bran cond sub pod time code
1             package Doubly::Linked::PP;
2              
3 22     22   2854369 use 5.006;
  22         105  
4 22     22   121 use strict;
  22         51  
  22         826  
5 22     22   153 use warnings;
  22         61  
  22         41214  
6              
7             our $VERSION = '0.06';
8              
9             sub new {
10 101076     101076 0 4152027 my ($pkg, $data) = @_;
11              
12 101076   66     421377 return bless {
13             data => $data,
14             next => undef,
15             prev => undef
16             }, ref $pkg || $pkg;
17             }
18              
19             sub length {
20 1     1 0 4 my ($self) = @_;
21              
22 1 50 33     8 my $i = $self->{next} || $self->{data} ? 1 : 0;
23              
24 1         4 while ($self->next) {
25 99999         146237 $self = $self->next;
26 99999         145367 $i++;
27             }
28              
29 1         22 return $i;
30             }
31              
32             sub start {
33 33     33 0 98 my ($self) = @_;
34              
35 33         107 while ($self->prev) {
36 19         52 $self = $self->prev;
37             }
38              
39 33         111 return $self;
40             }
41              
42             sub is_start {
43 6 50   6 0 39 if ($_[0]->prev) {
44 0         0 return 0;
45             }
46 6         30 return 1;
47             }
48              
49             sub end {
50 101044     101044 0 158636 my ($self) = @_;
51              
52 101044         171700 while ($self->next) {
53 103014         110282 $self = $self->next;
54             }
55              
56 101044         158263 return $self;
57             }
58              
59             sub is_end {
60 4 50   4 0 17 if ($_[0]->next) {
61 0         0 return 0;
62             }
63 4         30 return 1;
64             }
65              
66 101 100   101 0 348 sub data { $_[0]->{data} = $_[1] if $_[1]; $_[0]->{data} }
  101         552  
67              
68 507130     507130 0 804865 sub next { $_[0]->{next} }
69              
70 200087     200087 0 400963 sub prev { $_[0]->{prev} }
71              
72             sub bulk_add {
73 4     4 0 14524 my ($self, @items) = @_;
74 4         22 $self = $self->end;
75 4         12 for (@items) {
76 101010         184833 $self = $self->insert_at_end($_);
77             }
78 4         2449 return $self;
79             }
80              
81             sub add {
82 8     8 0 35 $_[0]->insert_at_end($_[1]);
83             }
84              
85             sub insert {
86 3     3 0 5 my ($self, $cb, $data) = @_;
87              
88 3 100       8 if (_is_undef($self)) {
89 1         2 $self->{data} = $data;
90 1         4 return $self;
91             }
92              
93 2         6 $self = $self->find($cb);
94              
95 2         7 return $self->insert_before($data);
96             }
97              
98             sub insert_before {
99 6     6 0 26 my ($self, $data) = @_;
100              
101 6 100       21 if (_is_undef($self)) {
102 1         2 $self->{data} = $data;
103 1         6 return $self;
104             }
105              
106 5         18 my $node = $self->new($data);
107              
108 5         13 $node->{next} = $self;
109              
110 5 50       18 if ($self->{prev}) {
111 0         0 $node->{prev} = $self->{prev};
112 0         0 $self->{prev}->{next} = $node;
113             }
114              
115 5         8 $self->{prev} = $node;
116              
117 5         21 return $node;
118             }
119              
120             sub insert_after {
121 18     18 0 54 my ($self, $data) = @_;
122              
123 18 100       60 if (_is_undef($self)) {
124 1         3 $self->{data} = $data;
125 1         5 return $self;
126             }
127              
128 17         79 my $node = $self->new($data);
129              
130 17         43 $node->{prev} = $self;
131              
132 17 100       77 if ($self->{next}) {
133 1         3 $node->{next} = $self->{next};
134 1         4 $self->{next}->{prev} = $node;
135             }
136              
137 17         38 $self->{next} = $node;
138              
139 17         71 return $node;
140             }
141              
142             sub insert_at_start {
143 15     15 0 50 my ($self, $data) = @_;
144              
145 15 100       68 if (_is_undef($self)) {
146 13         33 $self->{data} = $data;
147 13         67 return $self;
148             }
149              
150 2         7 $self = $self->start();
151              
152 2         7 my $node = $self->new($data);
153              
154 2         5 $self->{prev} = $node;
155 2         3 $node->{next} = $self;
156              
157 2         10 return $node;
158             }
159              
160             sub insert_at_end {
161 101033     101033 0 166573 my ($self, $data) = @_;
162              
163 101033 100       164379 if (_is_undef($self)) {
164 8         20 $self->{data} = $data;
165 8         39 return $self;
166             }
167              
168 101025         175488 $self = $self->end();
169              
170 101025         187201 my $node = $self->new($data);
171              
172 101025         165868 $self->{next} = $node;
173 101025         145591 $node->{prev} = $self;
174              
175 101025         186812 return $node;
176             }
177              
178             sub insert_at_pos {
179 3     3 0 10 my ($self, $pos, $data) = @_;
180              
181 3 100       9 if (_is_undef($self)) {
182 1         3 $self->{data} = $data;
183 1         5 return $self;
184             }
185              
186 2         9 $self = $self->start;
187              
188 2         8 for (my $i = 0; $i < $pos; $i++) {
189 3 100       11 if ($self->{next}) {
190 1         4 $self = $self->{next};
191             }
192             }
193              
194 2         6 return $self->insert_after($data);
195             }
196              
197             sub remove {
198 100027     100027 0 165903 my ($self) = @_;
199              
200 100027 100       173134 if (_is_undef($self)) {
201 2         7 return undef;
202             }
203              
204 100025         160841 my $prev = $self->{prev};
205 100025         149501 my $next = $self->{next};
206 100025         142280 my $data = $self->{data};
207              
208 100025 100       165485 if ($prev) {
    100          
209 100010 100       170767 if ($next) {
210 2         5 $next->{prev} = $prev;
211 2         6 $prev->{next} = $next;
212 2         4 %{$self} = %{$next};
  2         9  
  2         6  
213             } else {
214 100008         161224 $prev->{next} = undef;
215 100008         143765 %{$self} = %{$prev};
  100008         246908  
  100008         200451  
216             }
217             } elsif ($next) {
218 6         20 $next->{prev} = undef;
219 6         12 %{$self} = %{$next};
  6         22  
  6         16  
220             } else {
221 9         20 $self->{data} = undef;
222             }
223              
224 100025         189435 return $data;
225             }
226              
227             sub remove_from_start {
228 8     8 0 24 my ($self) = @_;
229              
230 8 100       23 if (_is_undef($self)) {
231 2         6 return undef;
232             }
233              
234 6         22 $self = $self->start();
235              
236 6         15 return $self->remove();
237             }
238              
239             sub remove_from_end {
240 6     6 0 11 my ($self) = @_;
241              
242 6 50       13 if (_is_undef($self)) {
243 0         0 return undef;
244             }
245              
246 6         12 $self = $self->end();
247              
248 6         14 return $self->remove();
249             }
250              
251             sub remove_from_pos {
252 4     4 0 13 my ($self, $pos) = @_;
253              
254 4 100       11 if (_is_undef($self)) {
255 1         6 return undef;
256             }
257              
258 3         9 $self = $self->start();
259              
260 3         11 for (my $i = 0; $i < $pos; $i++) {
261 3 50       9 if ($self->{next}) {
262 3         11 $self = $self->{next};
263             }
264             }
265              
266 3         9 return $self->remove();
267             }
268              
269             sub find {
270 3     3 0 7 my ($self, $cb) = @_;
271              
272 3         9 $self = $self->start;
273              
274 3 100       40 if ( $cb->($self->data) ) {
275 2         9 return $self;
276             }
277            
278 1         10 while ($self->next) {
279 1         4 $self = $self->next;
280              
281 1 50       23 if ( $cb->($self->data) ) {
282 1         11 return $self;
283             }
284             }
285              
286 0         0 die "No match found for find cb";
287             }
288              
289             sub destroy {
290 1     1 0 3 my ($self) = @_;
291 1         2 my $orig = $self;
292 1         5 $self = $self->end;
293 1         8 while ($self->prev) {
294 100001         170441 my $next = $self->prev;
295 100001         222950 $self->remove();
296 100001         257139 $self = $next;
297             }
298 1         4 $self->remove();
299 1         2 %{$orig} = %{$self};
  1         2  
  1         3  
300 1         5 $orig;
301             }
302              
303             sub _is_undef {
304 201123     201123   296903 my ($self) = shift;
305              
306 201123 50 66     393304 if ($self->{data} || $self->{prev} || $self->{next}) {
      33        
307 201093         441792 return 0;
308             }
309 30         93 return 1;
310             }
311              
312              
313             1;
314              
315             __END__