Filename | /var/www/foswikidev/core/lib/Foswiki/AggregateIterator.pm |
Statements | Executed 9 statements in 478µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 317µs | 434µs | BEGIN@16 | Foswiki::AggregateIterator::
1 | 1 | 1 | 12µs | 24µs | BEGIN@13 | Foswiki::AggregateIterator::
1 | 1 | 1 | 8µs | 12µs | BEGIN@14 | Foswiki::AggregateIterator::
1 | 1 | 1 | 4µs | 4µs | BEGIN@19 | Foswiki::AggregateIterator::
0 | 0 | 0 | 0s | 0s | hasNext | Foswiki::AggregateIterator::
0 | 0 | 0 | 0s | 0s | new | Foswiki::AggregateIterator::
0 | 0 | 0 | 0s | 0s | next | Foswiki::AggregateIterator::
0 | 0 | 0 | 0s | 0s | unique | Foswiki::AggregateIterator::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+ package Foswiki::AggregateIterator | ||||
6 | *implements* Foswiki::Iterator | ||||
7 | |||||
8 | Combine multiple iterators into a single iteration. | ||||
9 | |||||
10 | =cut | ||||
11 | |||||
12 | package Foswiki::AggregateIterator; | ||||
13 | 2 | 25µs | 2 | 36µs | # spent 24µs (12+12) within Foswiki::AggregateIterator::BEGIN@13 which was called:
# once (12µs+12µs) by Foswiki::Users::BEGIN@63 at line 13 # spent 24µs making 1 call to Foswiki::AggregateIterator::BEGIN@13
# spent 12µs making 1 call to strict::import |
14 | 2 | 26µs | 2 | 16µs | # spent 12µs (8+4) within Foswiki::AggregateIterator::BEGIN@14 which was called:
# once (8µs+4µs) by Foswiki::Users::BEGIN@63 at line 14 # spent 12µs making 1 call to Foswiki::AggregateIterator::BEGIN@14
# spent 4µs making 1 call to warnings::import |
15 | |||||
16 | 2 | 118µs | 1 | 434µs | # spent 434µs (317+117) within Foswiki::AggregateIterator::BEGIN@16 which was called:
# once (317µs+117µs) by Foswiki::Users::BEGIN@63 at line 16 # spent 434µs making 1 call to Foswiki::AggregateIterator::BEGIN@16 |
17 | 1 | 7µs | our @ISA = ('Foswiki::Iterator'); | ||
18 | |||||
19 | # spent 4µs within Foswiki::AggregateIterator::BEGIN@19 which was called:
# once (4µs+0s) by Foswiki::Users::BEGIN@63 at line 24 | ||||
20 | 1 | 5µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
21 | require locale; | ||||
22 | import locale(); | ||||
23 | } | ||||
24 | 1 | 294µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::AggregateIterator::BEGIN@19 |
25 | |||||
26 | =begin TML | ||||
27 | |||||
28 | ---++ new(\@list, $unique) | ||||
29 | |||||
30 | Create a new iterator over the given list of iterators. The list is | ||||
31 | not damaged in any way. | ||||
32 | |||||
33 | If =$unique= is set, we try to not repeat values. | ||||
34 | Warning: =$unique= assumes that the values are strings. | ||||
35 | |||||
36 | =cut | ||||
37 | |||||
38 | sub new { | ||||
39 | my ( $class, $list, $unique ) = @_; | ||||
40 | my $this = bless( | ||||
41 | { | ||||
42 | Itr_list => $list, | ||||
43 | Itr_index => 0, | ||||
44 | index => 0, | ||||
45 | process => undef, | ||||
46 | filter => undef, | ||||
47 | next => undef, | ||||
48 | unique => $unique, | ||||
49 | unique_hash => {} | ||||
50 | }, | ||||
51 | $class | ||||
52 | ); | ||||
53 | return $this; | ||||
54 | } | ||||
55 | |||||
56 | =begin TML | ||||
57 | |||||
58 | ---++ hasNext() -> $boolean | ||||
59 | |||||
60 | Returns false when the iterator is exhausted. | ||||
61 | |||||
62 | =cut | ||||
63 | |||||
64 | sub hasNext { | ||||
65 | my ($this) = @_; | ||||
66 | return 1 if $this->{next}; | ||||
67 | my $n; | ||||
68 | do { | ||||
69 | unless ( $this->{list} ) { | ||||
70 | if ( $this->{Itr_index} < scalar( @{ $this->{Itr_list} } ) ) { | ||||
71 | $this->{list} = $this->{Itr_list}->[ $this->{Itr_index}++ ]; | ||||
72 | } | ||||
73 | else { | ||||
74 | return 0; #no more iterators in list | ||||
75 | } | ||||
76 | } | ||||
77 | if ( $this->{list}->hasNext() ) { | ||||
78 | $n = $this->{list}->next(); | ||||
79 | } | ||||
80 | else { | ||||
81 | $this->{list} = undef; #goto next iterator | ||||
82 | } | ||||
83 | } while ( !$this->{list} | ||||
84 | || ( $this->{filter} && !&{ $this->{filter} }($n) ) | ||||
85 | || ( $this->{unique} && !$this->unique($n) ) ); | ||||
86 | $this->{next} = $n; | ||||
87 | return 1; | ||||
88 | } | ||||
89 | |||||
90 | sub unique { | ||||
91 | my ( $this, $value ) = @_; | ||||
92 | |||||
93 | unless ( defined( $this->{unique_hash}{$value} ) ) { | ||||
94 | $this->{unique_hash}{$value} = 1; | ||||
95 | return 1; | ||||
96 | } | ||||
97 | |||||
98 | return 0; | ||||
99 | } | ||||
100 | |||||
101 | =begin TML | ||||
102 | |||||
103 | ---++ next() -> $data | ||||
104 | |||||
105 | Return the next entry in the list. | ||||
106 | |||||
107 | The iterator object can be customised to pre- and post-process entries from | ||||
108 | the list before returning them. This is done by setting two fields in the | ||||
109 | iterator object: | ||||
110 | |||||
111 | * ={filter}= can be defined to be a sub that filters each entry. The entry | ||||
112 | will be ignored (next() will not return it) if the filter returns false. | ||||
113 | * ={process}= can be defined to be a sub to process each entry before it | ||||
114 | is returned by next. The value returned from next is the value returned | ||||
115 | by the process function. | ||||
116 | |||||
117 | =cut | ||||
118 | |||||
119 | sub next { | ||||
120 | my $this = shift; | ||||
121 | $this->hasNext(); | ||||
122 | my $n = $this->{next}; | ||||
123 | $this->{next} = undef; | ||||
124 | $n = &{ $this->{process} }($n) if $this->{process}; | ||||
125 | |||||
126 | #print STDERR "next - $n \n"; | ||||
127 | return $n; | ||||
128 | } | ||||
129 | |||||
130 | 1 | 3µs | 1; | ||
131 | __END__ |