File Coverage

lib/Data/RefQueue.pm
Criterion Covered Total %
statement 24 106 22.6
branch 2 32 6.2
condition 1 6 16.6
subroutine 7 20 35.0
pod 1 17 5.8
total 35 181 19.3


line stmt bran cond sub pod time code
1             package Data::RefQueue;
2             # Data::RefQueue - Queue system based on references and scalars.
3             # (c) 2002 - Ask Solem
4             # All rights reserved.
5             #
6             # This program is free software; you can redistribute it and/or modify
7             # it under the terms of the GNU General Public License version 2
8             # as published by the Free Software Foundation.
9             #
10             # This program is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13             # GNU General Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License
16             # along with this program; if not, write to the Free Software
17             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18             #
19             #
20             # $Id: RefQueue.pm,v 1.1 2007/05/07 13:08:23 ask Exp $
21             # $Source: /opt/CVS/DataRefqueue/lib/Data/RefQueue.pm,v $
22             # $Author: ask $
23             # $HeadURL$
24             # $Revision: 1.1 $
25             # $Date: 2007/05/07 13:08:23 $
26             #####
27              
28 1     1   947 use 5.006;
  1         3  
  1         35  
29 1     1   6 use strict;
  1         1  
  1         36  
30 1     1   7 use vars qw($VERSION $DEBUG);
  1         2  
  1         1718  
31              
32             $DEBUG = 0;
33              
34             $VERSION = '0.4';
35              
36             # ### prototypes
37             sub new; # new RefQueue object.
38             sub set; # set queue values.
39             sub setpos; # set position.
40             sub getpos; # get position.
41             sub size; # return the number of elements in queue.
42             sub next; # set position to next element.
43             sub prev; # set position to previous element.
44             sub save; # save current position and set pos to next.
45             sub reset; # reset the position to the first element.
46             sub fetch; # fetch current position.
47             sub queue; # the queue itself.
48             sub filled; # return all filled positions.
49             sub delete; # delete (truncate) current element.
50             sub remove; # remove this element.
51             sub cleanse; # remove all positions not filled.
52             sub insert_at; # find the element that contains 'key' and replace key with value.
53             sub not_filled; # return all positions that isn't filled.
54              
55             # #### data::refqueue new(string pkg, array values)
56             # Create a new RefQueue queue starting with @values.
57             #
58             sub new {
59 1     1 1 362 my($class, @values) = @_;
60 1         3 my $self = { };
61 1         2 bless $self, $class;
62              
63 1 50       4 if (scalar @values) {
64 0         0 $self->set(@values);
65             }
66 1         6 $self->reset;
67              
68 1         3 return $self;
69             }
70              
71             # #### arrayref queue(data::refqueue q)
72             # The queue itself.
73             #
74             sub queue {
75 1     1 0 1 my ($self) = @_;
76 1   50     9 $self->{QUEUE} ||= [ ];
77 1         2 return $self->{QUEUE};
78             }
79              
80             # #### int setpos(data::refqueue q, int pos)
81             # Set current queue position.
82             # XXX: Wraps around if higher/lower than availible elements.
83             #
84             sub setpos {
85 0     0 0 0 my ($self, $pos) = @_;
86 0         0 my ($package, $filename, $line, $subroutine) = caller( );
87              
88 0 0       0 if ($pos >= 0) {
89              
90 0 0       0 if ($pos > $self->size) {
    0          
91 0         0 $pos = 0;
92             }
93             elsif ($pos < 0) {
94 0         0 $pos = $self->size;
95             }
96              
97 0         0 $self->{POS} = $pos;
98             }
99             }
100              
101             # #### int getpos(data::refqueue q)
102             # Get current queue position.
103             #
104             sub getpos {
105 0     0 0 0 my ($self) = @_;
106 0         0 return $self->{POS};
107             }
108              
109              
110             # #### int size(data::refqueue q)
111             # Return the number of elements in the queue.
112             #
113             sub size {
114 0     0 0 0 my ($self) = @_;
115 0         0 my $q = $self->queue;
116 0         0 return $#$q;
117             }
118              
119             # #### void set(data::refqueue q, array values)
120             # Initialize queue, with values @values.
121             #
122             sub set {
123 1     1 0 245 my ($self, @values) = @_;
124 1         3 my $q = $self->queue;
125 1 50       9 print {*STDERR} "SET ". join(", ", @values). "\n" if $DEBUG;
  0         0  
126 1         5 @$q = @values;
127             }
128              
129             # #### void next(data::refqueue q)
130             # Set position to the next availible position.
131             #
132             sub next {
133 0     0 0 0 my ($self) = @_;
134 0         0 my $pos = $self->getpos() + 1;
135 0   0     0 $pos ||= 1;
136 0         0 $self->setpos($pos);
137             }
138              
139             # #### void next(data::refqueue q)
140             # Set position to the previous availible position.
141             #
142             sub prev {
143 0     0 0 0 my ($self) = @_;
144 0         0 my $pos = $self->getpos() - 1;
145 0   0     0 $pos ||= 0;
146 0         0 $self->setpos($pos);
147             }
148              
149             # #### void reset(data::refqueue q)
150             # Set queue position to 0.
151             #
152             sub reset {
153 1     1 0 3 my ($self) = @_;
154 1         6 $self->{POS} = 0;
155             }
156              
157             # #### void cleanse(data::refqueue q)
158             # Remove all positions not filled.
159             sub cleanse {
160 0     0 0   my ($self) = @_;
161 0           my $q = $self->queue;
162             MAIN:
163 0           while (1) {
164             ELEMENT:
165 0           for (my $qi; $qi <= $self->size; $qi++) {
166 0 0         if (! ref $q->[$qi]) {
167 0           $self->remove($self->setpos($qi));
168 0           goto MAIN;
169             # We use iteration instead of recursion for performance.
170             # Therefore the goto.
171             }
172             }
173 0           last MAIN;
174             }
175             }
176              
177             # #### arrayref not_filled(data::refqueue q)
178             # Return an array with the values not filled.
179             #
180             sub not_filled {
181 0     0 0   my ($self) = @_;
182 0           my $q = $self->queue;
183 0           my @ret;
184 0           for (my $qi = 0; $qi <= $self->size; $qi++) {
185 0 0         if (! ref $q->[$qi]) {
186 0           push @ret, $q->[$qi];
187             }
188             }
189 0           return \@ret;
190             }
191              
192             # #### arrayref filled(data::refqueue q)
193             # Return an array with the values filled.
194             #
195             sub filled {
196 0     0 0   my ($self) = @_;
197 0           my $q = $self->queue;
198 0           my @ret;
199 0           for (my $qi = 0; $qi <= $self->size; $qi++) {
200 0 0         if (ref $q->[$qi]) {
201 0           push @ret, $q->[$qi];
202             }
203             }
204 0           return \@ret;
205             }
206              
207             # #### void* fetch(data::refqueue q)
208             # Fetch the value in the current position.
209             #
210             sub fetch {
211 0     0 0   my ($self) = @_;
212 0 0         print {*STDERR} "FETCH AT ".$self->getpos(). "\n" if $DEBUG;
  0            
213 0           return $self->queue->[$self->getpos()];
214             }
215              
216             # #### void delete(data::refqueue q)
217             # Delete the contents of the current position.
218             #
219             sub delete {
220 0     0 0   my ($self) = @_;
221 0 0         print {*STDERR} "DELETE AT ".$self->getpos(). "\n" if $DEBUG;
  0            
222 0           return delete $self->queue->[$self->getpos()];
223             }
224              
225             # #### void save(data::refqueue q, void* value)
226             # Save something into the current position and set position
227             # to the next availible element in the queue.
228             #
229             sub save {
230 0     0 0   my ($self, $value) = @_;
231 0 0         print {*STDERR} "SAVE AT ".$self->getpos(). "\n" if $DEBUG;
  0            
232 0           my $q = $self->queue;
233 0           $q->[$self->getpos()] = $value;
234 0           return $self->next;
235             }
236              
237             # ### void remove(data::refqueue)
238             # Remove the current position entirely, decrementing
239             # the size of the queue by one.
240             #
241             sub remove {
242 0     0 0   my ($self) = @_;
243 0           my $q = $self->queue;
244 0           my @copy;
245 0 0         print {*STDERR} "REMOVE AT ".$self->getpos(). "\n" if $DEBUG;
  0            
246 0           for (my $qi = 0; $qi <= $self->size; $qi++) {
247 0 0         if ($qi != $self->getpos()) {
248 0           push @copy, $q->[$qi];
249             }
250             }
251 0           $self->set(@copy);
252 0           return;
253             }
254              
255             # ### int insert_at(data::refqueue q, void* key, void* value)
256             # Find the element that contains 'key' and replace key with value.
257             #
258             sub insert_at {
259 0     0 0   my ($self, $key, $value) = @_;
260 0           my $orig_pos = $self->getpos();
261 0           my $q = $self->queue;
262 0 0         print {*STDERR} "INSERT AT $key $value\n" if $DEBUG;
  0            
263 0           for (my $qi = 0; $qi <= $self->size; $qi++) {
264 0 0         if ($q->[$qi] eq $key) {
265 0 0         print {*STDERR} "KEY '$key' IS AT ELEMENT NUMBER ;$qi;\n" if $DEBUG;
  0            
266 0           $self->setpos($qi);
267 0           $self->save($value);
268 0           $self->setpos($orig_pos);
269 0           return 1;
270             }
271             }
272 0           return;
273             }
274              
275             1;
276             __END__