line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::Std::Fast::Storable; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
28807
|
use version; $VERSION = qv('0.0.8'); |
|
2
|
|
|
|
|
2583
|
|
|
2
|
|
|
|
|
13
|
|
4
|
2
|
|
|
2
|
|
157
|
use strict; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
67
|
|
5
|
2
|
|
|
2
|
|
9
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
60
|
|
6
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
2
|
|
|
|
|
24
|
|
|
2
|
|
|
|
|
199
|
|
7
|
2
|
|
|
2
|
|
2575
|
use Storable; |
|
2
|
|
|
|
|
8829
|
|
|
2
|
|
|
|
|
185
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
BEGIN { |
10
|
2
|
|
|
2
|
|
1011
|
require Class::Std::Fast; |
11
|
|
|
|
|
|
|
} |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
my $attributes_of_ref = {}; |
14
|
|
|
|
|
|
|
my @exported_subs = qw( |
15
|
|
|
|
|
|
|
Class::Std::Fast::ident |
16
|
|
|
|
|
|
|
Class::Std::Fast::DESTROY |
17
|
|
|
|
|
|
|
Class::Std::Fast::MODIFY_CODE_ATTRIBUTES |
18
|
|
|
|
|
|
|
Class::Std::Fast::AUTOLOAD |
19
|
|
|
|
|
|
|
Class::Std::Fast::_DUMP |
20
|
|
|
|
|
|
|
STORABLE_freeze |
21
|
|
|
|
|
|
|
STORABLE_thaw |
22
|
|
|
|
|
|
|
MODIFY_HASH_ATTRIBUTES |
23
|
|
|
|
|
|
|
); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub import { |
26
|
5
|
|
|
5
|
|
1483
|
my $caller_package = caller; |
27
|
|
|
|
|
|
|
|
28
|
5
|
50
|
33
|
|
|
45
|
my %flags = (@_>=3) |
|
|
50
|
|
|
|
|
|
29
|
|
|
|
|
|
|
? @_[1..$#_] |
30
|
|
|
|
|
|
|
: (@_==2) && $_[1] >=2 |
31
|
|
|
|
|
|
|
? ( constructor => 'basic', cache => 0 ) |
32
|
|
|
|
|
|
|
: ( constructor => 'normal', cache => 0); |
33
|
5
|
50
|
|
|
|
19
|
$flags{cache} = 0 if not defined $flags{cache}; |
34
|
5
|
50
|
|
|
|
12
|
$flags{constructor} = 'normal' if not defined $flags{constructor}; |
35
|
|
|
|
|
|
|
|
36
|
5
|
|
|
|
|
26
|
Class::Std::Fast::_init_import( |
37
|
|
|
|
|
|
|
$caller_package, %flags |
38
|
|
|
|
|
|
|
); |
39
|
|
|
|
|
|
|
|
40
|
2
|
|
|
2
|
|
14
|
no strict qw(refs); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
729
|
|
41
|
5
|
|
|
|
|
13
|
for my $name ( @exported_subs ) { |
42
|
40
|
|
|
|
|
230
|
my ($sub_name) = $name =~ m{(\w+)\z}xms; |
43
|
40
|
|
|
|
|
52
|
*{ $caller_package . '::' . $sub_name } = \&{$name}; |
|
40
|
|
|
|
|
428
|
|
|
40
|
|
|
|
|
96
|
|
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
sub MODIFY_HASH_ATTRIBUTES { |
48
|
7
|
|
|
7
|
|
104
|
my $caller_package = $_[0]; |
49
|
7
|
|
|
|
|
17
|
my @unhandled = Class::Std::Fast::MODIFY_HASH_ATTRIBUTES(@_); |
50
|
7
|
|
|
|
|
9
|
my $i = 0; |
51
|
12
|
100
|
|
|
|
56
|
$attributes_of_ref->{$caller_package} = { |
52
|
|
|
|
|
|
|
map { |
53
|
7
|
50
|
|
|
|
18
|
$_->{name} eq '????' ? '????_' . $i++ : $_->{name} |
54
|
|
|
|
|
|
|
=> $_->{ref}; |
55
|
7
|
|
|
|
|
9
|
} @{Class::Std::Fast::_get_internal_attributes($caller_package) || []} |
56
|
|
|
|
|
|
|
}; |
57
|
7
|
|
|
|
|
23
|
return @unhandled; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# It's a constant - so there's no use creating it in each freeze again |
61
|
|
|
|
|
|
|
my $FROZEN_ANON_SCALAR = Storable::freeze(\(my $anon_scalar)); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub STORABLE_freeze { |
64
|
|
|
|
|
|
|
# TODO do we really need to unpack @_? We're getting called for |
65
|
|
|
|
|
|
|
# Zillions of objects... |
66
|
18
|
|
|
18
|
1
|
1603
|
my($self, $cloning) = @_; |
67
|
18
|
100
|
|
|
|
75
|
Class::Std::Fast::real_can($self, 'STORABLE_freeze_pre') |
68
|
|
|
|
|
|
|
&& $self->STORABLE_freeze_pre($cloning); |
69
|
|
|
|
|
|
|
|
70
|
18
|
|
|
|
|
325
|
my %frozen_attr; #to be constructed |
71
|
18
|
|
|
|
|
19
|
my $id = ${$self}; |
|
18
|
|
|
|
|
37
|
|
72
|
18
|
|
|
|
|
41
|
my @package_list = ref $self; |
73
|
18
|
|
|
|
|
37
|
my %package_seen = ( $package_list[0] => 1 ); # ignore diamond/looped base classes :-) |
74
|
|
|
|
|
|
|
|
75
|
2
|
|
|
2
|
|
35
|
no strict qw(refs); |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
1086
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
PACKAGE: |
78
|
18
|
|
|
|
|
45
|
while( my $package = shift @package_list) { |
79
|
|
|
|
|
|
|
#make sure we add any base classes to the list of |
80
|
|
|
|
|
|
|
#packages to examine for attributes. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# Original line: |
83
|
|
|
|
|
|
|
# push @package_list, grep { ! $package_seen{$_}++; } @{"${package}::ISA"}; |
84
|
|
|
|
|
|
|
# This one's faster... |
85
|
30
|
50
|
|
|
|
36
|
push @package_list, grep { ! exists $package_seen{$_} && do { $package_seen{$_} = undef; 1; } } @{"${package}::ISA"}; |
|
12
|
|
|
|
|
1233
|
|
|
12
|
|
|
|
|
24
|
|
|
12
|
|
|
|
|
27
|
|
|
30
|
|
|
|
|
88
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
#look for any attributes of this object for this package |
88
|
30
|
50
|
|
|
|
92
|
my $attr_ref = $attributes_of_ref->{$package} or next PACKAGE; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# TODO replace inner my variable by $_ - faster... |
91
|
30
|
|
|
|
|
87
|
ATTR: # examine attributes from known packages only |
92
|
30
|
|
|
|
|
30
|
for ( keys %{$attr_ref} ) { |
93
|
|
|
|
|
|
|
#nothing to do if attr not set for this object |
94
|
66
|
100
|
|
|
|
350
|
exists $attr_ref->{$_}{$id} |
95
|
|
|
|
|
|
|
and $frozen_attr{$package}{ $_ } = $attr_ref->{$_}{$id}; # save the attr by name into the package hash |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
} |
98
|
18
|
100
|
|
|
|
79
|
Class::Std::Fast::real_can($self, 'STORABLE_freeze_post') |
99
|
|
|
|
|
|
|
&& $self->STORABLE_freeze_post($cloning, \%frozen_attr); |
100
|
|
|
|
|
|
|
|
101
|
18
|
|
|
|
|
557
|
return ($FROZEN_ANON_SCALAR, \%frozen_attr); |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub STORABLE_thaw { |
105
|
|
|
|
|
|
|
# croak "must be called from Storable" unless caller eq 'Storable'; |
106
|
|
|
|
|
|
|
# unfortunately, Storable never appears on the call stack. |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# TODO do we really need to unpack @_? We're getting called for |
109
|
|
|
|
|
|
|
# zillions of objects... |
110
|
21
|
|
|
21
|
1
|
1347
|
my $self = shift; |
111
|
21
|
|
|
|
|
26
|
my $cloning = shift; |
112
|
21
|
|
|
|
|
25
|
my $frozen_attr_ref = $_[1]; # $_[0] is the frozen anon scalar. |
113
|
|
|
|
|
|
|
|
114
|
21
|
100
|
|
|
|
83
|
Class::Std::Fast::real_can($self, 'STORABLE_thaw_pre') |
115
|
|
|
|
|
|
|
&& $self->STORABLE_thaw_pre($cloning, $frozen_attr_ref); |
116
|
|
|
|
|
|
|
|
117
|
21
|
|
66
|
|
|
25
|
my $id = ${$self} ||= Class::Std::Fast::ID(); |
|
21
|
|
|
|
|
84
|
|
118
|
|
|
|
|
|
|
|
119
|
51
|
|
|
|
|
159
|
PACKAGE: |
120
|
21
|
|
|
|
|
30
|
while( my ($package, $pkg_attr_ref) = each %{$frozen_attr_ref} ) { |
121
|
|
|
|
|
|
|
# TODO This test is quite expensive. Is there a better one? |
122
|
33
|
100
|
|
|
|
296
|
$self->isa($package) |
123
|
|
|
|
|
|
|
or croak "unknown base class '$package' seen while thawing " |
124
|
|
|
|
|
|
|
. ref $self; |
125
|
32
|
|
|
|
|
82
|
ATTR: |
126
|
32
|
|
|
|
|
40
|
for ( keys %{$attributes_of_ref->{$package}} ) { |
127
|
|
|
|
|
|
|
# for known attrs... |
128
|
|
|
|
|
|
|
# nothing to do if frozen attr doesn't exist |
129
|
70
|
100
|
|
|
|
180
|
exists $pkg_attr_ref->{$_} or next ATTR; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# block attempts to meddle with existing objects |
132
|
60
|
100
|
|
|
|
316
|
exists $attributes_of_ref->{$package}->{$_}->{$id} |
133
|
|
|
|
|
|
|
and croak "trying to modify existing attributes for $package"; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# ok, set the attribute |
136
|
59
|
|
|
|
|
175
|
$attributes_of_ref->{$package}->{$_}->{$id} |
137
|
|
|
|
|
|
|
= delete $pkg_attr_ref->{$_}; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
# this is probably serious enough to throw an exception. |
140
|
|
|
|
|
|
|
# however, TODO: it would be nice if the class could somehow |
141
|
|
|
|
|
|
|
# indicate to ignore this problem. |
142
|
31
|
100
|
|
|
|
193
|
%$pkg_attr_ref |
143
|
|
|
|
|
|
|
and croak "unknown attribute(s) seen while thawing class $package:" |
144
|
|
|
|
|
|
|
. join q{, }, keys %$pkg_attr_ref; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
18
|
100
|
|
|
|
198
|
Class::Std::Fast::real_can($self, 'STORABLE_thaw_post') |
148
|
|
|
|
|
|
|
&& $self->STORABLE_thaw_post($cloning); |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
1; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
__END__ |