Filename | /home/ss5/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/Iterator.pm |
Statements | Executed 13 statements in 4.12ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 5.82ms | 43.0ms | BEGIN@22 | Iterator::
1 | 1 | 1 | 54µs | 69µs | BEGIN@15 | Iterator::Util::
1 | 1 | 1 | 29µs | 58µs | BEGIN@16 | Iterator::Util::
1 | 1 | 1 | 17µs | 17µs | BEGIN@69 | Iterator::
0 | 0 | 0 | 0s | 0s | DESTROY | Iterator::
0 | 0 | 0 | 0s | 0s | location | Iterator::X::Internal_Error::
0 | 0 | 0 | 0s | 0s | full_message | Iterator::X::
0 | 0 | 0 | 0s | 0s | location | Iterator::X::
0 | 0 | 0 | 0s | 0s | __ANON__[:78] | Iterator::
0 | 0 | 0 | 0s | 0s | _initialize | Iterator::
0 | 0 | 0 | 0s | 0s | is_done | Iterator::
0 | 0 | 0 | 0s | 0s | is_exhausted | Iterator::
0 | 0 | 0 | 0s | 0s | isnt_exhausted | Iterator::
0 | 0 | 0 | 0s | 0s | new | Iterator::
0 | 0 | 0 | 0s | 0s | value | Iterator::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | =for gpg | ||||
2 | -----BEGIN PGP SIGNED MESSAGE----- | ||||
3 | Hash: SHA1 | ||||
4 | |||||
5 | =head1 NAME | ||||
6 | |||||
7 | Iterator - A general-purpose iterator class. | ||||
8 | |||||
9 | =head1 VERSION | ||||
10 | |||||
11 | This documentation describes version 0.03 of Iterator.pm, October 10, 2005. | ||||
12 | |||||
13 | =cut | ||||
14 | |||||
15 | 2 | 94µs | 2 | 84µs | # spent 69µs (54+15) within Iterator::Util::BEGIN@15 which was called:
# once (54µs+15µs) by Iterator::Util::BEGIN@28 at line 15 # spent 69µs making 1 call to Iterator::Util::BEGIN@15
# spent 15µs making 1 call to strict::import |
16 | 2 | 505µs | 2 | 88µs | # spent 58µs (29+29) within Iterator::Util::BEGIN@16 which was called:
# once (29µs+29µs) by Iterator::Util::BEGIN@28 at line 16 # spent 58µs making 1 call to Iterator::Util::BEGIN@16
# spent 29µs making 1 call to warnings::import |
17 | package Iterator; | ||||
18 | 1 | 3µs | our $VERSION = '0.03'; | ||
19 | |||||
20 | # Declare exception classes | ||||
21 | use Exception::Class | ||||
22 | # spent 43.0ms (5.82+37.1) within Iterator::BEGIN@22 which was called:
# once (5.82ms+37.1ms) by Iterator::Util::BEGIN@28 at line 65 | ||||
23 | 1 | 7.40ms | 'Iterator::X' => # spent 7.40ms making 1 call to Exception::Class::import | ||
24 | { | ||||
25 | description => 'Generic Iterator exception', | ||||
26 | }, | ||||
27 | 'Iterator::X::Parameter_Error' => | ||||
28 | { | ||||
29 | isa => 'Iterator::X', | ||||
30 | description => 'Iterator method parameter error', | ||||
31 | }, | ||||
32 | 'Iterator::X::OptionError' => | ||||
33 | { | ||||
34 | isa => 'Iterator::X', | ||||
35 | fields => 'name', | ||||
36 | description => 'A bad option was passed to an iterator method or function', | ||||
37 | }, | ||||
38 | 'Iterator::X::Exhausted' => | ||||
39 | { | ||||
40 | isa => 'Iterator::X', | ||||
41 | description => 'Attempt to next_value () on an exhausted iterator', | ||||
42 | }, | ||||
43 | 'Iterator::X::Am_Now_Exhausted' => | ||||
44 | { | ||||
45 | isa => 'Iterator::X', | ||||
46 | description => 'Signals Iterator object that it is now exhausted', | ||||
47 | }, | ||||
48 | 'Iterator::X::User_Code_Error' => | ||||
49 | { | ||||
50 | isa => 'Iterator::X', | ||||
51 | fields => 'eval_error', | ||||
52 | description => q{An exception was thrown within the user's code}, | ||||
53 | }, | ||||
54 | 'Iterator::X::IO_Error' => | ||||
55 | { | ||||
56 | isa => 'Iterator::X', | ||||
57 | fields => 'os_error', | ||||
58 | description => q{An I/O error occurred}, | ||||
59 | }, | ||||
60 | 'Iterator::X::Internal_Error' => | ||||
61 | { | ||||
62 | isa => 'Iterator::X', | ||||
63 | description => 'An Iterator.pm internal error. Please contact author.', | ||||
64 | }, | ||||
65 | 2 | 715µs | 1 | 43.0ms | ); # spent 43.0ms making 1 call to Iterator::BEGIN@22 |
66 | |||||
67 | # Class method to help caller catch exceptions | ||||
68 | BEGIN | ||||
69 | # spent 17µs within Iterator::BEGIN@69 which was called:
# once (17µs+0s) by Iterator::Util::BEGIN@28 at line 80 | ||||
70 | # Dave Rolsky added this subroutine in v1.22 of Exception::Class. | ||||
71 | # Thanks, Dave! | ||||
72 | # We define it here so we have the functionality in pre-1.22 versions; | ||||
73 | # we make it conditional so as to avoid a warning in post-1.22 versions. | ||||
74 | *Exception::Class::Base::caught = sub | ||||
75 | { | ||||
76 | my $class = shift; | ||||
77 | return Exception::Class->caught($class); | ||||
78 | } | ||||
79 | 1 | 18µs | if $Exception::Class::VERSION lt '1.22'; | ||
80 | 1 | 2.76ms | 1 | 17µs | } # spent 17µs making 1 call to Iterator::BEGIN@69 |
81 | |||||
82 | # Croak-like location of error | ||||
83 | sub Iterator::X::location | ||||
84 | { | ||||
85 | my ($pkg,$file,$line); | ||||
86 | my $caller_level = 0; | ||||
87 | while (1) | ||||
88 | { | ||||
89 | ($pkg,$file,$line) = caller($caller_level++); | ||||
90 | last if $pkg !~ /\A Iterator/x && $pkg !~ /\A Exception::Class/x | ||||
91 | } | ||||
92 | return "at $file line $line"; | ||||
93 | } | ||||
94 | |||||
95 | # Die-like location of error | ||||
96 | sub Iterator::X::Internal_Error::location | ||||
97 | { | ||||
98 | my $self = shift; | ||||
99 | return "at " . $self->file () . " line " . $self->line () | ||||
100 | } | ||||
101 | |||||
102 | # Override full_message, to report location of error in caller's code. | ||||
103 | sub Iterator::X::full_message | ||||
104 | { | ||||
105 | my $self = shift; | ||||
106 | |||||
107 | my $msg = $self->message; | ||||
108 | return $msg if substr($msg,-1,1) eq "\n"; | ||||
109 | |||||
110 | $msg =~ s/[ \t]+\z//; # remove any trailing spaces (is this necessary?) | ||||
111 | return $msg . q{ } . $self->location () . qq{\n}; | ||||
112 | } | ||||
113 | |||||
114 | |||||
115 | ## Constructor | ||||
116 | |||||
117 | # Method name: new | ||||
118 | # Synopsis: $iterator = Iterator->new( $code_ref ); | ||||
119 | # Description: Object constructor. | ||||
120 | # Created: 07/27/2005 by EJR | ||||
121 | # Parameters: $code_ref - the iterator sequence generation code. | ||||
122 | # Returns: New Iterator. | ||||
123 | # Exceptions: Iterator::X::Parameter_Error (via _initialize) | ||||
124 | sub new | ||||
125 | { | ||||
126 | my $class = shift; | ||||
127 | my $self = \do {my $anonymous}; | ||||
128 | bless $self, $class; | ||||
129 | $self->_initialize(@_); | ||||
130 | return $self; | ||||
131 | } | ||||
132 | |||||
133 | { # encapsulation enclosure | ||||
134 | |||||
135 | # Attributes: | ||||
136 | 4 | 6µs | my %code_for; # The sequence code (coderef) for each object. | ||
137 | my %is_exhausted; # Boolean: is this object exhausted? | ||||
138 | my %next_value_for; # One-item lookahead buffer for each object. | ||||
139 | # [if you update this list of attributes, be sure to edit DESTROY] | ||||
140 | |||||
141 | # Method name: _initialize | ||||
142 | # Synopsis: $iterator->_initialize( $code_ref ); | ||||
143 | # Description: Object initializer. | ||||
144 | # Created: 07/27/2005 by EJR | ||||
145 | # Parameters: $code_ref - the iterator sequence generation code. | ||||
146 | # Returns: Nothing. | ||||
147 | # Exceptions: Iterator::X::Parameter_Error | ||||
148 | # Iterator::X::User_Code_Error | ||||
149 | # Notes: For internal module use only. | ||||
150 | # Caches the first value of the iterator in %next_value_for. | ||||
151 | sub _initialize | ||||
152 | { | ||||
153 | my $self = shift; | ||||
154 | |||||
155 | Iterator::X::Parameter_Error->throw(q{Too few parameters to Iterator->new()}) | ||||
156 | if @_ < 1; | ||||
157 | Iterator::X::Parameter_Error->throw(q{Too many parameters to Iterator->new()}) | ||||
158 | if @_ > 1; | ||||
159 | my $code = shift; | ||||
160 | Iterator::X::Parameter_Error->throw (q{Parameter to Iterator->new() must be code reference}) | ||||
161 | if ref $code ne 'CODE'; | ||||
162 | |||||
163 | $code_for {$self} = $code; | ||||
164 | |||||
165 | # Get the next (first) value for this iterator | ||||
166 | eval | ||||
167 | { | ||||
168 | $next_value_for{$self} = $code-> (); | ||||
169 | }; | ||||
170 | |||||
171 | my $ex; | ||||
172 | if ($ex = Iterator::X::Am_Now_Exhausted->caught ()) | ||||
173 | { | ||||
174 | # Starting off exhausted is okay | ||||
175 | $is_exhausted{$self} = 1; | ||||
176 | } | ||||
177 | elsif ($@) | ||||
178 | { | ||||
179 | Iterator::X::User_Code_Error->throw (message => "$@", | ||||
180 | eval_error => $@); | ||||
181 | } | ||||
182 | |||||
183 | return; | ||||
184 | } | ||||
185 | |||||
186 | # Method name: DESTROY | ||||
187 | # Synopsis: (none) | ||||
188 | # Description: Object destructor. | ||||
189 | # Created: 07/27/2005 by EJR | ||||
190 | # Parameters: None. | ||||
191 | # Returns: Nothing. | ||||
192 | # Exceptions: None. | ||||
193 | # Notes: Invoked automatically by perl. | ||||
194 | # Releases the hash entries used by the object. | ||||
195 | # Module would leak memory otherwise. | ||||
196 | sub DESTROY | ||||
197 | { | ||||
198 | my $self = shift; | ||||
199 | delete $code_for{$self}; | ||||
200 | delete $is_exhausted{$self}; | ||||
201 | delete $next_value_for{$self}; | ||||
202 | } | ||||
203 | |||||
204 | # Method name: value | ||||
205 | # Synopsis: $next_value = $iterator->value(); | ||||
206 | # Description: Returns each value of the sequence in turn. | ||||
207 | # Created: 07/27/2005 by EJR | ||||
208 | # Parameters: None. | ||||
209 | # Returns: Next value, as generated by caller's code ref. | ||||
210 | # Exceptions: Iterator::X::Exhausted | ||||
211 | # Notes: Keeps one forward-looking value for the iterator in | ||||
212 | # %next_value_for. This is so we have something to | ||||
213 | # return when user's code throws Am_Now_Exhausted. | ||||
214 | sub value | ||||
215 | { | ||||
216 | my $self = shift; | ||||
217 | |||||
218 | Iterator::X::Exhausted->throw(q{Iterator is exhausted}) | ||||
219 | if $is_exhausted{$self}; | ||||
220 | |||||
221 | # The value that we'll be returning this time. | ||||
222 | my $this_value = $next_value_for{$self}; | ||||
223 | |||||
224 | # Compute the value that we'll return next time | ||||
225 | eval | ||||
226 | { | ||||
227 | $next_value_for{$self} = $code_for{$self}->(@_); | ||||
228 | }; | ||||
229 | if (my $ex = Iterator::X::Am_Now_Exhausted->caught ()) | ||||
230 | { | ||||
231 | # Aha, we're done; we'll have to stop next time. | ||||
232 | $is_exhausted{$self} = 1; | ||||
233 | } | ||||
234 | elsif ($@) | ||||
235 | { | ||||
236 | Iterator::X::User_Code_Error->throw (message => "$@", | ||||
237 | eval_error => $@); | ||||
238 | } | ||||
239 | |||||
240 | return $this_value; | ||||
241 | } | ||||
242 | |||||
243 | # Method name: is_exhausted | ||||
244 | # Synopsis: $boolean = $iterator->is_exhausted(); | ||||
245 | # Description: Flag indicating that the iterator is exhausted. | ||||
246 | # Created: 07/27/2005 by EJR | ||||
247 | # Parameters: None. | ||||
248 | # Returns: Current value of %is_exhausted for this object. | ||||
249 | # Exceptions: None. | ||||
250 | sub is_exhausted | ||||
251 | { | ||||
252 | my $self = shift; | ||||
253 | |||||
254 | return $is_exhausted{$self}; | ||||
255 | } | ||||
256 | |||||
257 | # Method name: isnt_exhausted | ||||
258 | # Synopsis: $boolean = $iterator->isnt_exhausted(); | ||||
259 | # Description: Flag indicating that the iterator is NOT exhausted. | ||||
260 | # Created: 07/27/2005 by EJR | ||||
261 | # Parameters: None. | ||||
262 | # Returns: Logical NOT of %is_exhausted for this object. | ||||
263 | # Exceptions: None. | ||||
264 | sub isnt_exhausted | ||||
265 | { | ||||
266 | my $self = shift; | ||||
267 | |||||
268 | return ! $is_exhausted{$self}; | ||||
269 | } | ||||
270 | |||||
271 | } # end of encapsulation enclosure | ||||
272 | |||||
273 | |||||
274 | # Function name: is_done | ||||
275 | # Synopsis: Iterator::is_done (); | ||||
276 | # Description: Convenience function. Throws an Am_Now_Exhausted exception. | ||||
277 | # Created: 08/02/2005 by EJR, per Will Coleda's suggestion. | ||||
278 | # Parameters: None. | ||||
279 | # Returns: Doesn't return. | ||||
280 | # Exceptions: Iterator::X::Am_Now_Exhausted | ||||
281 | sub is_done | ||||
282 | { | ||||
283 | Iterator::X::Am_Now_Exhausted->throw() | ||||
284 | } | ||||
285 | |||||
286 | |||||
287 | 1 | 18µs | 1; | ||
288 | __END__ |