Filename | /var/www/foswikidev/core/lib/Foswiki/Iterator/PagerIterator.pm |
Statements | Executed 11 statements in 825µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 14µs | 27µs | BEGIN@13 | Foswiki::Iterator::PagerIterator::
1 | 1 | 1 | 12µs | 16µs | BEGIN@14 | Foswiki::Iterator::PagerIterator::
1 | 1 | 1 | 10µs | 40µs | BEGIN@15 | Foswiki::Iterator::PagerIterator::
1 | 1 | 1 | 5µs | 5µs | BEGIN@17 | Foswiki::Iterator::PagerIterator::
1 | 1 | 1 | 4µs | 4µs | BEGIN@20 | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | hasNext | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | new | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | next | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | nextWeb | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | numberOfPages | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | numberOfTopics | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | pagesize | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | reset | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | showpage | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | skip | Foswiki::Iterator::PagerIterator::
0 | 0 | 0 | 0s | 0s | sortResults | Foswiki::Iterator::PagerIterator::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin | ||||
4 | |||||
5 | ---+ package Foswiki::Iterator::PagerIterator | ||||
6 | |||||
7 | Iterator that Pages another iterator | ||||
8 | |||||
9 | =cut | ||||
10 | |||||
11 | package Foswiki::Iterator::PagerIterator; | ||||
12 | |||||
13 | 2 | 29µs | 2 | 40µs | # spent 27µs (14+13) within Foswiki::Iterator::PagerIterator::BEGIN@13 which was called:
# once (14µs+13µs) by Foswiki::Search::BEGIN@23 at line 13 # spent 27µs making 1 call to Foswiki::Iterator::PagerIterator::BEGIN@13
# spent 13µs making 1 call to strict::import |
14 | 2 | 30µs | 2 | 20µs | # spent 16µs (12+4) within Foswiki::Iterator::PagerIterator::BEGIN@14 which was called:
# once (12µs+4µs) by Foswiki::Search::BEGIN@23 at line 14 # spent 16µs making 1 call to Foswiki::Iterator::PagerIterator::BEGIN@14
# spent 4µs making 1 call to warnings::import |
15 | 2 | 30µs | 2 | 69µs | # spent 40µs (10+29) within Foswiki::Iterator::PagerIterator::BEGIN@15 which was called:
# once (10µs+29µs) by Foswiki::Search::BEGIN@23 at line 15 # spent 40µs making 1 call to Foswiki::Iterator::PagerIterator::BEGIN@15
# spent 29µs making 1 call to Exporter::import |
16 | |||||
17 | 2 | 58µs | 1 | 5µs | # spent 5µs within Foswiki::Iterator::PagerIterator::BEGIN@17 which was called:
# once (5µs+0s) by Foswiki::Search::BEGIN@23 at line 17 # spent 5µs making 1 call to Foswiki::Iterator::PagerIterator::BEGIN@17 |
18 | 1 | 7µs | our @ISA = ('Foswiki::Iterator'); | ||
19 | |||||
20 | # spent 4µs within Foswiki::Iterator::PagerIterator::BEGIN@20 which was called:
# once (4µs+0s) by Foswiki::Search::BEGIN@23 at line 25 | ||||
21 | 1 | 9µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
22 | require locale; | ||||
23 | import locale(); | ||||
24 | } | ||||
25 | 1 | 659µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::Iterator::PagerIterator::BEGIN@20 |
26 | |||||
27 | =begin TML | ||||
28 | |||||
29 | ---++ ClassMethod new( $iter, $pagesize, $showpage) | ||||
30 | |||||
31 | skip a certain number of results based on pagesize and page number | ||||
32 | |||||
33 | (page 1 is the first page) | ||||
34 | |||||
35 | =cut | ||||
36 | |||||
37 | sub new { | ||||
38 | my ( $class, $iter, $pagesize, $showpage ) = @_; | ||||
39 | ASSERT( UNIVERSAL::isa( $iter, 'Foswiki::Iterator' ) ) if DEBUG; | ||||
40 | |||||
41 | my $this = bless( {}, $class ); | ||||
42 | $this->{iterator} = $iter; | ||||
43 | |||||
44 | $this->{next} = undef; | ||||
45 | $this->{pending} = | ||||
46 | 0; #has 'hasNext' already been called, but 'next' hasn't been | ||||
47 | |||||
48 | $this->{pagesize} = | ||||
49 | $pagesize | ||||
50 | || $Foswiki::cfg{Search}{DefaultPageSize} | ||||
51 | || 25; | ||||
52 | $this->{showpage} = $showpage; | ||||
53 | $this->{showpage} = 1 unless ( defined( $this->{showpage} ) ); | ||||
54 | |||||
55 | $this->{pager_skip_results_from} = | ||||
56 | $this->{pagesize} * ( $this->{showpage} - 1 ); | ||||
57 | print STDERR | ||||
58 | " $this->{pager_skip_results_from} = $this->{pagesize} * ($this->{showpage}-1);\n" | ||||
59 | if Foswiki::Iterator::MONITOR; | ||||
60 | $this->{pager_result_count} = $this->{pagesize}; | ||||
61 | |||||
62 | return $this; | ||||
63 | } | ||||
64 | |||||
65 | sub pagesize { | ||||
66 | my $this = shift; | ||||
67 | return $this->{pagesize}; | ||||
68 | } | ||||
69 | |||||
70 | sub showpage { | ||||
71 | my $this = shift; | ||||
72 | return $this->{showpage}; | ||||
73 | } | ||||
74 | |||||
75 | #lie - give the requested pagesize - it might be less, if we're at the end of the list | ||||
76 | #and we can never know if there is just one more, as the underlying iterator may have only asked for pagesize reaults | ||||
77 | #so it can't tell us | ||||
78 | sub numberOfTopics { | ||||
79 | my $this = shift; | ||||
80 | if ( !$this->hasNext() && ( $this->{pager_result_count} > 0 ) ) { | ||||
81 | return $this->{pagesize} - $this->{pager_result_count}; | ||||
82 | } | ||||
83 | else { | ||||
84 | #we're still iterating, so we don't know the page size | ||||
85 | return $this->{pagesize}; | ||||
86 | } | ||||
87 | } | ||||
88 | |||||
89 | #another lie - this hopes that the inner iterator knows the number, and isn't just guessing. | ||||
90 | sub numberOfPages { | ||||
91 | my $this = shift; | ||||
92 | if ( !$this->hasNext() && ( $this->{pager_result_count} > 0 ) ) { | ||||
93 | |||||
94 | #if we've exhausted the undelying iterator, and have not got pagesize elements, then we know there are no more. | ||||
95 | return $this->showpage(); | ||||
96 | } | ||||
97 | else { | ||||
98 | #we're still iterating, so we don't know the page size | ||||
99 | return | ||||
100 | int( $this->{iterator}->numberOfTopics() / $this->{pagesize} ) + 1; | ||||
101 | } | ||||
102 | } | ||||
103 | |||||
104 | sub nextWeb { | ||||
105 | my $this = shift; | ||||
106 | $this->{iterator}->nextWeb(); | ||||
107 | } | ||||
108 | |||||
109 | sub sortResults { | ||||
110 | my $this = shift; | ||||
111 | $this->{iterator}->sortResults(@_); | ||||
112 | } | ||||
113 | |||||
114 | # See Foswiki::Iterator for a description of the general iterator contract | ||||
115 | sub hasNext { | ||||
116 | my $this = shift; | ||||
117 | return 1 if $this->{pending}; | ||||
118 | |||||
119 | if ( $this->{pager_skip_results_from} > 0 ) { | ||||
120 | $this->{pager_skip_results_from} = | ||||
121 | $this->skip( $this->{pager_skip_results_from} ); | ||||
122 | |||||
123 | #this already loads $this->{next} | ||||
124 | |||||
125 | } | ||||
126 | else { | ||||
127 | if ( $this->{iterator}->hasNext() ) { | ||||
128 | $this->{next} = $this->{iterator}->next(); | ||||
129 | $this->{pending} = 1; | ||||
130 | } | ||||
131 | } | ||||
132 | |||||
133 | if ( $this->{pending} ) { | ||||
134 | if ( $this->{pager_result_count} <= 0 ) { | ||||
135 | |||||
136 | #SVEN - huh? | ||||
137 | #finished. | ||||
138 | $this->{next} = undef; | ||||
139 | $this->{pending} = 0; | ||||
140 | return 0; | ||||
141 | } | ||||
142 | $this->{pager_result_count}--; | ||||
143 | return 1; | ||||
144 | } | ||||
145 | return 0; | ||||
146 | } | ||||
147 | |||||
148 | #skip X elements (returns 0 if successful, or number of elements remaining to skip if there are not enough elements to skip) | ||||
149 | #skip must set up next as though hasNext was called. | ||||
150 | sub skip { | ||||
151 | my $this = shift; | ||||
152 | my $count = shift; | ||||
153 | |||||
154 | print STDERR | ||||
155 | "--------------------------------------------PagerIterator::skip($count)\n" | ||||
156 | if Foswiki::Iterator::MONITOR; | ||||
157 | |||||
158 | #ask CAN skip() for faster path | ||||
159 | if ( 1 == 2 && $this->{iterator}->can('skip') ) { | ||||
160 | $count = $this->{iterator}->skip($count); | ||||
161 | if ( $this->{iterator}->hasNext() ) { | ||||
162 | $this->{next} = $this->{iterator}->next(); | ||||
163 | $this->{pending} = 1; | ||||
164 | $count--; | ||||
165 | } | ||||
166 | } | ||||
167 | else { | ||||
168 | |||||
169 | #brute force | ||||
170 | while ( | ||||
171 | ( $count >= 0 | ||||
172 | ) #must come first - don't want to advance the inner itr if count ==0 | ||||
173 | and $this->{iterator}->hasNext() | ||||
174 | ) | ||||
175 | { | ||||
176 | $count--; | ||||
177 | $this->{next} = | ||||
178 | $this->{iterator}->next() | ||||
179 | ; #drain next, so hasNext goes to next element | ||||
180 | $this->{pending} = defined( $this->{next} ); | ||||
181 | } | ||||
182 | } | ||||
183 | |||||
184 | #in the bute force method, $count == -1 if there were enough elements. | ||||
185 | if ( $count >= 0 ) { | ||||
186 | |||||
187 | #skipped past the end of the set | ||||
188 | $this->{next} = undef; | ||||
189 | $this->{pending} = 0; | ||||
190 | } | ||||
191 | print STDERR | ||||
192 | "--------------------------------------------PagerIterator::skip() => $count\n" | ||||
193 | if Foswiki::Iterator::MONITOR; | ||||
194 | |||||
195 | return $count; | ||||
196 | } | ||||
197 | |||||
198 | # See Foswiki::Iterator for a description of the general iterator contract | ||||
199 | sub next { | ||||
200 | my $this = shift; | ||||
201 | return unless $this->hasNext(); | ||||
202 | $this->{pending} = 0; | ||||
203 | return $this->{next}; | ||||
204 | } | ||||
205 | |||||
206 | # See Foswiki::Iterator for a description of the general iterator contract | ||||
207 | sub reset { | ||||
208 | my ($this) = @_; | ||||
209 | |||||
210 | return unless ( $this->{iterator}->reset() ); | ||||
211 | $this->{next} = undef; | ||||
212 | $this->{pending} = 0; | ||||
213 | |||||
214 | return 1; | ||||
215 | } | ||||
216 | |||||
217 | 1 | 3µs | 1; | ||
218 | __END__ |