File Coverage

blib/lib/List/Object.pm
Criterion Covered Total %
statement 173 188 92.0
branch 44 56 78.5
condition 9 12 75.0
subroutine 32 35 91.4
pod 24 27 88.8
total 282 318 88.6


line stmt bran cond sub pod time code
1             package List::Object;
2 1     1   33537 use 5.008003;
  1         4  
  1         48  
3 1     1   7 use strict;
  1         2  
  1         35  
4 1     1   5 use warnings;
  1         7  
  1         29  
5              
6             # $Id$
7             # $Name$
8              
9 1     1   6 use Carp;
  1         2  
  1         2832  
10             #use Data::Dumper;
11              
12             require Exporter;
13              
14             our @ISA = qw(Exporter);
15              
16             # Items to export into callers namespace by default. Note: do not export
17             # names by default without a very good reason. Use EXPORT_OK instead.
18             # Do not simply export all your public functions/methods/constants.
19              
20             # This allows declaration use List::Object ':all';
21             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
22             # will save memory.
23             our %EXPORT_TAGS = ( 'all' => [ qw(
24            
25             ) ] );
26              
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
28              
29             our @EXPORT = qw(
30            
31             );
32              
33             our $VERSION = '0.01';
34              
35             my %types = (
36             '' => '',
37             '$' => 'SCALAR',
38             '@' => 'ARRAY',
39             '%' => 'HASH',
40             );
41              
42             my %rev_types = map { ($types{$_}, $_) } (keys %types);
43              
44             #print "HELLO!!!!\n";
45              
46             ###################################################################
47             sub new
48             { #
49 6     6 1 3426 my $class = CORE::shift;
50 6         16 my @args = @_;
51 6         9 my $this = {};
52              
53 6         15 bless $this, $class;
54 6         19 $this->_init(@args);
55 6         14 return $this;
56             }
57              
58             ###################################################################
59             sub _init
60             { #
61 6     6   8 my $this = CORE::shift;
62 6         14 my %args = @_;
63 6 100       31 $this->{_type} = defined $args{type} ? $args{type} : '%';
64 6 50       18 $this->{_allow_undef} = defined $args{allow_undef} ? $args{allow_undef} : '0';
65              
66 6 100       12 if (defined $args{list})
67             { #
68 3         6 $this->_valid_type(@{$args{list}});
  3         8  
69 3         7 $this->{_array} = $args{list};
70             }
71             else
72             {
73 3         7 $this->{_array} = [];
74             }
75 6         18 $this->rewind();
76             }
77              
78             ###################################################################
79             sub _valid_type
80             { #
81 92 100 100 92   367 return 1 if defined $List::Object::Loose && $List::Object::Loose == 1;
82             # done a second time to suppress the
83             # 'used only once: possible typo' perl warning
84              
85 91         93 my $this = shift;
86 91         304 my @check_list = @_;
87              
88 91         1113 my $valid = 1;
89 91         87 my $undef = 0;
90 91         113 for my $c (@check_list)
91             {
92 112 100 66     338 if (! $this->{_allow_undef} && ! defined $c)
93             { #
94 2         5 $undef = 1;
95 2         4 last;
96             }
97            
98 110         307 my $ref_type = ref $c;
99            
100 110 100       202 if (defined $c)
101             {
102             # are we and object (not a HASH, ARRAY, or SCALAR reftype?);
103 109 100       173 if (exists $rev_types{$ref_type})
104             {
105 27 100       103 unless (ref $c eq $types{$this->{_type}})
106             {
107 1         1 $valid = 0;
108 1         2 last;
109             }
110              
111             }
112             else
113             { #
114 82 100       622 unless ($c->isa($this->{_type}))
115             { #
116 2         4 $valid = 0;
117 2         6 last;
118             }
119             }
120             }
121            
122             }
123            
124 91 100 66     530 croak(__PACKAGE__ . " undef items not allows in list. ") if $undef && ! $this->{_allow_undef};
125 89 100       159 croak(__PACKAGE__ . " item is not valid ref type of '@{[$this->{_type}]}'") unless $valid;
  3         525  
126 86         134 return 1;
127             }
128              
129             # decrement the iterator location by one
130             # if the iterator is non-zero, and the
131             # list has been shortened below where
132             # the index is at;
133             ###################################################################
134             sub _fix_index
135             { #
136 0     0   0 croak "method not implemented";
137 0         0 my $this = shift;
138 0         0 my $changed_index = shift;
139             }
140              
141             ###################################################################
142             sub has_next
143             { #
144 3     3 1 9 return $_[0]->{_index} < @{$_[0]->{_array}} - 1;
  3         201  
145             }
146              
147             ###################################################################
148             sub next
149             { #
150 10     10 1 692 my $this = shift;
151 10 100       13 croak "index out of range" if $this->{_index} >= @{$this->{_array}} - 1;
  10         400  
152 9         21 $this->_valid_type($this->{_array}->[$this->{_index}]);
153 9         20 return $this->{_array}->[++$this->{_index}];
154             }
155              
156             ###################################################################
157             sub rewind
158             { #
159 48     48 1 885 $_[0]->{_index} = 0;
160 48         64 return 1;
161             }
162              
163             ###################################################################
164             sub shift
165             { #
166 1     1 1 6 $_[0]->_valid_type($_[0]->{_array}->[$_[0]->{_index}]);
167 1         4 $_[0]->rewind();
168            
169 1         2 shift @{$_[0]->{_array}};
  1         3  
170             }
171              
172             ###################################################################
173             sub push
174             { #
175 28     28 1 2084 my $this = CORE::shift;
176 28         43 my @pushed = @_;
177 28         49 $this->_valid_type(@pushed);
178 25         47 $this->rewind();
179 25         30 CORE::push @{$this->{_array}}, @pushed;
  25         80  
180             }
181              
182             ###################################################################
183             sub pop
184             { #
185 2     2 1 670 my $this = CORE::shift;
186 2         7 $this->rewind();
187 2         7 $this->_valid_type($this->{_array}->[$this->{_index}]);
188 2         3 CORE::pop @{$this->{_array}};
  2         7  
189             }
190              
191              
192             ###################################################################
193             sub unshift
194             { #
195 2     2 1 782 my $this = CORE::shift;
196 2         5 my @unshifted = @_;
197 2         5 $this->rewind();
198 2         7 $this->_valid_type(@unshifted);
199 1         1 CORE::unshift @{$this->{_array}}, @unshifted;
  1         5  
200             }
201              
202             ###################################################################
203             sub splice
204             { #
205 3     3 1 548 my $this = CORE::shift;
206              
207 3         6 $this->rewind();
208 3         5 my $offset = 0;
209 3         4 my $length = 0;
210 3         6 my @list = ();
211              
212 3 50       10 $offset = CORE::shift if @_;
213 3 50       7 $length = CORE::shift if @_;
214 3 100       9 @list = @_ if @_;
215 3         6 $this->_valid_type(@list);
216 3         4 splice @{$this->{_array}}, $offset, $length, @list;
  3         12  
217             }
218              
219             ###################################################################
220             sub join
221             { #
222 3     3 1 1155 my $this = CORE::shift;
223 3         39 my $join = '';
224            
225 3 100       15 if ($this->{_type} eq '')
    100          
226             { #
227 1 50       4 $join = CORE::shift if @_;
228 1         2 return CORE::join $join, @{$this->{_array}};
  1         4  
229             }
230             elsif($this->{_type} eq '$')
231             { #
232 1 50       4 $join = CORE::shift if @_;
233 1         2 return CORE::join $join, map { $$_} @{$this->{_array}};
  4         7  
  1         3  
234             }
235             else
236             { #
237 1         133 carp("Can't join non-scalar ref types, returning empty string.");
238 1         65 return '';
239            
240             }
241             }
242              
243             ###################################################################
244             sub count
245             { #
246 31     31 1 80 my $this = CORE::shift;
247 31         32 return scalar @{$this->{_array}};
  31         159  
248             }
249              
250             ###################################################################
251             sub clear
252             { #
253            
254 1     1 1 248 $_[0]->{_array} = [];
255 1         9 return 1;
256             }
257              
258             ###################################################################
259             sub get
260             { #
261 5     5 1 928 my $this = CORE::shift;
262 5         6 my $index = CORE::shift;
263 5 50       11 croak "index out of range" if $index >= $this->count();
264 5         18 $this->_valid_type($this->{_array}->[$index]);
265 5         17 return $this->{_array}->[$index];
266             }
267              
268             ###################################################################
269             sub set
270             { #
271 1     1 1 363 my $this = CORE::shift;
272 1         3 my $index = CORE::shift;
273 1         1 my $item = CORE::shift;
274 1 50       3 croak "index out of range" if $index >= $this->count();
275 1         4 $this->_valid_type($item);
276 1         3 $this->{_array}->[$index] = $item;
277             }
278              
279             ###################################################################
280             sub add
281             { #
282 21     21 1 568 my $this = CORE::shift;
283 21         40 $this->_valid_type(@_);
284 20         41 return $this->push(@_);
285             }
286              
287              
288             ###################################################################
289             sub remove
290             { #
291 1     1 1 349 my $this = CORE::shift;
292 1         2 my $index = CORE::shift;
293 1         4 my $rm_item = $this->splice($index, 1);
294 1         3 $this->_valid_type($rm_item);
295 1         4 $this->rewind();
296 1         3 return $rm_item;
297             }
298              
299              
300             ###################################################################
301             sub first
302             { #
303 7     7 1 28 my $this = CORE::shift;
304 7         23 $this->_valid_type($this->{_array}->[0]);
305 7         32 return $this->{_array}->[0];
306             }
307              
308             ###################################################################
309             sub last
310             { #
311 7     7 1 1553 my $this = CORE::shift;
312 7         23 $this->_valid_type($this->{_array}->[$this->count() - 1]);
313 7         16 return $this->{_array}->[$this->count() - 1];
314             }
315              
316             ###################################################################
317             sub peek
318             { #
319 2     2 1 8 my $this = CORE::shift;
320              
321 2         8 $this->_valid_type($this->{_array}->[$this->{_index}]);
322 2         7 return $this->{_array}->[$this->{_index}];
323             }
324              
325             ###################################################################
326             sub type
327             { #
328 4     4 1 522 return $_[0]->{_type};
329             }
330              
331             ###################################################################
332             sub allow_undef
333             { #
334 2     2 1 621 return $_[0]->{_allow_undef};
335            
336             }
337              
338             ###################################################################
339             sub array
340             { #
341 1     1 1 333 my $this = CORE::shift;
342 1         2 return @{$this->{_array}};
  1         6  
343             }
344              
345             ###################################################################
346             sub reverse
347             { #
348 1     1 0 329 my $this = CORE::shift;
349 1         3 $this->rewind();
350 1         2 $this->{_array} = [reverse @{$this->{_array}}] ;
  1         5  
351             }
352              
353             ###################################################################
354             sub sort
355             { #
356 2     2 1 10 my $this = CORE::shift;
357 2 100       12 if ($this->{_type} eq '')
    50          
358             { #
359 1         3 $this->rewind();
360 1         2 $this->{_array} = [sort @{$this->{_array}}];
  1         10  
361             }
362             elsif($this->{_type} eq '$')
363             { #
364             # look how nested this is!!!
365 1         3 $this->{_array} = [map {\$_} (sort (map {$$_} @{$this->{_array}})) ]
  4         7  
  4         9  
  1         2  
366             }
367             else
368             {
369 0         0 carp "Can't sort non-scalar ref types. Nothing done.";
370             }
371             }
372              
373             ###################################################################
374             sub sort_by
375             { #
376 4     4 1 824 my $this = CORE::shift;
377 4         7 my $sort_by = CORE::shift;
378              
379 4         9 $this->rewind();
380            
381 4         6 my $type = $this->{_type};
382              
383             my $sort_sub = sub { #
384 91     91   578 my $av = CORE::shift;
385 91         85 my $bv = CORE::shift;
386              
387 91 100 66     337 if ($av =~ /^[\d\.]+$/ && $bv =~ /^[\d\.]+$/)
388             {
389 22         56 return $av <=> $bv;
390             }
391             else
392             { #
393 69         131 return $av cmp $bv;
394             }
395 4         18 };
396              
397 4 100       17 if (! defined $types{$type})
    50          
    0          
398             {
399             # sort list of objects method
400 3 50       28 $this->_error() unless $type->can($sort_by);
401 3         4 $this->{_array} = [ sort { &$sort_sub($a->$sort_by(), $b->$sort_by()) } @{$this->{_array}}];
  70         174  
  3         16  
402             }
403             elsif ($type eq '%')
404             {
405 1         1 $this->{_array} = [ sort { &$sort_sub($a->{$sort_by}, $b->{$sort_by}) } @{$this->{_array}}];
  21         36  
  1         6  
406             }
407             elsif ($type eq '@')
408             {
409 0           $this->{_array} = [ sort { &$sort_sub($a->[$sort_by], $b->[$sort_by]) } @{$this->{_array}}];
  0            
  0            
410             }
411             else
412             { #
413             # for lists of scalars and scalar refs, fall back to sort;
414 0           carp "Can't sory_by() on scalars and scalar refs, Falling back to sort()";
415 0           $this->sort();
416             }
417             }
418              
419             ###################################################################
420             sub unique_by
421             { #
422 0     0 0   croak "method not implemented";
423 0           my $this = CORE::shift;
424 0           my $type = $this->{_type};
425 0           my $method = CORE::shift;
426            
427             }
428              
429             ###################################################################
430             sub filter_by
431             { #
432 0     0 0   croak "method not implemented";
433 0           my $this = CORE::shift;
434             }
435              
436             1;
437             __END__