File Coverage

blib/lib/Data/Sofu/List.pm
Criterion Covered Total %
statement 88 158 55.7
branch 17 30 56.6
condition 0 6 0.0
subroutine 19 34 55.8
pod 32 32 100.0
total 156 260 60.0


line stmt bran cond sub pod time code
1             ###############################################################################
2             #List.pm
3             #Last Change: 2009-28-01
4             #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch
5             #Version 0.3
6             ####################
7             #This file is part of the sofu.pm project, a parser library for an all-purpose
8             #ASCII file format. More information can be found on the project web site
9             #at http://sofu.sourceforge.net/ .
10             #
11             #sofu.pm is published under the terms of the MIT license, which basically means
12             #"Do with it whatever you want". For more information, see the license.txt
13             #file that should be enclosed with libsofu distributions. A copy of the license
14             #is (at the time of this writing) also available at
15             #http://www.opensource.org/licenses/mit-license.php .
16             ###############################################################################
17              
18             =head1 NAME
19              
20             Data::Sofu::List - A Sofu List
21              
22             =head1 DESCRIPTION
23              
24             Provides a interface similar to the original SofuD (sofu.sf.net)
25              
26             =head1 Synopsis
27              
28             require Data::Sofu::List;
29             my $list = Data::Sofu::List->new();
30             $list->appendElement(Data::Sofu::Value->new($_)) foreach (0 .. 10);;
31              
32             =head1 SYNTAX
33              
34             This Module is pure OO, exports nothing
35              
36             =cut
37              
38              
39             package Data::Sofu::List;
40 3     3   20 use strict;
  3         7  
  3         140  
41 3     3   22 use warnings;
  3         6  
  3         6153  
42             require Data::Sofu::Object;
43             our @ISA = qw/Data::Sofu::Object/;
44             our $VERSION="0.3";
45              
46             =head1 METHODS
47              
48             Also look at C for methods, cause List inherits from it
49              
50             =head2 new([DATA])
51             Creates a new C and returns it
52              
53             DATA has to be an Arrayhref
54              
55             $inc = Data::Sofu::List->new(\@INC);
56              
57             =cut
58              
59             sub new {
60 222     222 1 391 my $self={};
61 222         711 $self->{List}=[];
62 222         667 bless $self,shift;
63 222 100       528 if (@_) {
64 18         54 $self->set(@_);
65             }
66 222         602 return $self;
67             }
68              
69             =head2 set(DATA)
70              
71             Sets the contents of this list (replaces the old contents).
72              
73             DATA has to be an Arrayhref
74              
75             $inc->set(\@INC);
76              
77             =cut
78              
79             sub set {
80 30     30 1 53 my $self=shift;
81 30         32 local $_;
82             #@{$self->{List}}=map {Data::Sofu::Object->new($_)} @_;
83 30         145 my $temp=shift;
84 30         71 foreach (@$temp) {
85 120         354 $_=Data::Sofu::Object->new($_);
86             }
87 30         317 $self->{List}=$temp;
88             }
89              
90             =head2 asList()
91              
92             Returns itself, used to make sure this List is really a List (C and C will die if called with this method)
93              
94             =cut
95              
96             sub asList {
97 69     69 1 296 return shift;
98             }
99              
100             =head2 asArray()
101              
102             Perl only
103              
104             Returns the list as a perl array.
105              
106             =cut
107              
108             sub asArray {
109 0     0 1 0 my $self=shift;
110 0         0 return @{$$self{List}};
  0         0  
111             }
112              
113             =head2 isList()
114              
115             Returns 1
116              
117             =cut
118              
119             sub isList {
120 192     192 1 567 return 1;
121             }
122              
123             =head2 object(INDEX)
124              
125             Return the object at the position INDEX in the List.
126              
127             Dies if the List is shorter than INDEX.
128              
129             =cut
130              
131             sub object {
132 84     84 1 111 my $self=shift;
133 84         140 my $k=int shift;
134 84 50       218 if (exists $self->{List}->[$k]) {
135 84         373 return $self->{List}->[$k];
136             }
137 0         0 die "Requested object $k doesn't exists in this List";
138             }
139              
140             =head2 hasElement(INDEX)
141              
142             Deprecated!
143              
144             Returns a true value if the List has an Element with the number INDEX
145              
146             =cut
147              
148             sub hasElement {
149 3     3 1 15 my $self=shift;
150 3         6 my $k=int shift;
151 3         18 return exists $self->{List}->[$k];
152             }
153              
154             =head2 hasObject(INDEX)
155              
156             Returns a true value if the List has an Element with the number INDEX
157              
158             =cut
159              
160             sub hasObject {
161 0     0 1 0 my $self=shift;
162 0         0 my $k=int shift;
163 0         0 return exists $self->{List}->[$k];
164             }
165              
166             =head2 hasValue(INDEX)
167              
168             Returns 1 if this List has an Element at INDEX and this Element is a C.
169              
170             $inc->hasValue(2) === $inc->hasElement(2) and $inc->object(2)->isValue();
171              
172             Note: Return 0 if the Object is not a Value and under if the Element doesn't exist at all.
173              
174             =cut
175              
176             sub hasValue {
177 57     57 1 125 my $self=shift;
178 57         84 my $k=int shift;
179 57 50       334 return $self->{List}->[$k]->isValue() if exists $self->{List}->[$k];
180 0         0 return undef;
181             }
182              
183             =head2 hasMap(INDEX)
184              
185             Returns 1 if this List has an Element at INDEX and this Element is a C.
186              
187             $inc->hasMap(2) === $inc->hasElement(2) and $inc->object(2)->isMap();
188              
189             Note: Return 0 if the Object is not a Map and under if the Element doesn't exist at all.
190              
191             =cut
192              
193             sub hasMap {
194 6     6 1 18 my $self=shift;
195 6         13 my $k=int shift;
196 6 50       57 return $self->{List}->[$k]->isMap() if exists $self->{List}->[$k];
197 0         0 return undef;
198             }
199              
200             =head2 hasList(INDEX)
201              
202             Returns 1 if this List has an Element at INDEX and this Element is a C.
203              
204             $inc->hasMap(2) === $inc->hasElement(2) and $inc->object(2)->isList();
205              
206             Note: Return 0 if the Object is not a List and under if the Element doesn't exist at all.
207              
208             =cut
209              
210             sub hasList {
211 6     6 1 14 my $self=shift;
212 6         12 my $k=int shift;
213 6 50       35 return $self->{List}->[$k]->isList() if exists $self->{List}->[$k];
214 0         0 return undef;
215             }
216              
217             =head2 list(INDEX)
218              
219             Returns the Object at the postition "INDEX" as a C.
220              
221             Dies if the Object is not a C.
222            
223             $inc->list(2) === $inc->object(2)->asList()
224              
225             =cut
226              
227             sub list {
228 6     6 1 12 my $self=shift;
229 6         19 return $self->object(shift(@_))->asList();
230             }
231              
232             =head2 map(INDEX)
233              
234             Returns the Object at the postition "INDEX" as a C.
235              
236             Dies if the Object is not a C.
237            
238             $inc->map(2) === $inc->object(2)->asMap()
239              
240             =cut
241              
242             sub map {
243 3     3 1 9 my $self=shift;
244 3         10 return $self->object(shift(@_))->asMap();
245             }
246              
247             =head2 value(INDEX)
248              
249             Returns the Object at the postition "INDEX" as a C.
250              
251             Dies if the Object is not a C.
252            
253             $inc->value(2) === $inc->object(2)->asValue()
254              
255             =cut
256              
257             sub value {
258 63     63 1 100 my $self=shift;
259 63         137 return $self->object(shift(@_))->asValue();
260             }
261              
262             =head2 setElement(INDEX, VALUE)
263              
264             Perl only (for now)
265              
266             Sets the Element at INDEX to VALUE
267              
268             $inc->setElement(0,Data::Sofu::Value->new("."));
269              
270             =cut
271              
272             sub setElement {
273 0     0 1 0 my $self=shift;
274 0         0 my $key = int shift;
275 0         0 $self->{List}->[$key]=Data::Sofu::Object->new(shift);
276             }
277              
278             =head2 next()
279              
280             Iterartes over the List, return the next Element on every call and undef at the end of the List.
281              
282             When called in void context it just resets the iterator.
283              
284             =cut
285              
286             sub next {
287 840     840 1 2268 my $self=shift;
288 840 100       2107 $self->{Iter} = 0 unless $self->{Iter};
289 840 50       1619 unless (defined wantarray) {
290 0         0 $self->{Iter}=0;
291 0         0 return;
292             }
293 840 100       1098 if ($self->{Iter} > $#{$self->{List}}) {
  840         2324  
294 168         329 delete $self->{Iter};
295 168         605 return undef;
296             }
297            
298 672         3125 return $self->{List}->[$self->{Iter}++];
299             }
300              
301             =head2 splice(OFFSET, LENGTH, REPLACEMENT)
302              
303             Perl only (for now)
304              
305             Like Perl splice, replaces LENGTH Elements from OFFSET with REPLACEMENT, returns the replaced Elements.
306            
307             my $lib = new Data::Sofu::List();
308             $inc->splice(2,0,Data::Sofu::Value->new("."),Data::Sofu::Value->new(".."),Data::Sofu::Value->new("../lib"));
309             # Inserts 3 new Elements after the second Element
310              
311             =cut
312              
313             sub splice {
314 0     0 1 0 my $self=shift;
315 0         0 return CORE::splice(@{$self->{List}},@_);
  0         0  
316             }
317              
318             =head2 spliceList(OFFSET, LENGTH, REPLACEMENT)
319              
320             Perl only (for now)
321              
322             Like splice, replaces LENGTH Elements from OFFSET with REPLACEMENT, returns the replaced Elements.
323              
324             REPLACEMENT is another C
325            
326             my $lib = new Data::Sofu::List(Data::Sofu::Value->new("."),Data::Sofu::Value->new(".."),Data::Sofu::Value->new("../lib"));
327             $inc->spliceList(2,0,$lib);
328             # Inserts the list $lib after the second Element.
329              
330             =cut
331              
332             sub spliceList {
333 0     0 1 0 my $self=shift;
334 0         0 my $off=shift;
335 0         0 my $len=shift;
336 0         0 my $rep=shift;
337 0         0 return CORE::splice(@{$self->{List}},$off,$len,$rep->asArray());
  0         0  
338             }
339              
340             =head2 appendElement(ELEMENT)
341              
342             Appends one (or multiple (Perl only)) ELEMENT to the end of this List.
343              
344             $inc->appendElement(Data::Sofu::Value->new("lib/"));
345              
346             =cut
347              
348             sub appendElement {
349 0     0 1 0 my $self=shift;
350 0         0 local $_;
351 0         0 push @{$self->{List}},map {Data::Sofu::Object->new($_)} @_;
  0         0  
  0         0  
352             }
353              
354             =head2 firstElement()
355              
356             Perl only (for now)
357              
358             Removes and returns the first Element of this List
359              
360             =cut
361              
362             sub firstElement {
363 0     0 1 0 my $self=shift;
364 0         0 return shift @{$self->{List}};
  0         0  
365             }
366              
367             =head2 lastElement()
368              
369             Perl only (for now)
370              
371             Removes and returns the last Element of this List
372              
373             =cut
374              
375             sub lastElement {
376 0     0 1 0 my $self=shift;
377 0         0 return pop @{$self->{List}};
  0         0  
378             }
379              
380              
381             =head2 insertElement(ELEMENT)
382              
383             Perl only (for now)
384              
385             Appends one (or multiple (Perl only)) ELEMENT to the front of this List.
386              
387             $inc->insertElement(Data::Sofu::Value->new("lib/"));
388              
389             =cut
390              
391             sub insertElement {
392 0     0 1 0 my $self=shift;
393 0         0 local $_;
394 0         0 unshift @{$self->{List}},map {Data::Sofu::Object->new($_)} @_;
  0         0  
  0         0  
395             }
396              
397             =head2 appendList(LIST)
398              
399             Perl only (for now)
400              
401             Appends another LIST to the end of this List.
402              
403             my $lib = new Data::Sofu::List(Data::Sofu::Value->new("."),Data::Sofu::Value->new(".."),Data::Sofu::Value->new("../lib"));
404             $inc->appendList($lib);
405              
406             =cut
407              
408             sub appendList {
409 0     0 1 0 my $self=shift;
410 0         0 my $other=shift;
411 0         0 push @{$self->{List}},$other->asArray();
  0         0  
412              
413             }
414              
415             =head2 insertList(LIST)
416              
417             Perl only (for now)
418              
419             Appends another LIST to the front of this List.
420              
421             my $lib = new Data::Sofu::List(Data::Sofu::Value->new("."),Data::Sofu::Value->new(".."),Data::Sofu::Value->new("../lib"));
422             $inc->insertList($lib);
423              
424             =cut
425              
426             sub insertList {
427 0     0 1 0 my $self=shift;
428 0         0 my $other=shift;
429 0         0 unshift @{$self->{List}},$other->asArray();
  0         0  
430              
431             }
432              
433             =head2 elementIndex(VALUE)
434              
435             Returns the index of the first Element that machtes VALUE
436              
437             =cut
438              
439             sub elementIndex {
440 0     0 1 0 my $self=shift;
441 0         0 my $o = shift;
442 0         0 for (my $i=0; $i<@{$self->{List}};$i++) {
  0         0  
443 0 0       0 return $i if $self->{List}->[$i] eq $o;
444             }
445 0         0 return undef;
446             }
447              
448             =head2 clear(VALUE)
449              
450             Perl only (for now)
451              
452             Empties this list
453              
454             =cut
455              
456             sub clear {
457 0     0 1 0 my $self=shift;
458 0         0 $self->{List}=[];
459             }
460              
461             =head2 length
462              
463             Perl only (for now)
464              
465             Returns the length of this List.
466              
467             Note: The index of the last element is length-1!
468              
469             =cut
470              
471             sub length {
472 156     156 1 195 my $self=shift;
473 156         182 return scalar @{$self->{List}};
  156         714  
474             }
475              
476              
477             =head2 opApply()
478              
479             Takes a Subroutine and iterates with it over this List. Values can't be modified.
480              
481             The Subroutine takes one Argument: The Value.
482              
483             $inc->opApply(sub {
484             print "Element = $_[0]->asValue->toString(),"\n";
485             });
486              
487             Note: The Values are Objects, so they still can be changed, but not replaced.
488              
489             =cut
490              
491             sub opApply {
492 0     0 1 0 my $self=shift;
493 0         0 my $code=shift;
494 0 0 0     0 croak("opApply needs a Code Reference") unless ref $code and lc ref $code eq "code";
495 0         0 foreach my $e (@{$self->{Map}}) {
  0         0  
496 0         0 my $element=$e;
497 0         0 $code->($element);
498             }
499             }
500              
501              
502             =head2 opApplyDeluxe()
503              
504             Perl only.
505              
506             Takes a Subroutine and iterates with it over this List. Values can be modified.
507              
508             The Subroutine takes one Argument: The Value.
509              
510             $inc->opApplyDeluxe(sub {
511             $_[0]=Data::Sofu::List(split /\//,$_[0]->asValue()->toString());
512             });
513              
514              
515             Note: Please make sure every replaced Value is a C or inherits from it.
516              
517             =cut
518              
519             sub opApplyDeluxe {
520 0     0 1 0 my $self=shift;
521 0         0 my $code=shift;
522 0 0 0     0 croak("opApplyDeluxe needs a Code Reference") unless ref $code and lc ref $code eq "code";
523 0         0 foreach my $e (@{$self->{Map}}) {
  0         0  
524 0         0 $code->($e);
525             }
526             }
527              
528             =head2 storeComment(TREE,COMMENT)
529              
530             Stores a comment in the Object if TREE is empty, otherwise it propagades the Comment to all its Elements
531              
532             Should not be called directly, use importComments() instead.
533              
534             =cut
535              
536             sub storeComment {
537 4     4 1 6 my $self=shift;
538 4         6 my $tree=shift;
539 4         5 my $comment=shift;
540             #print "Tree = $tree, Comment = @{$comment}\n";
541 4 50       7 if ($tree eq "") {
542 0         0 $self->{Comment}=$comment;
543             }
544             else {
545 4         14 my ($value,$tree) = split(/\-\>/,$tree,2);
546             #$value=Sofukeyunescape($value);
547 4         23 $self->{List}->[$value]->storeComment($tree,$comment);
548             }
549              
550             }
551              
552             =head2 stringify(LEVEL, TREE)
553              
554             Returns a string representing this List and all its elements.
555              
556             Runs string(LEVEL+1,TREE+index) on all its elements.
557              
558             =cut
559              
560              
561             sub stringify {
562 18     18 1 23 my $self=shift;
563 18         21 my $level=shift;
564 18         19 my $tree=shift;
565 18 100       34 $level-=1 if $level < 0;
566 18         21 my $str="";
567 18 50       34 $str="Value = " unless $level;
568 18         23 $str.="(";
569 18         46 $str.=$self->stringComment();
570 18         23 $str.="\n";
571 18         17 my $i=0;
572 18         16 foreach my $elem (@{$self->{List}}) {
  18         71  
573 72         164 $str.=$self->indent($level);
574 72         331 $str.=$elem->string($level+1,$tree."->".$i++);
575             }
576 18 100       52 $str.=$self->indent($level-1) if $level > 1;
577 18         27 $str.=")\n";
578 18         82 return $str;
579             }
580              
581             =head2 binarify(TREE,BINARY DRIVER)
582              
583             Returns the binary version of this List and all its elements using the BINARY DRIVER. Don't call this one, use binaryPack instead.
584              
585             =cut
586              
587              
588             sub binarify {
589 36     36 1 44 my $self=shift;
590 36         47 my $tree=shift;
591 36         47 my $bin=shift;
592 36         94 my $str=$bin->packType(2);
593 36         110 $str.=$self->packComment($bin);
594 36         63 $str.=$bin->packLong(scalar @{$self->{List}});
  36         131  
595 36         67 my $i=0;
596 36         61 foreach my $elem (@{$self->{List}}) {
  36         95  
597 144         676 $str.=$elem->binary("$tree->".$i++,$bin);
598             }
599 36         226 return $str;
600             }
601              
602             =head1 BUGS
603              
604             Some Methods here are not included in Sofud, but they should be so their name might change (Old ones will be preserved)
605              
606             =head1 SEE ALSO
607              
608             L, L, L, L, L, L, L
609              
610             =cut
611              
612             1;