line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Test2::Util::Stash; |
2
|
157
|
|
|
157
|
|
998
|
use strict; |
|
157
|
|
|
|
|
321
|
|
|
157
|
|
|
|
|
4245
|
|
3
|
157
|
|
|
157
|
|
762
|
use warnings; |
|
157
|
|
|
|
|
383
|
|
|
157
|
|
|
|
|
6169
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.000153'; |
6
|
|
|
|
|
|
|
|
7
|
157
|
|
|
157
|
|
853
|
use Carp qw/croak/; |
|
157
|
|
|
|
|
293
|
|
|
157
|
|
|
|
|
6630
|
|
8
|
157
|
|
|
157
|
|
1004
|
use B; |
|
157
|
|
|
|
|
326
|
|
|
157
|
|
|
|
|
10250
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our @EXPORT_OK = qw{ |
11
|
|
|
|
|
|
|
get_stash |
12
|
|
|
|
|
|
|
get_glob |
13
|
|
|
|
|
|
|
get_symbol |
14
|
|
|
|
|
|
|
parse_symbol |
15
|
|
|
|
|
|
|
purge_symbol |
16
|
|
|
|
|
|
|
slot_to_sig sig_to_slot |
17
|
|
|
|
|
|
|
}; |
18
|
157
|
|
|
157
|
|
1129
|
use base 'Exporter'; |
|
157
|
|
|
|
|
398
|
|
|
157
|
|
|
|
|
37281
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
my %SIGMAP = ( |
21
|
|
|
|
|
|
|
'&' => 'CODE', |
22
|
|
|
|
|
|
|
'$' => 'SCALAR', |
23
|
|
|
|
|
|
|
'%' => 'HASH', |
24
|
|
|
|
|
|
|
'@' => 'ARRAY', |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my %SLOTMAP = reverse %SIGMAP; |
28
|
|
|
|
|
|
|
|
29
|
19
|
50
|
|
19
|
1
|
93
|
sub slot_to_sig { $SLOTMAP{$_[0]} || croak "unsupported slot: '$_[0]'" } |
30
|
4
|
50
|
|
4
|
1
|
58
|
sub sig_to_slot { $SIGMAP{$_[0]} || croak "unsupported sigil: $_[0]" } |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub get_stash { |
33
|
1054
|
|
33
|
1054
|
1
|
2016
|
my $package = shift || caller; |
34
|
157
|
|
|
157
|
|
1155
|
no strict 'refs'; |
|
157
|
|
|
|
|
423
|
|
|
157
|
|
|
|
|
14778
|
|
35
|
1054
|
|
|
|
|
1315
|
return \%{"${package}\::"}; |
|
1054
|
|
|
|
|
2971
|
|
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub get_glob { |
39
|
1059
|
|
|
1059
|
1
|
2080
|
my $sym = _parse_symbol(scalar(caller), @_); |
40
|
157
|
|
|
157
|
|
1072
|
no strict 'refs'; |
|
157
|
|
|
|
|
371
|
|
|
157
|
|
|
|
|
6135
|
|
41
|
157
|
|
|
157
|
|
962
|
no warnings 'once'; |
|
157
|
|
|
|
|
373
|
|
|
157
|
|
|
|
|
131137
|
|
42
|
1059
|
|
|
|
|
1492
|
return \*{"$sym->{package}\::$sym->{name}"}; |
|
1059
|
|
|
|
|
3027
|
|
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
58
|
|
|
58
|
1
|
205
|
sub parse_symbol { _parse_symbol(scalar(caller), @_) } |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub _parse_symbol { |
48
|
2149
|
|
|
2149
|
|
3651
|
my ($caller, $symbol, $package) = @_; |
49
|
|
|
|
|
|
|
|
50
|
2149
|
100
|
|
|
|
3966
|
if (ref($symbol)) { |
51
|
1499
|
|
|
|
|
2145
|
my $pkg = $symbol->{package}; |
52
|
|
|
|
|
|
|
|
53
|
1499
|
100
|
100
|
|
|
3932
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
54
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
55
|
|
|
|
|
|
|
|
56
|
1498
|
|
66
|
|
|
3255
|
$symbol->{package} ||= $caller; |
57
|
|
|
|
|
|
|
|
58
|
1498
|
|
|
|
|
2751
|
return $symbol; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
650
|
50
|
|
|
|
1244
|
utf8::downgrade($symbol) if $] == 5.010000; # prevent crash on 5.10.0 |
62
|
650
|
50
|
|
|
|
4112
|
my ($sig, $pkg, $name) = ($symbol =~ m/^(\W?)(.*::)?([^:]+)$/) |
63
|
|
|
|
|
|
|
or croak "Invalid symbol: '$symbol'"; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Normalize package, '::' becomes 'main', 'Foo::' becomes 'Foo' |
66
|
650
|
100
|
|
|
|
1496
|
$pkg = $pkg |
|
|
100
|
|
|
|
|
|
67
|
|
|
|
|
|
|
? $pkg eq '::' |
68
|
|
|
|
|
|
|
? 'main' |
69
|
|
|
|
|
|
|
: substr($pkg, 0, -2) |
70
|
|
|
|
|
|
|
: undef; |
71
|
|
|
|
|
|
|
|
72
|
650
|
100
|
100
|
|
|
1567
|
croak "Symbol package ($pkg) and package argument ($package) do not match" |
|
|
|
66
|
|
|
|
|
73
|
|
|
|
|
|
|
if $pkg && $package && $pkg ne $package; |
74
|
|
|
|
|
|
|
|
75
|
649
|
|
100
|
|
|
1846
|
$sig ||= '&'; |
76
|
649
|
|
33
|
|
|
1676
|
my $type = $SIGMAP{$sig} || croak "unsupported sigil: '$sig'"; |
77
|
|
|
|
|
|
|
|
78
|
649
|
|
66
|
|
|
1511
|
my $real_package = $package || $pkg || $caller; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
return { |
81
|
649
|
|
|
|
|
3289
|
name => $name, |
82
|
|
|
|
|
|
|
sigil => $sig, |
83
|
|
|
|
|
|
|
type => $type, |
84
|
|
|
|
|
|
|
symbol => "${sig}${real_package}::${name}", |
85
|
|
|
|
|
|
|
package => $real_package, |
86
|
|
|
|
|
|
|
}; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub get_symbol { |
90
|
944
|
|
|
944
|
1
|
2150
|
my $sym = _parse_symbol(scalar(caller), @_); |
91
|
|
|
|
|
|
|
|
92
|
944
|
|
|
|
|
1656
|
my $name = $sym->{name}; |
93
|
944
|
|
|
|
|
1247
|
my $type = $sym->{type}; |
94
|
944
|
|
|
|
|
1278
|
my $package = $sym->{package}; |
95
|
944
|
|
|
|
|
1343
|
my $symbol = $sym->{symbol}; |
96
|
|
|
|
|
|
|
|
97
|
944
|
|
|
|
|
1590
|
my $stash = get_stash($package); |
98
|
944
|
100
|
|
|
|
2215
|
return undef unless exists $stash->{$name}; |
99
|
|
|
|
|
|
|
|
100
|
882
|
|
|
|
|
1396
|
my $glob = get_glob($sym); |
101
|
882
|
100
|
100
|
|
|
1938
|
return *{$glob}{$type} if $type ne 'SCALAR' && defined(*{$glob}{$type}); |
|
398
|
|
|
|
|
1695
|
|
|
787
|
|
|
|
|
2177
|
|
102
|
|
|
|
|
|
|
|
103
|
484
|
50
|
|
|
|
850
|
if ($] < 5.010) { |
104
|
0
|
0
|
|
|
|
0
|
return undef unless defined(*{$glob}{$type}); |
|
0
|
|
|
|
|
0
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
{ |
107
|
0
|
|
|
|
|
0
|
local ($@, $!); |
|
0
|
|
|
|
|
0
|
|
108
|
0
|
|
|
0
|
|
0
|
local $SIG{__WARN__} = sub { 1 }; |
|
0
|
|
|
|
|
0
|
|
109
|
0
|
0
|
|
|
|
0
|
return *{$glob}{$type} if eval "package $package; my \$y = $symbol; 1"; |
|
0
|
|
|
|
|
0
|
|
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
0
|
0
|
|
|
|
0
|
return undef unless defined *{$glob}{$type}; |
|
0
|
|
|
|
|
0
|
|
113
|
0
|
0
|
|
|
|
0
|
return *{$glob}{$type} if defined ${*{$glob}{$type}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
114
|
0
|
|
|
|
|
0
|
return undef; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
484
|
|
|
|
|
1484
|
my $sv = B::svref_2object($glob)->SV; |
118
|
484
|
100
|
|
|
|
1643
|
return *{$glob}{$type} if $sv->isa('B::SV'); |
|
104
|
|
|
|
|
282
|
|
119
|
380
|
50
|
|
|
|
800
|
return undef unless $sv->isa('B::SPECIAL'); |
120
|
380
|
50
|
|
|
|
729
|
return *{$glob}{$type} if $B::specialsv_name[$$sv] ne 'Nullsv'; |
|
0
|
|
|
|
|
0
|
|
121
|
380
|
|
|
|
|
746
|
return undef; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub purge_symbol { |
125
|
88
|
|
|
88
|
1
|
384
|
my $sym = _parse_symbol(scalar(caller), @_); |
126
|
|
|
|
|
|
|
|
127
|
88
|
|
|
|
|
149
|
local *GLOBCLONE = *{get_glob($sym)}; |
|
88
|
|
|
|
|
162
|
|
128
|
88
|
|
|
|
|
217
|
delete get_stash($sym->{package})->{$sym->{name}}; |
129
|
88
|
|
|
|
|
174
|
my $new_glob = get_glob($sym); |
130
|
|
|
|
|
|
|
|
131
|
88
|
|
|
|
|
223
|
for my $type (qw/CODE SCALAR HASH ARRAY FORMAT IO/) { |
132
|
528
|
100
|
|
|
|
980
|
next if $type eq $sym->{type}; |
133
|
440
|
|
|
|
|
1190
|
my $ref = get_symbol({type => $type, name => 'GLOBCLONE', sigil => $SLOTMAP{$type}}, __PACKAGE__); |
134
|
440
|
100
|
|
|
|
1124
|
next unless $ref; |
135
|
21
|
|
|
|
|
44
|
*$new_glob = $ref; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
88
|
|
|
|
|
616
|
return *GLOBCLONE{$sym->{type}}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
1; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
__END__ |