| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Dispatch::Fu; |
|
2
|
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
154514
|
use strict; |
|
|
6
|
|
|
|
|
13
|
|
|
|
6
|
|
|
|
|
253
|
|
|
4
|
6
|
|
|
6
|
|
90
|
use warnings; |
|
|
6
|
|
|
|
|
11
|
|
|
|
6
|
|
|
|
|
357
|
|
|
5
|
6
|
|
|
6
|
|
52
|
use Exporter qw/import/; |
|
|
6
|
|
|
|
|
36
|
|
|
|
6
|
|
|
|
|
262
|
|
|
6
|
6
|
|
|
6
|
|
30
|
use Carp qw/carp croak/; |
|
|
6
|
|
|
|
|
16
|
|
|
|
6
|
|
|
|
|
5237
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = q{1.06}; |
|
9
|
|
|
|
|
|
|
our @EXPORT = qw(dispatch on cases xdefault xshift_and_deref); |
|
10
|
|
|
|
|
|
|
our @EXPORT_OK = qw(dispatch on cases xdefault xshift_and_deref); |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my $DISPATCH_TABLE = {}; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# sub for introspection, returns the string names of each case |
|
15
|
|
|
|
|
|
|
# added using the C keyword |
|
16
|
|
|
|
|
|
|
sub cases() { |
|
17
|
201
|
|
|
201
|
1
|
2975
|
return sort keys %$DISPATCH_TABLE; |
|
18
|
|
|
|
|
|
|
} |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub _reset_default_handler() { |
|
21
|
|
|
|
|
|
|
$DISPATCH_TABLE = { |
|
22
|
|
|
|
|
|
|
default => sub { |
|
23
|
0
|
|
|
0
|
|
0
|
carp qq{Supported cases are:\n}; |
|
24
|
0
|
|
|
|
|
0
|
foreach my $case (cases) { |
|
25
|
0
|
|
|
|
|
0
|
print qq{\t$case\n}; |
|
26
|
|
|
|
|
|
|
}; |
|
27
|
|
|
|
|
|
|
}, |
|
28
|
114
|
|
|
114
|
|
1329
|
}; |
|
29
|
114
|
|
|
|
|
257
|
return; |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
_reset_default_handler; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub dispatch (&@) { |
|
35
|
110
|
|
|
110
|
1
|
278411
|
my $code_ref = shift; # catch sub ref that was coerced from the 'dispatch' BLOCK |
|
36
|
110
|
|
|
|
|
176
|
my $match_ref = shift; # catch the input reference passed after the 'dispatch' BLOCK |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# build up dispatch table for each k/v pair preceded by 'on' |
|
39
|
110
|
|
|
|
|
407
|
while ( my $key = shift @_ ) { |
|
40
|
654
|
|
|
|
|
961
|
my $HV = shift @_; |
|
41
|
654
|
|
|
|
|
1053
|
$DISPATCH_TABLE->{$key} = _to_sub($HV); |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
110
|
50
|
|
|
|
295
|
croak qq{Dispatch::Fu [warning]: no cases defined. Make sure no semicolons are in places that need commas!} if not %$DISPATCH_TABLE; |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# call $code_ref that needs to return a valid bucket name |
|
47
|
110
|
|
|
|
|
365
|
my $key = $code_ref->($match_ref); |
|
48
|
|
|
|
|
|
|
|
|
49
|
110
|
100
|
66
|
|
|
92495
|
croak qq{Computed static bucket "$key" not found\n} if not $DISPATCH_TABLE->{$key} or 'CODE' ne ref $DISPATCH_TABLE->{$key}; |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# call subroutine ref defined as the v in the k/v $DISPATCH_TABLE->{$key} slot |
|
52
|
108
|
|
|
|
|
237
|
my $sub_to_call = $DISPATCH_TABLE->{$key}; |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# reset table, happens after call to CODE ref so that C is available inside |
|
55
|
|
|
|
|
|
|
# of the body of the sub |
|
56
|
108
|
|
|
|
|
346
|
_reset_default_handler; |
|
57
|
|
|
|
|
|
|
|
|
58
|
108
|
|
|
|
|
346
|
return $sub_to_call->($match_ref); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# on accumulater, wants h => v pair, where h is a static bucket string and v is a sub ref |
|
62
|
|
|
|
|
|
|
sub on (@) { |
|
63
|
655
|
|
|
655
|
1
|
1762793
|
my ($key, $val) = @_; |
|
64
|
|
|
|
|
|
|
# detect situations like when instead of a comma, "on" sits behind a semicolon |
|
65
|
655
|
100
|
|
|
|
1400
|
carp qq{Dispatch::Fu [warning]: "on $key" used in void context is always a mistake. The "on" method always follows a comma!} unless wantarray; |
|
66
|
655
|
|
|
|
|
2203
|
return @_; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# if $case is in cases(), return $case; otherwise return $default |
|
70
|
|
|
|
|
|
|
# Note: $default defaults to q{default}; i.e., if the name of the |
|
71
|
|
|
|
|
|
|
# default case is not specified, the string 'default' is returned |
|
72
|
|
|
|
|
|
|
sub xdefault($;$) { |
|
73
|
5
|
|
|
5
|
1
|
30
|
my ($case, $default) = @_; |
|
74
|
5
|
100
|
100
|
|
|
17
|
if ($case and grep { /$case/ } (cases)){ |
|
|
22
|
|
|
|
|
119
|
|
|
75
|
1
|
|
|
|
|
6
|
return $case; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
4
|
100
|
|
|
|
19
|
return (defined $default) ? $default : q{default}; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# for multi-assignment syntax, given the first reference in the parameter list; e.g., "my ($x, $y, $z) = ..." |
|
81
|
|
|
|
|
|
|
sub xshift_and_deref(@) { |
|
82
|
2
|
100
|
|
2
|
1
|
15
|
return %{ +shift } if ref $_[0] eq q{HASH}; |
|
|
1
|
|
|
|
|
7
|
|
|
83
|
1
|
50
|
|
|
|
4
|
return @{ +shift } if ref $_[0] eq q{ARRAY}; |
|
|
1
|
|
|
|
|
5
|
|
|
84
|
0
|
0
|
|
|
|
0
|
return shift @_ if ref $_[0] eq q{SCALAR}; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# utility sub to force a BLOCK into a sub reference |
|
88
|
|
|
|
|
|
|
sub _to_sub (&) { |
|
89
|
654
|
|
|
654
|
|
2260
|
shift; |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
1; |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
__END__ |