line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
827
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
2
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
52
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Class::ReturnValue; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Class::ReturnValue - A return-value object that lets you treat it |
10
|
|
|
|
|
|
|
as as a boolean, array or object |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 DESCRIPTION |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Class::ReturnValue is a "clever" return value object that can allow |
15
|
|
|
|
|
|
|
code calling your routine to expect: |
16
|
|
|
|
|
|
|
a boolean value (did it fail) |
17
|
|
|
|
|
|
|
or a list (what are the return values) |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 EXAMPLE |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub demo { |
22
|
|
|
|
|
|
|
my $value = shift; |
23
|
|
|
|
|
|
|
my $ret = Class::ReturnValue->new(); |
24
|
|
|
|
|
|
|
$ret->as_array('0', 'No results found'); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
unless($value) { |
27
|
|
|
|
|
|
|
$ret->as_error(errno => '1', |
28
|
|
|
|
|
|
|
message => "You didn't supply a parameter.", |
29
|
|
|
|
|
|
|
do_backtrace => 1); |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
return($ret->return_value); |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
if (demo('foo')){ |
36
|
|
|
|
|
|
|
print "the routine succeeded with one parameter"; |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
if (demo()) { |
39
|
|
|
|
|
|
|
print "The routine succeeded with 0 paramters. shouldn't happen"; |
40
|
|
|
|
|
|
|
} else { |
41
|
|
|
|
|
|
|
print "The routine failed with 0 parameters (as it should)."; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my $return = demo(); |
46
|
|
|
|
|
|
|
if ($return) { |
47
|
|
|
|
|
|
|
print "The routine succeeded with 0 paramters. shouldn't happen"; |
48
|
|
|
|
|
|
|
} else { |
49
|
|
|
|
|
|
|
print "The routine failed with 0 parameters (as it should). ". |
50
|
|
|
|
|
|
|
"Stack trace:\n". |
51
|
|
|
|
|
|
|
$return->backtrace; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my @return3 = demo('foo'); |
55
|
|
|
|
|
|
|
print "The routine got ".join(',',@return3). |
56
|
|
|
|
|
|
|
"when asking for demo's results as an array"; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
my $return2 = demo('foo'); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
unless ($return2) { |
62
|
|
|
|
|
|
|
print "The routine failed with a parameter. shouldn't happen.". |
63
|
|
|
|
|
|
|
"Stack trace:\n". |
64
|
|
|
|
|
|
|
$return2->backtrace; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my @return2_array = @{$return2}; # TODO: does this work |
68
|
|
|
|
|
|
|
my @return2_array2 = $return2->as_array; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=cut |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
1
|
|
|
1
|
|
20
|
use Exporter; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
51
|
|
75
|
|
|
|
|
|
|
|
76
|
1
|
|
|
1
|
|
5
|
use vars qw/$VERSION @EXPORT @ISA/; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
92
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
@ISA = qw/Exporter/; |
79
|
|
|
|
|
|
|
@EXPORT = qw /&return_value/; |
80
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
61
|
|
81
|
1
|
|
|
1
|
|
949
|
use Devel::StackTrace; |
|
1
|
|
|
|
|
4449
|
|
|
1
|
|
|
|
|
29
|
|
82
|
1
|
|
|
1
|
|
2211
|
use Data::Dumper; |
|
1
|
|
|
|
|
7191
|
|
|
1
|
|
|
|
|
107
|
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$VERSION = '0.55'; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
|
88
|
1
|
|
|
1
|
|
10
|
use overload 'bool' => \&error_condition; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
13
|
|
89
|
1
|
|
|
1
|
|
63
|
use overload '""' => \&error_condition; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
90
|
1
|
|
|
1
|
|
47
|
use overload 'eq' => \&my_eq; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
91
|
1
|
|
|
1
|
|
47
|
use overload '@{}' => \&as_array; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
92
|
1
|
|
|
1
|
|
47
|
use overload 'fallback' => \&as_array; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
4
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head1 METHODS |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item new |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Instantiate a new Class::ReturnValue object |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=cut |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub new { |
104
|
11
|
|
|
11
|
1
|
4655
|
my $self = {}; |
105
|
11
|
|
|
|
|
15
|
bless($self); |
106
|
11
|
|
|
|
|
30
|
return($self); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub my_eq { |
110
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
111
|
0
|
0
|
|
|
|
0
|
if (wantarray()) { |
112
|
0
|
|
|
|
|
0
|
return($self->as_array); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
else { |
115
|
0
|
|
|
|
|
0
|
return($self); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=item as_array |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Return the 'as_array' attribute of this object as an array. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=cut |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=item as_array [ARRAY] |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
If $self is called in an array context, returns the array specified in ARRAY |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=cut |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub as_array { |
133
|
|
|
|
|
|
|
|
134
|
10
|
|
|
10
|
1
|
30
|
my $self = shift; |
135
|
10
|
100
|
|
|
|
27
|
if (@_) { |
136
|
6
|
|
|
|
|
764
|
@{$self->{'as_array'}} = (@_); |
|
6
|
|
|
|
|
89
|
|
137
|
|
|
|
|
|
|
} |
138
|
10
|
|
|
|
|
17
|
return(@{$self->{'as_array'}}); |
|
10
|
|
|
|
|
793
|
|
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item as_error HASH |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Turns this return-value object into an error return object. TAkes three parameters: |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
message |
147
|
|
|
|
|
|
|
do_backtrace |
148
|
|
|
|
|
|
|
errno |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
'message' is a human readable error message explaining what's going on |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
'do_backtrace' is a boolean. If it's true, a carp-style backtrace will be |
153
|
|
|
|
|
|
|
stored in $self->{'backtrace'}. It defaults to true |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
errno and message default to undef. errno _must_ be specified. |
156
|
|
|
|
|
|
|
It's a numeric error number. Any true integer value will cause the |
157
|
|
|
|
|
|
|
object to evaluate to false in a scalar context. At first, this may look a |
158
|
|
|
|
|
|
|
bit counterintuitive, but it means that you can have error codes and still |
159
|
|
|
|
|
|
|
allow simple use of your functions in a style like this: |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
if ($obj->do_something) { |
163
|
|
|
|
|
|
|
print "Yay! it worked"; |
164
|
|
|
|
|
|
|
} else { |
165
|
|
|
|
|
|
|
print "Sorry. there's been an error."; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
as well as more complex use like this: |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
my $retval = $obj->do_something; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
if ($retval) { |
174
|
|
|
|
|
|
|
print "Yay. we did something\n"; |
175
|
|
|
|
|
|
|
my ($foo, $bar, $baz) = @{$retval}; |
176
|
|
|
|
|
|
|
my $human_readable_return = $retval; |
177
|
|
|
|
|
|
|
} else { |
178
|
|
|
|
|
|
|
if ($retval->errno == 20) { |
179
|
|
|
|
|
|
|
die "Failed with error 20 (Not enough monkeys)."; |
180
|
|
|
|
|
|
|
} else { |
181
|
|
|
|
|
|
|
die $retval->backtrace; # Die and print out a backtrace |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub as_error { |
189
|
3
|
|
|
3
|
1
|
9
|
my $self = shift; |
190
|
3
|
|
|
|
|
26
|
my %args = ( errno => undef, |
191
|
|
|
|
|
|
|
message => undef, |
192
|
|
|
|
|
|
|
do_backtrace => 1, |
193
|
|
|
|
|
|
|
@_); |
194
|
|
|
|
|
|
|
|
195
|
3
|
50
|
|
|
|
14
|
unless($args{'errno'}) { |
196
|
0
|
|
|
|
|
0
|
carp "$self -> as_error called without an 'errno' parameter"; |
197
|
0
|
|
|
|
|
0
|
return (undef); |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
3
|
|
|
|
|
10
|
$self->{'errno'} = $args{'errno'}; |
201
|
3
|
|
|
|
|
185
|
$self->{'error_message'} = $args{'message'}; |
202
|
3
|
100
|
|
|
|
11
|
if ($args{'do_backtrace'}) { |
203
|
|
|
|
|
|
|
# Use carp's internal backtrace methods, rather than duplicating them ourselves |
204
|
2
|
|
|
|
|
16
|
my $trace = Devel::StackTrace->new(ignore_package => 'Class::ReturnValue'); |
205
|
|
|
|
|
|
|
|
206
|
2
|
|
|
|
|
215
|
$self->{'backtrace'} = $trace->as_string; # like carp |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
3
|
|
|
|
|
673
|
return(1); |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item errno |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
Returns the errno if there's been an error. Otherwise, return undef |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub errno { |
220
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
221
|
2
|
50
|
|
|
|
9
|
if ($self->{'errno'}) { |
222
|
2
|
|
|
|
|
10
|
return ($self->{'errno'}); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
else { |
225
|
0
|
|
|
|
|
0
|
return(undef); |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item error_message |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
If there's been an error return the error message. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=cut |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub error_message { |
237
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
238
|
1
|
50
|
|
|
|
6
|
if ($self->{'error_message'}) { |
239
|
1
|
|
|
|
|
7
|
return($self->{'error_message'}); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
else { |
242
|
0
|
|
|
|
|
0
|
return(undef); |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item backtrace |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
If there's been an error and we asked for a backtrace, return the backtrace. |
250
|
|
|
|
|
|
|
Otherwise, return undef. |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub backtrace { |
255
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
256
|
2
|
100
|
|
|
|
14
|
if ($self->{'backtrace'}) { |
257
|
1
|
|
|
|
|
12
|
return($self->{'backtrace'}); |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
else { |
260
|
1
|
|
|
|
|
4
|
return(undef); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=cut |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=item error_condition |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
If there's been an error, return undef. Otherwise return 1 |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub error_condition { |
273
|
9
|
|
|
9
|
1
|
106
|
my $self = shift; |
274
|
9
|
100
|
|
|
|
31
|
if ($self->{'errno'}) { |
|
|
50
|
|
|
|
|
|
275
|
2
|
|
|
|
|
7
|
return (undef); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
elsif (wantarray()) { |
278
|
0
|
|
|
|
|
0
|
return(@{$self->{'as_array'}}); |
|
0
|
|
|
|
|
0
|
|
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
else { |
281
|
7
|
|
|
|
|
20
|
return(1); |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub return_value { |
286
|
9
|
|
|
9
|
0
|
33
|
my $self = shift; |
287
|
9
|
100
|
|
|
|
20
|
if (wantarray) { |
288
|
3
|
|
|
|
|
7
|
return ($self->as_array); |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
else { |
291
|
6
|
|
|
|
|
27
|
return ($self); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head1 AUTHOR |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Jesse Vincent |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=head1 BUGS |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
This module has, as yet, not been used in production code. I thing |
303
|
|
|
|
|
|
|
it should work, but have never benchmarked it. I have not yet used |
304
|
|
|
|
|
|
|
it extensively, though I do plan to in the not-too-distant future. |
305
|
|
|
|
|
|
|
If you have questions or comments, please write me. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
If you need to report a bug, please send mail to |
308
|
|
|
|
|
|
|
or report your error on the web |
309
|
|
|
|
|
|
|
at http://rt.cpan.org/ |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head1 COPYRIGHT |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Copyright (c) 2002,2003,2005,2007 Jesse Vincent |
314
|
|
|
|
|
|
|
You may use, modify, fold, spindle or mutilate this module under |
315
|
|
|
|
|
|
|
the same terms as perl itself. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head1 SEE ALSO |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Class::ReturnValue isn't an exception handler. If it doesn't |
320
|
|
|
|
|
|
|
do what you want, you might want look at one of the exception handlers |
321
|
|
|
|
|
|
|
below: |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
Error, Exception, Exceptions, Exceptions::Class |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
You might also want to look at Contextual::Return, another implementation |
326
|
|
|
|
|
|
|
of the same concept as this module. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=cut |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
1; |