Filename | /usr/lib/x86_64-linux-gnu/perl5/5.28/Template/VMethods.pm |
Statements | Executed 31878 statements in 157ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1991 | 1 | 1 | 57.2ms | 77.9ms | list_sort | Template::VMethods::
3981 | 1 | 1 | 33.8ms | 33.8ms | text_substr | Template::VMethods::
1991 | 1 | 1 | 24.1ms | 24.1ms | list_import | Template::VMethods::
1991 | 1 | 1 | 20.7ms | 20.7ms | CORE:sort (opcode) | Template::VMethods::
1 | 1 | 1 | 45µs | 47µs | BEGIN@24 | Template::VMethods::
1 | 1 | 1 | 11µs | 12µs | BEGIN@27 | Template::VMethods::
1 | 1 | 1 | 10µs | 25µs | BEGIN@469 | Template::VMethods::
1 | 1 | 1 | 8µs | 31µs | BEGIN@118 | Template::VMethods::
1 | 1 | 1 | 7µs | 55µs | BEGIN@26 | Template::VMethods::
1 | 1 | 1 | 6µs | 17µs | BEGIN@496 | Template::VMethods::
1 | 1 | 1 | 6µs | 21µs | BEGIN@25 | Template::VMethods::
1 | 1 | 1 | 6µs | 15µs | BEGIN@502 | Template::VMethods::
1 | 1 | 1 | 5µs | 15µs | BEGIN@124 | Template::VMethods::
1 | 1 | 1 | 600ns | 600ns | __ANON__ (xsub) | Template::VMethods::
0 | 0 | 0 | 0s | 0s | __ANON__[:234] | Template::VMethods::
0 | 0 | 0 | 0s | 0s | __ANON__[:606] | Template::VMethods::
0 | 0 | 0 | 0s | 0s | _list_sort_make_key | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_defined | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_delete | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_each | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_empty | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_exists | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_hash | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_import | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_item | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_items | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_keys | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_list | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_nsort | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_pairs | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_size | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_sort | Template::VMethods::
0 | 0 | 0 | 0s | 0s | hash_values | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_defined | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_empty | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_first | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_grep | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_hash | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_item | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_join | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_last | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_list | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_max | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_merge | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_nsort | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_pop | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_push | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_reverse | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_shift | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_size | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_slice | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_splice | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_unique | Template::VMethods::
0 | 0 | 0 | 0s | 0s | list_unshift | Template::VMethods::
0 | 0 | 0 | 0s | 0s | root_dec | Template::VMethods::
0 | 0 | 0 | 0s | 0s | root_inc | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_chunk | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_collapse | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_defined | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_dquote | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_empty | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_hash | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_item | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_lcfirst | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_length | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_list | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_lower | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_match | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_remove | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_repeat | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_replace | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_search | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_size | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_split | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_squote | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_trim | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_ucfirst | Template::VMethods::
0 | 0 | 0 | 0s | 0s | text_upper | Template::VMethods::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | #============================================================= -*-Perl-*- | ||||
2 | # | ||||
3 | # Template::VMethods | ||||
4 | # | ||||
5 | # DESCRIPTION | ||||
6 | # Module defining virtual methods for the Template Toolkit | ||||
7 | # | ||||
8 | # AUTHOR | ||||
9 | # Andy Wardley <abw@wardley.org> | ||||
10 | # | ||||
11 | # COPYRIGHT | ||||
12 | # Copyright (C) 1996-2015 Andy Wardley. All Rights Reserved. | ||||
13 | # | ||||
14 | # This module is free software; you can redistribute it and/or | ||||
15 | # modify it under the same terms as Perl itself. | ||||
16 | # | ||||
17 | # REVISION | ||||
18 | # $Id$ | ||||
19 | # | ||||
20 | #============================================================================ | ||||
21 | |||||
22 | package Template::VMethods; | ||||
23 | |||||
24 | 2 | 29µs | 2 | 50µs | # spent 47µs (45+2) within Template::VMethods::BEGIN@24 which was called:
# once (45µs+2µs) by Template::Stash::BEGIN@24 at line 24 # spent 47µs making 1 call to Template::VMethods::BEGIN@24
# spent 2µs making 1 call to strict::import |
25 | 2 | 24µs | 2 | 37µs | # spent 21µs (6+15) within Template::VMethods::BEGIN@25 which was called:
# once (6µs+15µs) by Template::Stash::BEGIN@24 at line 25 # spent 21µs making 1 call to Template::VMethods::BEGIN@25
# spent 15µs making 1 call to warnings::import |
26 | 2 | 30µs | 2 | 102µs | # spent 55µs (7+48) within Template::VMethods::BEGIN@26 which was called:
# once (7µs+48µs) by Template::Stash::BEGIN@24 at line 26 # spent 55µs making 1 call to Template::VMethods::BEGIN@26
# spent 48µs making 1 call to Exporter::import |
27 | 2 | 411µs | 2 | 12µs | # spent 12µs (11+600ns) within Template::VMethods::BEGIN@27 which was called:
# once (11µs+600ns) by Template::Stash::BEGIN@24 at line 27 # spent 12µs making 1 call to Template::VMethods::BEGIN@27
# spent 600ns making 1 call to Template::VMethods::__ANON__ |
28 | 1 | 400ns | require Template::Stash; | ||
29 | |||||
30 | 1 | 200ns | our $VERSION = 2.16; | ||
31 | 1 | 200ns | our $DEBUG = 0 unless defined $DEBUG; | ||
32 | 1 | 200ns | our $PRIVATE = $Template::Stash::PRIVATE; | ||
33 | |||||
34 | 1 | 2µs | our $ROOT_VMETHODS = { | ||
35 | inc => \&root_inc, | ||||
36 | dec => \&root_dec, | ||||
37 | }; | ||||
38 | |||||
39 | 1 | 12µs | our $TEXT_VMETHODS = { | ||
40 | item => \&text_item, | ||||
41 | list => \&text_list, | ||||
42 | hash => \&text_hash, | ||||
43 | length => \&text_length, | ||||
44 | size => \&text_size, | ||||
45 | empty => \&text_empty, | ||||
46 | defined => \&text_defined, | ||||
47 | upper => \&text_upper, | ||||
48 | lower => \&text_lower, | ||||
49 | ucfirst => \&text_ucfirst, | ||||
50 | lcfirst => \&text_lcfirst, | ||||
51 | match => \&text_match, | ||||
52 | search => \&text_search, | ||||
53 | repeat => \&text_repeat, | ||||
54 | replace => \&text_replace, | ||||
55 | remove => \&text_remove, | ||||
56 | split => \&text_split, | ||||
57 | chunk => \&text_chunk, | ||||
58 | substr => \&text_substr, | ||||
59 | trim => \&text_trim, | ||||
60 | collapse => \&text_collapse, | ||||
61 | squote => \&text_squote, | ||||
62 | dquote => \&text_dquote, | ||||
63 | html => \&Template::Filters::html_filter, | ||||
64 | xml => \&Template::Filters::xml_filter, | ||||
65 | }; | ||||
66 | |||||
67 | 1 | 6µs | our $HASH_VMETHODS = { | ||
68 | item => \&hash_item, | ||||
69 | hash => \&hash_hash, | ||||
70 | size => \&hash_size, | ||||
71 | empty => \&hash_empty, | ||||
72 | each => \&hash_each, | ||||
73 | keys => \&hash_keys, | ||||
74 | values => \&hash_values, | ||||
75 | items => \&hash_items, | ||||
76 | pairs => \&hash_pairs, | ||||
77 | list => \&hash_list, | ||||
78 | exists => \&hash_exists, | ||||
79 | defined => \&hash_defined, | ||||
80 | delete => \&hash_delete, | ||||
81 | import => \&hash_import, | ||||
82 | sort => \&hash_sort, | ||||
83 | nsort => \&hash_nsort, | ||||
84 | }; | ||||
85 | |||||
86 | 1 | 9µs | our $LIST_VMETHODS = { | ||
87 | item => \&list_item, | ||||
88 | list => \&list_list, | ||||
89 | hash => \&list_hash, | ||||
90 | push => \&list_push, | ||||
91 | pop => \&list_pop, | ||||
92 | unshift => \&list_unshift, | ||||
93 | shift => \&list_shift, | ||||
94 | max => \&list_max, | ||||
95 | size => \&list_size, | ||||
96 | empty => \&list_empty, | ||||
97 | defined => \&list_defined, | ||||
98 | first => \&list_first, | ||||
99 | last => \&list_last, | ||||
100 | reverse => \&list_reverse, | ||||
101 | grep => \&list_grep, | ||||
102 | join => \&list_join, | ||||
103 | sort => \&list_sort, | ||||
104 | nsort => \&list_nsort, | ||||
105 | unique => \&list_unique, | ||||
106 | import => \&list_import, | ||||
107 | merge => \&list_merge, | ||||
108 | slice => \&list_slice, | ||||
109 | splice => \&list_splice, | ||||
110 | }; | ||||
111 | |||||
112 | |||||
113 | #======================================================================== | ||||
114 | # root virtual methods | ||||
115 | #======================================================================== | ||||
116 | |||||
117 | sub root_inc { | ||||
118 | 2 | 41µs | 2 | 54µs | # spent 31µs (8+23) within Template::VMethods::BEGIN@118 which was called:
# once (8µs+23µs) by Template::Stash::BEGIN@24 at line 118 # spent 31µs making 1 call to Template::VMethods::BEGIN@118
# spent 23µs making 1 call to warnings::unimport |
119 | my $item = shift; | ||||
120 | ++$item; | ||||
121 | } | ||||
122 | |||||
123 | sub root_dec { | ||||
124 | 2 | 1.58ms | 2 | 24µs | # spent 15µs (5+10) within Template::VMethods::BEGIN@124 which was called:
# once (5µs+10µs) by Template::Stash::BEGIN@24 at line 124 # spent 15µs making 1 call to Template::VMethods::BEGIN@124
# spent 10µs making 1 call to warnings::unimport |
125 | my $item = shift; | ||||
126 | --$item; | ||||
127 | } | ||||
128 | |||||
129 | |||||
130 | #======================================================================== | ||||
131 | # text virtual methods | ||||
132 | #======================================================================== | ||||
133 | |||||
134 | sub text_item { | ||||
135 | $_[0]; | ||||
136 | } | ||||
137 | |||||
138 | sub text_list { | ||||
139 | [ $_[0] ]; | ||||
140 | } | ||||
141 | |||||
142 | sub text_hash { | ||||
143 | { value => $_[0] }; | ||||
144 | } | ||||
145 | |||||
146 | sub text_length { | ||||
147 | length $_[0]; | ||||
148 | } | ||||
149 | |||||
150 | sub text_size { | ||||
151 | return 1; | ||||
152 | } | ||||
153 | |||||
154 | sub text_empty { | ||||
155 | return 0 == text_length($_[0]) ? 1 : 0; | ||||
156 | } | ||||
157 | |||||
158 | sub text_defined { | ||||
159 | return 1; | ||||
160 | } | ||||
161 | |||||
162 | sub text_upper { | ||||
163 | return uc $_[0]; | ||||
164 | } | ||||
165 | |||||
166 | sub text_lower { | ||||
167 | return lc $_[0]; | ||||
168 | } | ||||
169 | |||||
170 | sub text_ucfirst { | ||||
171 | return ucfirst $_[0]; | ||||
172 | } | ||||
173 | |||||
174 | sub text_lcfirst { | ||||
175 | return lcfirst $_[0]; | ||||
176 | } | ||||
177 | |||||
178 | sub text_trim { | ||||
179 | for ($_[0]) { | ||||
180 | s/^\s+//; | ||||
181 | s/\s+$//; | ||||
182 | } | ||||
183 | return $_[0]; | ||||
184 | } | ||||
185 | |||||
186 | sub text_collapse { | ||||
187 | for ($_[0]) { | ||||
188 | s/^\s+//; | ||||
189 | s/\s+$//; | ||||
190 | s/\s+/ /g | ||||
191 | } | ||||
192 | return $_[0]; | ||||
193 | } | ||||
194 | |||||
195 | sub text_match { | ||||
196 | my ($str, $search, $global) = @_; | ||||
197 | return $str unless defined $str and defined $search; | ||||
198 | my @matches = $global ? ($str =~ /$search/g) | ||||
199 | : ($str =~ /$search/); | ||||
200 | return @matches ? \@matches : ''; | ||||
201 | } | ||||
202 | |||||
203 | sub text_search { | ||||
204 | my ($str, $pattern) = @_; | ||||
205 | return $str unless defined $str and defined $pattern; | ||||
206 | return $str =~ /$pattern/; | ||||
207 | } | ||||
208 | |||||
209 | sub text_repeat { | ||||
210 | my ($str, $count) = @_; | ||||
211 | $str = '' unless defined $str; | ||||
212 | return '' unless $count; | ||||
213 | $count ||= 1; | ||||
214 | return $str x $count; | ||||
215 | } | ||||
216 | |||||
217 | sub text_replace { | ||||
218 | my ($text, $pattern, $replace, $global) = @_; | ||||
219 | $text = '' unless defined $text; | ||||
220 | $pattern = '' unless defined $pattern; | ||||
221 | $replace = '' unless defined $replace; | ||||
222 | $global = 1 unless defined $global; | ||||
223 | |||||
224 | if ($replace =~ /\$\d+/) { | ||||
225 | # replacement string may contain backrefs | ||||
226 | my $expand = sub { | ||||
227 | my ($chunk, $start, $end) = @_; | ||||
228 | $chunk =~ s{ \\(\\|\$) | \$ (\d+) }{ | ||||
229 | $1 ? $1 | ||||
230 | : ($2 > $#$start || $2 == 0 || !defined $start->[$2]) ? '' | ||||
231 | : substr($text, $start->[$2], $end->[$2] - $start->[$2]); | ||||
232 | }exg; | ||||
233 | $chunk; | ||||
234 | }; | ||||
235 | if ($global) { | ||||
236 | $text =~ s{$pattern}{ &$expand($replace, [@-], [@+]) }eg; | ||||
237 | } | ||||
238 | else { | ||||
239 | $text =~ s{$pattern}{ &$expand($replace, [@-], [@+]) }e; | ||||
240 | } | ||||
241 | } | ||||
242 | else { | ||||
243 | if ($global) { | ||||
244 | $text =~ s/$pattern/$replace/g; | ||||
245 | } | ||||
246 | else { | ||||
247 | $text =~ s/$pattern/$replace/; | ||||
248 | } | ||||
249 | } | ||||
250 | return $text; | ||||
251 | } | ||||
252 | |||||
253 | sub text_remove { | ||||
254 | my ($str, $search) = @_; | ||||
255 | return $str unless defined $str and defined $search; | ||||
256 | $str =~ s/$search//g; | ||||
257 | return $str; | ||||
258 | } | ||||
259 | |||||
260 | sub text_split { | ||||
261 | my ($str, $split, $limit) = @_; | ||||
262 | $str = '' unless defined $str; | ||||
263 | |||||
264 | # For versions of Perl prior to 5.18 we have to be very careful about | ||||
265 | # spelling out each possible combination of arguments because split() | ||||
266 | # is very sensitive to them, for example C<split(' ', ...)> behaves | ||||
267 | # differently to C<$space=' '; split($space, ...)>. Test 33 of | ||||
268 | # vmethods/text.t depends on this behaviour. | ||||
269 | |||||
270 | if ($] < 5.018) { | ||||
271 | if (defined $limit) { | ||||
272 | return [ defined $split | ||||
273 | ? split($split, $str, $limit) | ||||
274 | : split(' ', $str, $limit) ]; | ||||
275 | } | ||||
276 | else { | ||||
277 | return [ defined $split | ||||
278 | ? split($split, $str) | ||||
279 | : split(' ', $str) ]; | ||||
280 | } | ||||
281 | } | ||||
282 | |||||
283 | # split's behavior changed in Perl 5.18.0 making this: | ||||
284 | # C<$space=' '; split($space, ...)> | ||||
285 | # behave the same as this: | ||||
286 | # C<split(' ', ...)> | ||||
287 | # qr// behaves the same, so use that for user-defined split. | ||||
288 | |||||
289 | my $split_re; | ||||
290 | if (defined $split) { | ||||
291 | eval { | ||||
292 | $split_re = qr/$split/; | ||||
293 | }; | ||||
294 | } | ||||
295 | $split_re = ' ' unless defined $split_re; | ||||
296 | $limit ||= 0; | ||||
297 | return [split($split_re, $str, $limit)]; | ||||
298 | } | ||||
299 | |||||
300 | sub text_chunk { | ||||
301 | my ($string, $size) = @_; | ||||
302 | my @list; | ||||
303 | $size ||= 1; | ||||
304 | if ($size < 0) { | ||||
305 | # sexeger! It's faster to reverse the string, search | ||||
306 | # it from the front and then reverse the output than to | ||||
307 | # search it from the end, believe it nor not! | ||||
308 | $string = reverse $string; | ||||
309 | $size = -$size; | ||||
310 | unshift(@list, scalar reverse $1) | ||||
311 | while ($string =~ /((.{$size})|(.+))/g); | ||||
312 | } | ||||
313 | else { | ||||
314 | push(@list, $1) while ($string =~ /((.{$size})|(.+))/g); | ||||
315 | } | ||||
316 | return \@list; | ||||
317 | } | ||||
318 | |||||
319 | # spent 33.8ms within Template::VMethods::text_substr which was called 3981 times, avg 8µs/call:
# 3981 times (33.8ms+0s) by Template::Stash::XS::get at line 1 of /root/tor-browser-build/input text, avg 8µs/call | ||||
320 | 3981 | 4.53ms | my ($text, $offset, $length, $replacement) = @_; | ||
321 | 3981 | 3.38ms | $offset ||= 0; | ||
322 | |||||
323 | 3981 | 2.86ms | if(defined $length) { | ||
324 | 3981 | 2.21ms | if (defined $replacement) { | ||
325 | substr( $text, $offset, $length, $replacement ); | ||||
326 | return $text; | ||||
327 | } | ||||
328 | else { | ||||
329 | 3981 | 38.5ms | return substr( $text, $offset, $length ); | ||
330 | } | ||||
331 | } | ||||
332 | else { | ||||
333 | return substr( $text, $offset ); | ||||
334 | } | ||||
335 | } | ||||
336 | |||||
337 | sub text_squote { | ||||
338 | my $text = shift; | ||||
339 | for ($text) { | ||||
340 | s/(['\\])/\\$1/g; | ||||
341 | } | ||||
342 | return $text; | ||||
343 | } | ||||
344 | |||||
345 | sub text_dquote { | ||||
346 | my $text = shift; | ||||
347 | for ($text) { | ||||
348 | s/(["\\])/\\$1/g; | ||||
349 | s/\n/\\n/g; | ||||
350 | } | ||||
351 | return $text; | ||||
352 | } | ||||
353 | |||||
354 | #======================================================================== | ||||
355 | # hash virtual methods | ||||
356 | #======================================================================== | ||||
357 | |||||
358 | |||||
359 | sub hash_item { | ||||
360 | my ($hash, $item) = @_; | ||||
361 | $item = '' unless defined $item; | ||||
362 | return if $PRIVATE && $item =~ /$PRIVATE/; | ||||
363 | $hash->{ $item }; | ||||
364 | } | ||||
365 | |||||
366 | sub hash_hash { | ||||
367 | $_[0]; | ||||
368 | } | ||||
369 | |||||
370 | sub hash_size { | ||||
371 | scalar keys %{$_[0]}; | ||||
372 | } | ||||
373 | |||||
374 | sub hash_empty { | ||||
375 | return 0 == hash_size($_[0]) ? 1 : 0; | ||||
376 | } | ||||
377 | |||||
378 | sub hash_each { | ||||
379 | # this will be changed in TT3 to do what hash_pairs() does | ||||
380 | [ %{ $_[0] } ]; | ||||
381 | } | ||||
382 | |||||
383 | sub hash_keys { | ||||
384 | [ keys %{ $_[0] } ]; | ||||
385 | } | ||||
386 | |||||
387 | sub hash_values { | ||||
388 | [ values %{ $_[0] } ]; | ||||
389 | } | ||||
390 | |||||
391 | sub hash_items { | ||||
392 | [ %{ $_[0] } ]; | ||||
393 | } | ||||
394 | |||||
395 | sub hash_pairs { | ||||
396 | [ map { | ||||
397 | { key => $_ , value => $_[0]->{ $_ } } | ||||
398 | } | ||||
399 | sort keys %{ $_[0] } | ||||
400 | ]; | ||||
401 | } | ||||
402 | |||||
403 | sub hash_list { | ||||
404 | my ($hash, $what) = @_; | ||||
405 | $what ||= ''; | ||||
406 | return ($what eq 'keys') ? [ keys %$hash ] | ||||
407 | : ($what eq 'values') ? [ values %$hash ] | ||||
408 | : ($what eq 'each') ? [ %$hash ] | ||||
409 | : # for now we do what pairs does but this will be changed | ||||
410 | # in TT3 to return [ $hash ] by default | ||||
411 | [ map { { key => $_ , value => $hash->{ $_ } } } | ||||
412 | sort keys %$hash | ||||
413 | ]; | ||||
414 | } | ||||
415 | |||||
416 | sub hash_exists { | ||||
417 | exists $_[0]->{ $_[1] }; | ||||
418 | } | ||||
419 | |||||
420 | sub hash_defined { | ||||
421 | # return the item requested, or 1 if no argument | ||||
422 | # to indicate that the hash itself is defined | ||||
423 | my $hash = shift; | ||||
424 | return @_ ? defined $hash->{ $_[0] } : 1; | ||||
425 | } | ||||
426 | |||||
427 | sub hash_delete { | ||||
428 | my $hash = shift; | ||||
429 | delete $hash->{ $_ } for @_; | ||||
430 | } | ||||
431 | |||||
432 | sub hash_import { | ||||
433 | my ($hash, $imp) = @_; | ||||
434 | $imp = {} unless ref $imp eq 'HASH'; | ||||
435 | @$hash{ keys %$imp } = values %$imp; | ||||
436 | return ''; | ||||
437 | } | ||||
438 | |||||
439 | sub hash_sort { | ||||
440 | my ($hash) = @_; | ||||
441 | [ sort { lc $hash->{$a} cmp lc $hash->{$b} } (keys %$hash) ]; | ||||
442 | } | ||||
443 | |||||
444 | sub hash_nsort { | ||||
445 | my ($hash) = @_; | ||||
446 | [ sort { $hash->{$a} <=> $hash->{$b} } (keys %$hash) ]; | ||||
447 | } | ||||
448 | |||||
449 | |||||
450 | #======================================================================== | ||||
451 | # list virtual methods | ||||
452 | #======================================================================== | ||||
453 | |||||
454 | |||||
455 | sub list_item { | ||||
456 | $_[0]->[ $_[1] || 0 ]; | ||||
457 | } | ||||
458 | |||||
459 | sub list_list { | ||||
460 | $_[0]; | ||||
461 | } | ||||
462 | |||||
463 | sub list_hash { | ||||
464 | my $list = shift; | ||||
465 | if (@_) { | ||||
466 | my $n = shift || 0; | ||||
467 | return { map { ($n++, $_) } @$list }; | ||||
468 | } | ||||
469 | 2 | 142µs | 2 | 40µs | # spent 25µs (10+15) within Template::VMethods::BEGIN@469 which was called:
# once (10µs+15µs) by Template::Stash::BEGIN@24 at line 469 # spent 25µs making 1 call to Template::VMethods::BEGIN@469
# spent 15µs making 1 call to warnings::unimport |
470 | return { @$list }; | ||||
471 | } | ||||
472 | |||||
473 | sub list_push { | ||||
474 | my $list = shift; | ||||
475 | push(@$list, @_); | ||||
476 | return ''; | ||||
477 | } | ||||
478 | |||||
479 | sub list_pop { | ||||
480 | my $list = shift; | ||||
481 | pop(@$list); | ||||
482 | } | ||||
483 | |||||
484 | sub list_unshift { | ||||
485 | my $list = shift; | ||||
486 | unshift(@$list, @_); | ||||
487 | return ''; | ||||
488 | } | ||||
489 | |||||
490 | sub list_shift { | ||||
491 | my $list = shift; | ||||
492 | shift(@$list); | ||||
493 | } | ||||
494 | |||||
495 | sub list_max { | ||||
496 | 2 | 40µs | 2 | 28µs | # spent 17µs (6+11) within Template::VMethods::BEGIN@496 which was called:
# once (6µs+11µs) by Template::Stash::BEGIN@24 at line 496 # spent 17µs making 1 call to Template::VMethods::BEGIN@496
# spent 11µs making 1 call to warnings::unimport |
497 | my $list = shift; | ||||
498 | $#$list; | ||||
499 | } | ||||
500 | |||||
501 | sub list_size { | ||||
502 | 2 | 926µs | 2 | 25µs | # spent 15µs (6+10) within Template::VMethods::BEGIN@502 which was called:
# once (6µs+10µs) by Template::Stash::BEGIN@24 at line 502 # spent 15µs making 1 call to Template::VMethods::BEGIN@502
# spent 10µs making 1 call to warnings::unimport |
503 | my $list = shift; | ||||
504 | $#$list + 1; | ||||
505 | } | ||||
506 | |||||
507 | sub list_empty { | ||||
508 | return 0 == list_size($_[0]) ? 1 : 0; | ||||
509 | } | ||||
510 | |||||
511 | sub list_defined { | ||||
512 | # return the item requested, or 1 if no argument to | ||||
513 | # indicate that the hash itself is defined | ||||
514 | my $list = shift; | ||||
515 | return 1 unless @_; # list.defined is always true | ||||
516 | return unless looks_like_number $_[0]; # list.defined('bah') is always false | ||||
517 | return defined $list->[$_[0]]; # list.defined(n) | ||||
518 | } | ||||
519 | |||||
520 | sub list_first { | ||||
521 | my $list = shift; | ||||
522 | return $list->[0] unless @_; | ||||
523 | return [ @$list[0..$_[0]-1] ]; | ||||
524 | } | ||||
525 | |||||
526 | sub list_last { | ||||
527 | my $list = shift; | ||||
528 | return $list->[-1] unless @_; | ||||
529 | return [ @$list[-$_[0]..-1] ]; | ||||
530 | } | ||||
531 | |||||
532 | sub list_reverse { | ||||
533 | my $list = shift; | ||||
534 | [ reverse @$list ]; | ||||
535 | } | ||||
536 | |||||
537 | sub list_grep { | ||||
538 | my ($list, $pattern) = @_; | ||||
539 | $pattern ||= ''; | ||||
540 | return [ grep /$pattern/, @$list ]; | ||||
541 | } | ||||
542 | |||||
543 | sub list_join { | ||||
544 | my ($list, $joint) = @_; | ||||
545 | join(defined $joint ? $joint : ' ', | ||||
546 | map { defined $_ ? $_ : '' } @$list); | ||||
547 | } | ||||
548 | |||||
549 | sub _list_sort_make_key { | ||||
550 | my ($item, $fields) = @_; | ||||
551 | my @keys; | ||||
552 | |||||
553 | if (ref($item) eq 'HASH') { | ||||
554 | @keys = map { $item->{ $_ } } @$fields; | ||||
555 | } | ||||
556 | elsif (blessed $item) { | ||||
557 | @keys = map { $item->can($_) ? $item->$_() : $item } @$fields; | ||||
558 | } | ||||
559 | else { | ||||
560 | @keys = $item; | ||||
561 | } | ||||
562 | |||||
563 | # ugly hack to generate a single string using a delimiter that is | ||||
564 | # unlikely (but not impossible) to be found in the wild. | ||||
565 | return lc join('/*^UNLIKELY^*/', map { defined $_ ? $_ : '' } @keys); | ||||
566 | } | ||||
567 | |||||
568 | # spent 77.9ms (57.2+20.7) within Template::VMethods::list_sort which was called 1991 times, avg 39µs/call:
# 1991 times (57.2ms+20.7ms) by Template::Stash::XS::get at line 11 of /root/tor-browser-build/input text, avg 39µs/call | ||||
569 | 1991 | 1.76ms | my ($list, @fields) = @_; | ||
570 | 1991 | 2.62ms | return $list unless @$list > 1; # no need to sort 1 item lists | ||
571 | return [ | ||||
572 | @fields # Schwartzian Transform | ||||
573 | ? map { $_->[0] } # for case insensitivity | ||||
574 | sort { $a->[1] cmp $b->[1] } | ||||
575 | map { [ $_, _list_sort_make_key($_, \@fields) ] } | ||||
576 | @$list | ||||
577 | : map { $_->[0] } | ||||
578 | sort { $a->[1] cmp $b->[1] } | ||||
579 | 1991 | 74.1ms | 1991 | 20.7ms | map { [ $_, lc $_ ] } # spent 20.7ms making 1991 calls to Template::VMethods::CORE:sort, avg 10µs/call |
580 | @$list, | ||||
581 | ]; | ||||
582 | } | ||||
583 | |||||
584 | sub list_nsort { | ||||
585 | my ($list, @fields) = @_; | ||||
586 | return $list unless @$list > 1; # no need to sort 1 item lists | ||||
587 | |||||
588 | my $sort = sub { | ||||
589 | my $cmp; | ||||
590 | |||||
591 | if(@fields) { | ||||
592 | # compare each field individually | ||||
593 | for my $field (@fields) { | ||||
594 | my $A = _list_sort_make_key($a, [ $field ]); | ||||
595 | my $B = _list_sort_make_key($b, [ $field ]); | ||||
596 | ($cmp = $A <=> $B) and last; | ||||
597 | } | ||||
598 | } | ||||
599 | else { | ||||
600 | my $A = _list_sort_make_key($a); | ||||
601 | my $B = _list_sort_make_key($b); | ||||
602 | $cmp = $A <=> $B; | ||||
603 | } | ||||
604 | |||||
605 | $cmp; | ||||
606 | }; | ||||
607 | |||||
608 | return [ sort $sort @{ $list } ]; | ||||
609 | } | ||||
610 | |||||
611 | sub list_unique { | ||||
612 | my %u; | ||||
613 | [ grep { ++$u{$_} == 1 } @{$_[0]} ]; | ||||
614 | } | ||||
615 | |||||
616 | # spent 24.1ms within Template::VMethods::list_import which was called 1991 times, avg 12µs/call:
# 1991 times (24.1ms+0s) by Template::Stash::XS::get at line 11 of /root/tor-browser-build/input text, avg 12µs/call | ||||
617 | 1991 | 949µs | my $list = shift; | ||
618 | 1991 | 15.8ms | push(@$list, grep defined, map ref eq 'ARRAY' ? @$_ : undef, @_); | ||
619 | 1991 | 7.12ms | return $list; | ||
620 | } | ||||
621 | |||||
622 | sub list_merge { | ||||
623 | my $list = shift; | ||||
624 | return [ @$list, grep defined, map ref eq 'ARRAY' ? @$_ : undef, @_ ]; | ||||
625 | } | ||||
626 | |||||
627 | sub list_slice { | ||||
628 | my ($list, $from, $to) = @_; | ||||
629 | $from ||= 0; | ||||
630 | $to = $#$list unless defined $to; | ||||
631 | $from += @$list if $from < 0; | ||||
632 | $to += @$list if $to < 0; | ||||
633 | return [ @$list[$from..$to] ]; | ||||
634 | } | ||||
635 | |||||
636 | sub list_splice { | ||||
637 | my ($list, $offset, $length, @replace) = @_; | ||||
638 | if (@replace) { | ||||
639 | # @replace can contain a list of multiple replace items, or | ||||
640 | # be a single reference to a list | ||||
641 | @replace = @{ $replace[0] } | ||||
642 | if @replace == 1 && ref $replace[0] eq 'ARRAY'; | ||||
643 | return [ splice @$list, $offset, $length, @replace ]; | ||||
644 | } | ||||
645 | elsif (defined $length) { | ||||
646 | return [ splice @$list, $offset, $length ]; | ||||
647 | } | ||||
648 | elsif (defined $offset) { | ||||
649 | return [ splice @$list, $offset ]; | ||||
650 | } | ||||
651 | else { | ||||
652 | return [ splice(@$list) ]; | ||||
653 | } | ||||
654 | } | ||||
655 | |||||
656 | 1 | 25µs | 1; | ||
657 | |||||
658 | __END__ | ||||
# spent 20.7ms within Template::VMethods::CORE:sort which was called 1991 times, avg 10µs/call:
# 1991 times (20.7ms+0s) by Template::VMethods::list_sort at line 579, avg 10µs/call | |||||
# spent 600ns within Template::VMethods::__ANON__ which was called:
# once (600ns+0s) by Template::VMethods::BEGIN@27 at line 27 |