Filename | /var/www/foswikidev/core/lib/Foswiki/Prefs/Stack.pm |
Statements | Executed 13708 statements in 30.2ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
15 | 2 | 2 | 2.70ms | 2.70ms | restore | Foswiki::Prefs::Stack::
63 | 8 | 1 | 2.42ms | 2.79ms | newLevel | Foswiki::Prefs::Stack::
673 | 1 | 1 | 2.02ms | 2.02ms | finalizedBefore | Foswiki::Prefs::Stack::
111 | 1 | 1 | 1.67ms | 2.57ms | getPreference | Foswiki::Prefs::Stack::
782 | 3 | 1 | 1.22ms | 1.22ms | backAtLevel | Foswiki::Prefs::Stack::
673 | 1 | 1 | 1.07ms | 1.07ms | prefIsDefined | Foswiki::Prefs::Stack::
209 | 2 | 1 | 978µs | 978µs | _getLevel | Foswiki::Prefs::Stack::
101 | 1 | 1 | 419µs | 788µs | getDefinitionLevel | Foswiki::Prefs::Stack::
62 | 2 | 1 | 385µs | 851µs | insert | Foswiki::Prefs::Stack::
18 | 2 | 2 | 271µs | 433µs | finish | Foswiki::Prefs::Stack::
7 | 1 | 1 | 163µs | 516µs | clone | Foswiki::Prefs::Stack::
24 | 3 | 2 | 118µs | 118µs | new | Foswiki::Prefs::Stack::
40 | 4 | 2 | 61µs | 61µs | size | Foswiki::Prefs::Stack::
10 | 1 | 1 | 26µs | 26µs | finalized | Foswiki::Prefs::Stack::
1 | 1 | 1 | 13µs | 26µs | BEGIN@26 | Foswiki::Prefs::Stack::
1 | 1 | 1 | 10µs | 12µs | BEGIN@28 | Foswiki::Prefs::Stack::
1 | 1 | 1 | 8µs | 13µs | BEGIN@27 | Foswiki::Prefs::Stack::
1 | 1 | 1 | 4µs | 4µs | BEGIN@30 | Foswiki::Prefs::Stack::
0 | 0 | 0 | 0s | 0s | prefs | Foswiki::Prefs::Stack::
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 | ---+ UNPUBLISHED package Foswiki::Prefs::Stack | ||||
6 | |||||
7 | Foswiki preferences mechanism are like stacks: | ||||
8 | * Preferences pushed later have precedence over ones pushed earlier I must | ||||
9 | * be able to return (restore) to a state I was earlier | ||||
10 | |||||
11 | This stack can exist as an index, so preference data is not copied everywhere. | ||||
12 | |||||
13 | The index is composed by three elements: | ||||
14 | * A bitstring map. Each preference has a bitmap. Each bit corresponds to a | ||||
15 | level. The bit is 1 if the preference is defined at that level and 0 | ||||
16 | otherwise. If a preference is "defined" in some level, but it was | ||||
17 | finalized, then the corresponding bit is 0. | ||||
18 | * A level list storing a backend object that is associated with each level | ||||
19 | * A final hash that maps preferences to the level they were finalized. | ||||
20 | |||||
21 | This class deals with this stuff and must be used only by =Foswiki::Prefs= | ||||
22 | |||||
23 | =cut | ||||
24 | |||||
25 | package Foswiki::Prefs::Stack; | ||||
26 | 2 | 26µs | 2 | 38µs | # spent 26µs (13+13) within Foswiki::Prefs::Stack::BEGIN@26 which was called:
# once (13µs+13µs) by Foswiki::Prefs::BEGIN@77 at line 26 # spent 26µs making 1 call to Foswiki::Prefs::Stack::BEGIN@26
# spent 13µs making 1 call to strict::import |
27 | 2 | 22µs | 2 | 17µs | # spent 13µs (8+4) within Foswiki::Prefs::Stack::BEGIN@27 which was called:
# once (8µs+4µs) by Foswiki::Prefs::BEGIN@77 at line 27 # spent 13µs making 1 call to Foswiki::Prefs::Stack::BEGIN@27
# spent 4µs making 1 call to warnings::import |
28 | 2 | 55µs | 2 | 15µs | # spent 12µs (10+3) within Foswiki::Prefs::Stack::BEGIN@28 which was called:
# once (10µs+3µs) by Foswiki::Prefs::BEGIN@77 at line 28 # spent 12µs making 1 call to Foswiki::Prefs::Stack::BEGIN@28
# spent 3µs making 1 call to bytes::import |
29 | |||||
30 | # spent 4µs within Foswiki::Prefs::Stack::BEGIN@30 which was called:
# once (4µs+0s) by Foswiki::Prefs::BEGIN@77 at line 35 | ||||
31 | 1 | 4µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
32 | require locale; | ||||
33 | import locale(); | ||||
34 | } | ||||
35 | 1 | 935µs | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::Prefs::Stack::BEGIN@30 |
36 | |||||
37 | =begin TML | ||||
38 | |||||
39 | ---++ ClassMethod new( $session ) | ||||
40 | |||||
41 | Creates a new Stack object. | ||||
42 | |||||
43 | =cut | ||||
44 | |||||
45 | # spent 118µs within Foswiki::Prefs::Stack::new which was called 24 times, avg 5µs/call:
# 16 times (79µs+0s) by Foswiki::Prefs::_getWebPrefsObj at line 188 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 5µs/call
# 7 times (27µs+0s) by Foswiki::Prefs::Stack::clone at line 277, avg 4µs/call
# once (13µs+0s) by Foswiki::Prefs::new at line 92 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm | ||||
46 | 24 | 10µs | my $proto = shift; | ||
47 | 24 | 10µs | my $class = ref($proto) || $proto; | ||
48 | 24 | 49µs | my $this = { | ||
49 | 'final' => {}, # Map preferences to the level the were finalized. | ||||
50 | 'levels' => [], # Maps leves to the corresponding backend objects. | ||||
51 | 'map' => {}, # Associate each preference with its bitstring map. | ||||
52 | }; | ||||
53 | 24 | 81µs | return bless $this, $class; | ||
54 | } | ||||
55 | |||||
56 | =begin TML | ||||
57 | |||||
58 | ---++ ObjectMethod finish() | ||||
59 | |||||
60 | Break circular references. | ||||
61 | |||||
62 | =cut | ||||
63 | |||||
64 | # Note to developers; please undef *all* fields in the object explicitly, | ||||
65 | # whether they are references or not. That way this method is "golden | ||||
66 | # documentation" of the live fields in the object. | ||||
67 | # spent 433µs (271+162) within Foswiki::Prefs::Stack::finish which was called 18 times, avg 24µs/call:
# 17 times (99µs+28µs) by Foswiki::Prefs::Web::finish at line 60 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 7µs/call
# once (173µs+134µs) by Foswiki::Prefs::finish at line 122 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm | ||||
68 | 18 | 3µs | my $this = shift; | ||
69 | 18 | 20µs | undef $this->{'final'}; | ||
70 | 18 | 12µs | if ( $this->{'levels'} ) { | ||
71 | foreach my $back ( @{ $this->{'levels'} } ) { | ||||
72 | 38 | 172µs | 38 | 162µs | $back->finish(); # spent 160µs making 37 calls to Foswiki::Prefs::TopicRAM::finish, avg 4µs/call
# spent 2µs making 1 call to Foswiki::Prefs::HASH::finish |
73 | } | ||||
74 | } | ||||
75 | 18 | 14µs | undef $this->{'levels'}; | ||
76 | 18 | 30µs | undef $this->{'map'}; | ||
77 | } | ||||
78 | |||||
79 | =begin TML | ||||
80 | |||||
81 | ---++ ObjectMethod size() -> $size | ||||
82 | |||||
83 | Returns the size of the stack in number of levels. | ||||
84 | |||||
85 | =cut | ||||
86 | |||||
87 | # spent 61µs within Foswiki::Prefs::Stack::size which was called 40 times, avg 2µs/call:
# 16 times (21µs+0s) by Foswiki::Prefs::_pushWebInStack at line 163 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 1µs/call
# 9 times (15µs+0s) by Foswiki::Prefs::pushTopicContext at line 274 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call
# 8 times (14µs+0s) by Foswiki::Prefs::Web::isInTopOfStack at line 75 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 2µs/call
# 7 times (11µs+0s) by Foswiki::Prefs::setPluginPreferences at line 338 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call | ||||
88 | 40 | 125µs | return scalar( @{ $_[0]->{levels} } ); | ||
89 | } | ||||
90 | |||||
91 | =begin TML | ||||
92 | |||||
93 | ---++ ObjectMethod backAtLevel($level) -> $back | ||||
94 | |||||
95 | Returns the backend object corresponding to $level. If $level is negative, | ||||
96 | consider that number from the top of the stack. -1 means the top element. | ||||
97 | |||||
98 | =cut | ||||
99 | |||||
100 | # spent 1.22ms within Foswiki::Prefs::Stack::backAtLevel which was called 782 times, avg 2µs/call:
# 673 times (1.09ms+0s) by Foswiki::Prefs::getPreference at line 447 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call
# 101 times (117µs+0s) by Foswiki::Prefs::getPreference at line 455 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 1µs/call
# 8 times (15µs+0s) by Foswiki::Prefs::popTopicContext at line 318 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call | ||||
101 | 782 | 2.33ms | return $_[0]->{levels}->[ $_[1] ]; | ||
102 | } | ||||
103 | |||||
104 | =begin TML | ||||
105 | |||||
106 | ---++ ObjectMethod finalizedBefore($pref, $level) -> $boolean | ||||
107 | |||||
108 | Returns true if $pref was finalized somewhere earlier than $level. If $pref is | ||||
109 | finalized *in* $level or it's not finalized, returns true. | ||||
110 | |||||
111 | =cut | ||||
112 | |||||
113 | # spent 2.02ms within Foswiki::Prefs::Stack::finalizedBefore which was called 673 times, avg 3µs/call:
# 673 times (2.02ms+0s) by Foswiki::Prefs::getPreference at line 448 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 3µs/call | ||||
114 | 673 | 350µs | my ( $this, $key, $level ) = @_; | ||
115 | 673 | 448µs | $level += @{ $this->{levels} } if $level < 0; | ||
116 | 673 | 15.0ms | return exists $this->{final}{$key} && $this->{final}{$key} < $level; | ||
117 | } | ||||
118 | |||||
119 | =begin TML | ||||
120 | |||||
121 | ---++ ObjectMethod finalized($pref) -> $boolean | ||||
122 | |||||
123 | Returns true if $pref in finalized. | ||||
124 | |||||
125 | =cut | ||||
126 | |||||
127 | # spent 26µs within Foswiki::Prefs::Stack::finalized which was called 10 times, avg 3µs/call:
# 10 times (26µs+0s) by Foswiki::Prefs::setSessionPreferences at line 402 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 3µs/call | ||||
128 | 10 | 6µs | my ( $this, $key ) = @_; | ||
129 | 10 | 35µs | return exists $this->{final}{$key}; | ||
130 | } | ||||
131 | |||||
132 | =begin TML | ||||
133 | |||||
134 | ---++ ObjectMethod prefs() -> @prefs | ||||
135 | |||||
136 | Returns a list with the name of all defined prefs in the stack. | ||||
137 | |||||
138 | =cut | ||||
139 | |||||
140 | sub prefs { | ||||
141 | return keys %{ $_[0]->{'map'} }; | ||||
142 | } | ||||
143 | |||||
144 | =begin TML | ||||
145 | |||||
146 | ---++ ObjectMethod prefIsDefined($pref) -> $boolean | ||||
147 | |||||
148 | Returns true if $pref is defined somewhere in the stack. | ||||
149 | |||||
150 | =cut | ||||
151 | |||||
152 | # spent 1.07ms within Foswiki::Prefs::Stack::prefIsDefined which was called 673 times, avg 2µs/call:
# 673 times (1.07ms+0s) by Foswiki::Prefs::getPreference at line 451 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call | ||||
153 | 673 | 1.75ms | return exists $_[0]->{'map'}{ $_[1] }; | ||
154 | } | ||||
155 | |||||
156 | =begin TML | ||||
157 | |||||
158 | ---++ ObjectMethod insert($type, $pref, $value) -> $num | ||||
159 | |||||
160 | Define preference named $pref of type $type as $value. $type can be 'Local' or | ||||
161 | 'Set'. | ||||
162 | |||||
163 | Returns the number of inserted preferences (0 or 1). | ||||
164 | |||||
165 | =cut | ||||
166 | |||||
167 | # spent 851µs (385+466) within Foswiki::Prefs::Stack::insert which was called 62 times, avg 14µs/call:
# 52 times (310µs+363µs) by Foswiki::Prefs::pushTopicContext at line 290 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 13µs/call
# 10 times (75µs+103µs) by Foswiki::Prefs::setSessionPreferences at line 403 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 18µs/call | ||||
168 | 62 | 14µs | my $this = shift; | ||
169 | |||||
170 | 62 | 24µs | my $back = $this->{levels}->[-1]; | ||
171 | 62 | 58µs | 62 | 466µs | my $num = $back->insert(@_); # spent 466µs making 62 calls to Foswiki::Prefs::HASH::insert, avg 8µs/call |
172 | |||||
173 | 62 | 13µs | my $key = $_[1]; | ||
174 | 62 | 37µs | $this->{'map'}{$key} = '' unless exists $this->{'map'}{$key}; | ||
175 | |||||
176 | 62 | 24µs | my $level = $#{ $this->{levels} }; | ||
177 | 62 | 74µs | vec( $this->{'map'}{$key}, $level, 1 ) = 1; | ||
178 | |||||
179 | 62 | 128µs | return $num; | ||
180 | } | ||||
181 | |||||
182 | =begin TML | ||||
183 | |||||
184 | ---++ ObjectMethod newLevel($back, $prefix) | ||||
185 | |||||
186 | Pushes all preferences in $back on the stack, except for the finalized ones. | ||||
187 | Optionally $prefix preferences name in the index. This feature is used by | ||||
188 | plugins: A preference PREF defined in MyPlugin topic should be referenced by | ||||
189 | MYPLUGIN_PREF. In this example $prefix is MYPLUGIN_. | ||||
190 | |||||
191 | =cut | ||||
192 | |||||
193 | # spent 2.79ms (2.42+362µs) within Foswiki::Prefs::Stack::newLevel which was called 63 times, avg 44µs/call:
# 18 times (948µs+126µs) by Foswiki::Prefs::pushTopicContext at line 284 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 60µs/call
# 17 times (781µs+107µs) by Foswiki::Prefs::_pushWebInStack at line 169 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 52µs/call
# 9 times (87µs+32µs) by Foswiki::Prefs::pushTopicContext at line 288 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 13µs/call
# 9 times (78µs+24µs) by Foswiki::Prefs::pushTopicContext at line 287 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 11µs/call
# 7 times (174µs+31µs) by Foswiki::Prefs::setPluginPreferences at line 337 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 29µs/call
# once (301µs+33µs) by Foswiki::Prefs::loadDefaultPreferences at line 368 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm
# once (41µs+5µs) by Foswiki::Prefs::loadSitePreferences at line 385 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm
# once (14µs+4µs) by Foswiki::Prefs::setUserPreferences at line 353 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm | ||||
194 | 63 | 30µs | my ( $this, $back, $prefix ) = @_; | ||
195 | |||||
196 | 63 | 38µs | push @{ $this->{levels} }, $back; | ||
197 | 63 | 32µs | my $level = $#{ $this->{levels} }; | ||
198 | 63 | 18µs | $prefix ||= ''; | ||
199 | 63 | 397µs | 63 | 249µs | foreach ( map { $prefix . $_ } $back->prefs ) { # spent 232µs making 54 calls to Foswiki::Prefs::TopicRAM::prefs, avg 4µs/call
# spent 17µs making 9 calls to Foswiki::Prefs::HASH::prefs, avg 2µs/call |
200 | 773 | 229µs | next if exists $this->{final}{$_}; | ||
201 | 714 | 383µs | $this->{'map'}{$_} = '' unless exists $this->{'map'}{$_}; | ||
202 | 714 | 657µs | vec( $this->{'map'}{$_}, $level, 1 ) = 1; | ||
203 | } | ||||
204 | |||||
205 | 63 | 240µs | 63 | 114µs | my @finalPrefs = split /[,\s]+/, ( $back->get('FINALPREFERENCES') || '' ); # spent 98µs making 54 calls to Foswiki::Prefs::TopicRAM::get, avg 2µs/call
# spent 15µs making 9 calls to Foswiki::Prefs::HASH::get, avg 2µs/call |
206 | 63 | 41µs | foreach (@finalPrefs) { | ||
207 | 196 | 122µs | $this->{final}{$_} = $level | ||
208 | unless exists $this->{final}{$_}; | ||||
209 | } | ||||
210 | |||||
211 | 63 | 150µs | return $back; | ||
212 | } | ||||
213 | |||||
214 | =begin TML | ||||
215 | |||||
216 | ---++ ObjectMethod getDefinitionLevel($pref) -> $level | ||||
217 | |||||
218 | Returns the $level in which $pref was defined or undef if it's not defined. | ||||
219 | |||||
220 | =cut | ||||
221 | |||||
222 | # spent 788µs (419+369) within Foswiki::Prefs::Stack::getDefinitionLevel which was called 101 times, avg 8µs/call:
# 101 times (419µs+369µs) by Foswiki::Prefs::getPreference at line 452 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 8µs/call | ||||
223 | 101 | 45µs | my ( $this, $pref ) = @_; | ||
224 | return | ||||
225 | 101 | 312µs | 101 | 369µs | exists $this->{'map'}{$pref} ? _getLevel( $this->{'map'}{$pref} ) : undef; # spent 369µs making 101 calls to Foswiki::Prefs::Stack::_getLevel, avg 4µs/call |
226 | } | ||||
227 | |||||
228 | # Used to get the level of the highest 1, given a bitstring map. | ||||
229 | sub _getLevel { | ||||
230 | 209 | 107µs | my $map = shift; | ||
231 | return | ||||
232 | 209 | 1.09ms | int( log( ord( substr( $map, -1 ) ) ) / log(2) ) + | ||
233 | ( ( length($map) - 1 ) * 8 ); | ||||
234 | } | ||||
235 | |||||
236 | =begin TML | ||||
237 | |||||
238 | ---++ ObjectMethod getPreference($pref [, $level] ) -> $value | ||||
239 | |||||
240 | Returns the $value of $pref, considering the stack rules (values in higher | ||||
241 | levels overrides those in lower levels). | ||||
242 | |||||
243 | Optionally consider preferences at most $level. This is usefull to get a | ||||
244 | preference of Web if the stack has Web/Subweb. This makes it possible to use | ||||
245 | the same stack for Web and Web/Subweb. | ||||
246 | |||||
247 | =cut | ||||
248 | |||||
249 | # spent 2.57ms (1.67+902µs) within Foswiki::Prefs::Stack::getPreference which was called 111 times, avg 23µs/call:
# 111 times (1.67ms+902µs) by Foswiki::Prefs::Web::get at line 117 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 23µs/call | ||||
250 | 111 | 64µs | my ( $this, $key, $level ) = @_; | ||
251 | 111 | 96µs | my $map = $this->{'map'}{$key}; | ||
252 | 111 | 25µs | return unless defined $map; | ||
253 | 108 | 49µs | if ( defined $level ) { | ||
254 | 108 | 365µs | my $mask = | ||
255 | ( chr(0xFF) x int( $level / 8 ) ) | ||||
256 | . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 ); | ||||
257 | 108 | 84µs | $map &= $mask; | ||
258 | 108 | 173µs | substr( $map, -1 ) = '' | ||
259 | while length($map) > 0 && ord( substr( $map, -1 ) ) == 0; | ||||
260 | 108 | 37µs | return unless length($map) > 0; | ||
261 | } | ||||
262 | 108 | 673µs | 216 | 902µs | return $this->{levels}->[ _getLevel($map) ]->get($key); # spent 609µs making 108 calls to Foswiki::Prefs::Stack::_getLevel, avg 6µs/call
# spent 293µs making 108 calls to Foswiki::Prefs::TopicRAM::get, avg 3µs/call |
263 | } | ||||
264 | |||||
265 | =begin TML | ||||
266 | |||||
267 | ---++ ObjectMethod clone($level ) -> $stack | ||||
268 | |||||
269 | This constructs a new $stack object as a clone of this one, up to the given | ||||
270 | $level. If no $level is given, the resulting object is an extac copy. | ||||
271 | |||||
272 | =cut | ||||
273 | |||||
274 | # spent 516µs (163+353) within Foswiki::Prefs::Stack::clone which was called 7 times, avg 74µs/call:
# 7 times (163µs+353µs) by Foswiki::Prefs::Web::cloneStack at line 104 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 74µs/call | ||||
275 | 7 | 2µs | my ( $this, $level ) = @_; | ||
276 | |||||
277 | 7 | 6µs | 7 | 27µs | my $clone = $this->new(); # spent 27µs making 7 calls to Foswiki::Prefs::Stack::new, avg 4µs/call |
278 | 7 | 81µs | $clone->{'map'} = { %{ $this->{'map'} } }; | ||
279 | 7 | 8µs | $clone->{'levels'} = [ @{ $this->{levels} } ]; | ||
280 | 7 | 20µs | $clone->{'final'} = { %{ $this->{final} } }; | ||
281 | 7 | 15µs | 7 | 326µs | $clone->restore($level) if defined $level; # spent 326µs making 7 calls to Foswiki::Prefs::Stack::restore, avg 47µs/call |
282 | |||||
283 | 7 | 15µs | return $clone; | ||
284 | } | ||||
285 | |||||
286 | =begin TML | ||||
287 | |||||
288 | ---++ ObjectMethod restore($level) | ||||
289 | |||||
290 | Restores tha stack to the state it was in the given $level. | ||||
291 | |||||
292 | =cut | ||||
293 | |||||
294 | # spent 2.70ms within Foswiki::Prefs::Stack::restore which was called 15 times, avg 180µs/call:
# 8 times (2.37ms+0s) by Foswiki::Prefs::popTopicContext at line 313 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 297µs/call
# 7 times (326µs+0s) by Foswiki::Prefs::Stack::clone at line 281, avg 47µs/call | ||||
295 | 15 | 7µs | my ( $this, $level ) = @_; | ||
296 | |||||
297 | 15 | 136µs | my @keys = grep { $this->{final}{$_} > $level } keys %{ $this->{final} }; | ||
298 | 15 | 7µs | delete @{ $this->{final} }{@keys}; | ||
299 | 15 | 28µs | splice @{ $this->{levels} }, $level + 1; | ||
300 | |||||
301 | 15 | 37µs | my $mask = | ||
302 | ( chr(0xFF) x int( $level / 8 ) ) | ||||
303 | . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 ); | ||||
304 | 15 | 233µs | foreach my $p ( keys %{ $this->{'map'} } ) { | ||
305 | 1564 | 430µs | $this->{'map'}{$p} &= $mask; | ||
306 | |||||
307 | 1564 | 1.05ms | while ( length( $this->{'map'}{$p} ) > 0 | ||
308 | && ord( substr( $this->{'map'}{$p}, -1 ) ) == 0 ) | ||||
309 | { | ||||
310 | 113 | 99µs | substr( $this->{'map'}{$p}, -1 ) = ''; | ||
311 | } | ||||
312 | |||||
313 | 1564 | 694µs | delete $this->{'map'}{$p} if length( $this->{'map'}{$p} ) == 0; | ||
314 | } | ||||
315 | } | ||||
316 | |||||
317 | 1 | 2µs | 1; | ||
318 | __END__ |