line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Hash::AutoHash; |
2
|
|
|
|
|
|
|
our $VERSION='1.17'; |
3
|
|
|
|
|
|
|
$VERSION=eval $VERSION; # I think this is the accepted idiom.. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
################################################################################# |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# Author: Nat Goodman |
8
|
|
|
|
|
|
|
# Created: 09-02-24 |
9
|
|
|
|
|
|
|
# $Id: |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
# Wrapper that provides accessor and mutator methods for hashes (real or tied) |
12
|
|
|
|
|
|
|
# Hash can be externally supplied or this object itself |
13
|
|
|
|
|
|
|
# Tying of hash can be done by application or by this class |
14
|
|
|
|
|
|
|
# Can also wrap object tied to hash |
15
|
|
|
|
|
|
|
# (actually, any object with suitable FETCH and STORE methods) |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
################################################################################# |
18
|
|
|
|
|
|
|
|
19
|
30
|
|
|
30
|
|
1344361
|
use strict; |
|
30
|
|
|
|
|
77
|
|
|
30
|
|
|
|
|
1117
|
|
20
|
30
|
|
|
30
|
|
171
|
use Carp; |
|
30
|
|
|
|
|
64
|
|
|
30
|
|
|
|
|
1893
|
|
21
|
30
|
|
|
30
|
|
158
|
use vars qw($AUTOLOAD); |
|
30
|
|
|
|
|
64
|
|
|
30
|
|
|
|
|
20080
|
|
22
|
|
|
|
|
|
|
our @CONSTRUCTORS_EXPORT_OK= |
23
|
|
|
|
|
|
|
qw(autohash_new autohash_hash autohash_tie autohash_wrap autohash_wrapobj autohash_wraptie); |
24
|
|
|
|
|
|
|
our @SUBCLASS_EXPORT_OK= |
25
|
|
|
|
|
|
|
qw(autohash_clear autohash_delete autohash_each autohash_exists autohash_keys autohash_values |
26
|
|
|
|
|
|
|
autohash_get autohash_set autohash_count autohash_empty autohash_notempty |
27
|
|
|
|
|
|
|
autohash_alias autohash_tied |
28
|
|
|
|
|
|
|
autohash_destroy autohash_untie); |
29
|
|
|
|
|
|
|
our @EXPORT_OK=(@CONSTRUCTORS_EXPORT_OK,@SUBCLASS_EXPORT_OK); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# following are used by subclasses |
32
|
|
|
|
|
|
|
our @RENAME_EXPORT_OK=(); |
33
|
|
|
|
|
|
|
our %RENAME_EXPORT_OK=(); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# our @EXPORT_OK=qw(autohash_new autohash_tie |
36
|
|
|
|
|
|
|
# autohash_wraphash autohash_wraptie autohash_wrapobject |
37
|
|
|
|
|
|
|
# autohash2hash autohash2object |
38
|
|
|
|
|
|
|
# autohash_clear autohash_delete autohash_exists autohash_keys autohash_values |
39
|
|
|
|
|
|
|
# autohash_count autohash_empty autohash_notempty |
40
|
|
|
|
|
|
|
# autohash_destroy autohash_untie |
41
|
|
|
|
|
|
|
# autohash_get autohash_set); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub import { |
44
|
142
|
|
|
142
|
|
135824
|
my $class_or_self=shift; |
45
|
142
|
100
|
|
|
|
477
|
if (ref $class_or_self) { |
46
|
|
|
|
|
|
|
# called as object method. access hash slot via AUTOLOAD |
47
|
11
|
|
|
|
|
65
|
$AUTOLOAD='import'; |
48
|
11
|
|
|
|
|
33
|
return $class_or_self->AUTOLOAD(@_); |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
# called as class method. do regular 'import' |
51
|
131
|
|
|
|
|
285
|
my $caller=caller; |
52
|
131
|
|
|
|
|
330
|
my $helper_class=$class_or_self.'::helper'; |
53
|
131
|
|
|
|
|
564
|
$helper_class->_import($class_or_self,$caller,@_); |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
sub new { |
56
|
79
|
|
|
79
|
1
|
157680
|
my $class_or_self=shift; |
57
|
79
|
100
|
|
|
|
250
|
if (ref $class_or_self) { |
58
|
|
|
|
|
|
|
# called as object method. access hash slot via AUTOLOAD |
59
|
12
|
|
|
|
|
23
|
$AUTOLOAD='new'; |
60
|
12
|
|
|
|
|
35
|
return $class_or_self->AUTOLOAD(@_); |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
# called as class method. do regular 'new' via helper class |
63
|
67
|
|
|
|
|
149
|
my $helper_class=$class_or_self.'::helper'; |
64
|
67
|
|
|
|
|
310
|
$helper_class->_new($class_or_self,@_); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
# NG 12-09-02: no longer possible to use method notation for keys with same names as methods |
67
|
|
|
|
|
|
|
# inherited from UNIVERSAL. 'Cuz as of Perl 5.9.3, calling UNIVERSAL methods as |
68
|
|
|
|
|
|
|
# functions is deprecated and developers encouraged to use method form instead. |
69
|
|
|
|
|
|
|
# sub can { |
70
|
|
|
|
|
|
|
# my $class_or_self=shift; |
71
|
|
|
|
|
|
|
# if (ref $class_or_self) { |
72
|
|
|
|
|
|
|
# # called as object method. access hash slot via AUTOLOAD |
73
|
|
|
|
|
|
|
# $AUTOLOAD='can'; |
74
|
|
|
|
|
|
|
# return $class_or_self->AUTOLOAD(@_); |
75
|
|
|
|
|
|
|
# } |
76
|
|
|
|
|
|
|
# # called as class method. do regular 'can' via base class |
77
|
|
|
|
|
|
|
# return $class_or_self->SUPER::can(@_); |
78
|
|
|
|
|
|
|
# } |
79
|
|
|
|
|
|
|
# sub isa { |
80
|
|
|
|
|
|
|
# my $class_or_self=shift; |
81
|
|
|
|
|
|
|
# if (ref $class_or_self) { |
82
|
|
|
|
|
|
|
# # called as object method. access hash slot via AUTOLOAD |
83
|
|
|
|
|
|
|
# $AUTOLOAD='isa'; |
84
|
|
|
|
|
|
|
# return $class_or_self->AUTOLOAD(@_); |
85
|
|
|
|
|
|
|
# } |
86
|
|
|
|
|
|
|
# # called as function or class method. do regular 'isa' via base class |
87
|
|
|
|
|
|
|
# return $class_or_self->SUPER::isa(@_); |
88
|
|
|
|
|
|
|
# } |
89
|
|
|
|
|
|
|
# sub DOES { # in perl 5.10, UNIVERSAL provides this |
90
|
|
|
|
|
|
|
# my $class_or_self=shift; |
91
|
|
|
|
|
|
|
# if (ref $class_or_self) { |
92
|
|
|
|
|
|
|
# # called as object method. access hash slot via AUTOLOAD |
93
|
|
|
|
|
|
|
# $AUTOLOAD='DOES'; |
94
|
|
|
|
|
|
|
# return $class_or_self->AUTOLOAD(@_); |
95
|
|
|
|
|
|
|
# } |
96
|
|
|
|
|
|
|
# # called as function or class method. do regular 'DOES' via base class |
97
|
|
|
|
|
|
|
# # illegal and will die in perls < 5.10 |
98
|
|
|
|
|
|
|
# return $class_or_self->SUPER::DOES(@_); |
99
|
|
|
|
|
|
|
# } |
100
|
|
|
|
|
|
|
# sub VERSION { |
101
|
|
|
|
|
|
|
# my $class_or_self=shift; |
102
|
|
|
|
|
|
|
# if (ref $class_or_self) { |
103
|
|
|
|
|
|
|
# # called as object method. access hash slot via AUTOLOAD |
104
|
|
|
|
|
|
|
# $AUTOLOAD='VERSION'; |
105
|
|
|
|
|
|
|
# return $class_or_self->AUTOLOAD(@_); |
106
|
|
|
|
|
|
|
# } |
107
|
|
|
|
|
|
|
# # called as function or class method. do regular 'VERSION' via base class |
108
|
|
|
|
|
|
|
# return $class_or_self->SUPER::VERSION(@_); |
109
|
|
|
|
|
|
|
# } |
110
|
|
|
|
|
|
|
sub DESTROY { |
111
|
|
|
|
|
|
|
# CAUTION: do NOT shift - need $_[0] intact |
112
|
772
|
50
|
|
772
|
|
2742828
|
if (ref($_[0])) { |
113
|
|
|
|
|
|
|
# called as object method. inish up in helper class where namespace more complete |
114
|
772
|
|
|
|
|
2213
|
my $helper_class=ref($_[0]).'::helper'; |
115
|
772
|
|
|
|
|
1335
|
my $helper_function=__PACKAGE__.'::helper::_destroy'; |
116
|
772
|
|
|
|
|
4658
|
return $helper_class->$helper_function(@_); |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
# called as class method. pass to base class. not sure this ever happens... |
119
|
0
|
|
|
|
|
0
|
my $class_or_self=shift; |
120
|
0
|
|
|
|
|
0
|
return $class_or_self->SUPER::DESTROY(@_); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# my $self=$_[0]; # CAUTION: do NOT shift - need $_[0] intact |
124
|
|
|
|
|
|
|
# return unless ref $self; # shouldn't happen, but... |
125
|
|
|
|
|
|
|
# if (@_==1) { # called as destructor or accessor |
126
|
|
|
|
|
|
|
# # perlobj says that $_[0] is read-only when DESTROY called as destructor |
127
|
|
|
|
|
|
|
# local $@=undef; |
128
|
|
|
|
|
|
|
# eval { $_[0]=undef }; |
129
|
|
|
|
|
|
|
# return if $@; # eval failed, so it's destructor. |
130
|
|
|
|
|
|
|
# $_[0]=$self; # not destructor. restore $_[0] |
131
|
|
|
|
|
|
|
# } |
132
|
|
|
|
|
|
|
# # not destructor. access hash slot via AUTOLOAD |
133
|
|
|
|
|
|
|
# shift; # now shift $self out of @_ |
134
|
|
|
|
|
|
|
# $AUTOLOAD='DESTROY'; |
135
|
|
|
|
|
|
|
# $self->AUTOLOAD(@_) |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub AUTOLOAD { |
138
|
1785
|
|
|
1785
|
|
2645425
|
my $self=shift; |
139
|
1785
|
|
|
|
|
12016
|
$AUTOLOAD=~s/^.*:://; # strip class qualification |
140
|
|
|
|
|
|
|
# return if $AUTOLOAD eq 'DESTROY'; # the books say you should do this |
141
|
1785
|
|
|
|
|
2982
|
my $key=$AUTOLOAD; |
142
|
1785
|
100
|
|
|
|
4455
|
defined $key or $key='AUTOLOAD'; |
143
|
1785
|
|
|
|
|
2202
|
$AUTOLOAD=undef; # reset for next time |
144
|
|
|
|
|
|
|
# finish up in helper class where namespace more complete |
145
|
1785
|
|
|
|
|
2734
|
my $helper_function=__PACKAGE__.'::helper::_autoload'; |
146
|
1785
|
|
|
|
|
7077
|
$self->$helper_function($key,@_); |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
################################################################################# |
150
|
|
|
|
|
|
|
# helper package exists to avoid polluting Hash::AutoHash namespace with |
151
|
|
|
|
|
|
|
# subs that would mask accessor/mutator AUTOLOADs |
152
|
|
|
|
|
|
|
# functions herein (except _new, _autoload) are exportable by Hash::AutoHash |
153
|
|
|
|
|
|
|
################################################################################# |
154
|
|
|
|
|
|
|
package Hash::AutoHash::helper; |
155
|
|
|
|
|
|
|
our $VERSION=$Hash::AutoHash::VERSION; |
156
|
30
|
|
|
30
|
|
182
|
use strict; |
|
30
|
|
|
|
|
56
|
|
|
30
|
|
|
|
|
890
|
|
157
|
30
|
|
|
30
|
|
189
|
use Carp; |
|
30
|
|
|
|
|
69
|
|
|
30
|
|
|
|
|
1923
|
|
158
|
30
|
|
|
30
|
|
173
|
use Scalar::Util qw(blessed readonly reftype); |
|
30
|
|
|
|
|
64
|
|
|
30
|
|
|
|
|
1980
|
|
159
|
30
|
|
|
30
|
|
2858
|
use List::MoreUtils qw(uniq); |
|
30
|
|
|
|
|
3658
|
|
|
30
|
|
|
|
|
1426
|
|
160
|
30
|
|
|
30
|
|
25994
|
use Tie::ToObject; |
|
30
|
|
|
|
|
9741
|
|
|
30
|
|
|
|
|
977
|
|
161
|
30
|
|
|
30
|
|
202
|
use vars qw(%SELF2HASH %SELF2OBJECT %SELF2EACH %CLASS2ANCESTORS %EXPORT_OK); |
|
30
|
|
|
|
|
58
|
|
|
30
|
|
|
|
|
2945
|
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub _import { |
164
|
131
|
|
|
131
|
|
353
|
my($helper_class,$class,$caller,@want)=@_; |
165
|
131
|
|
|
|
|
375
|
$helper_class->EXPORT_OK; # initializes %EXPORT_OK if necessary |
166
|
30
|
|
|
30
|
|
383
|
no strict 'refs'; |
|
30
|
|
|
|
|
56
|
|
|
30
|
|
|
|
|
3703
|
|
167
|
131
|
|
|
|
|
166
|
my %caller2export=%{$class.'::EXPORT_OK'}; |
|
131
|
|
|
|
|
1619
|
|
168
|
|
|
|
|
|
|
# my @export_ok=keys %caller2export; |
169
|
131
|
|
|
|
|
73304
|
for my $want (@want) { |
170
|
231
|
100
|
|
|
|
2573
|
confess("\"$want\" not exported by $class module") unless exists $caller2export{$want}; |
171
|
224
|
100
|
|
|
|
980
|
confess("\"$want\" not defined by $class module") unless defined $caller2export{$want}; |
172
|
222
|
|
|
|
|
385
|
my $caller_sym=$caller.'::'.$want; |
173
|
222
|
|
|
|
|
314
|
my $export_sym=$caller2export{$want}; |
174
|
30
|
|
|
30
|
|
153
|
no strict 'refs'; |
|
30
|
|
|
|
|
48
|
|
|
30
|
|
|
|
|
11164
|
|
175
|
222
|
|
|
|
|
245
|
*{$caller_sym}=\&{$export_sym}; |
|
222
|
|
|
|
|
64064
|
|
|
222
|
|
|
|
|
615
|
|
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# front-end to autohash_new constructor function, which in turn is front-end |
180
|
|
|
|
|
|
|
# to other constructor functions. |
181
|
|
|
|
|
|
|
sub _new { |
182
|
57
|
|
|
57
|
|
166
|
my($helper_class,$class)=splice @_,0,2; |
183
|
57
|
|
|
|
|
157
|
my $self=autohash_new(@_); |
184
|
57
|
|
|
|
|
271
|
bless $self,$class; # re-bless in case called via subclass |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub _destroy { |
188
|
772
|
|
|
772
|
|
1234
|
my $helper_class=shift; |
189
|
|
|
|
|
|
|
# $_[0] is now original object. |
190
|
|
|
|
|
|
|
# CAUTION: do NOT shift further - need $_[0] intact |
191
|
|
|
|
|
|
|
# perlobj says that $_[0] is read-only when DESTROY called as destructor |
192
|
772
|
100
|
100
|
|
|
9744
|
return if @_==1 && readonly($_[0]); # destructor. nothing to do. |
193
|
|
|
|
|
|
|
# not destructor. access hash slot via AUTOLOAD |
194
|
11
|
|
|
|
|
17
|
my $self=shift; |
195
|
11
|
|
|
|
|
17
|
my $helper_function=__PACKAGE__.'::_autoload'; |
196
|
11
|
|
|
|
|
37
|
$self->$helper_function('DESTROY',@_) |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub _autoload { |
200
|
1796
|
|
|
1796
|
|
3973
|
my($self,$key)=splice(@_,0,2); |
201
|
1796
|
100
|
|
|
|
4559
|
if (my $object=tied %$self) { # tied hash, so invoke FETCH/STORE methods |
202
|
1184
|
100
|
|
|
|
5222
|
return @_==0? $object->FETCH($key): $object->STORE($key,@_); |
203
|
|
|
|
|
|
|
} else { # regular hash |
204
|
612
|
100
|
|
|
|
3160
|
return @_==0? ($self->{$key}): ($self->{$key}=$_[0]); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# use vars qw(%CLASS2ANCESTORS); |
209
|
|
|
|
|
|
|
sub _ancestors { |
210
|
42
|
|
|
42
|
|
88
|
my($class,$visited)=@_; |
211
|
42
|
|
|
|
|
84
|
my $ancestors=$CLASS2ANCESTORS{$class}; |
212
|
42
|
100
|
|
|
|
158
|
defined $visited or $visited={}; |
213
|
42
|
100
|
66
|
|
|
305
|
unless (defined($ancestors) || $visited->{$class}) { |
214
|
|
|
|
|
|
|
# first call, so compute it |
215
|
36
|
|
|
|
|
92
|
$ancestors=[$class]; # include self |
216
|
36
|
|
|
|
|
102
|
$visited->{$class}++; |
217
|
36
|
|
|
|
|
60
|
my @isa; |
218
|
30
|
|
|
30
|
|
176
|
{no strict "refs"; @isa = @{ $class . '::ISA' };} |
|
30
|
|
|
|
|
50
|
|
|
30
|
|
|
|
|
6429
|
|
|
36
|
|
|
|
|
59
|
|
|
36
|
|
|
|
|
55
|
|
|
36
|
|
|
|
|
589
|
|
219
|
36
|
|
|
|
|
105
|
for my $super (@isa) { |
220
|
6
|
|
|
|
|
26
|
push(@$ancestors,_ancestors($super,$visited)); |
221
|
|
|
|
|
|
|
} |
222
|
36
|
|
|
|
|
448
|
@$ancestors=uniq(@$ancestors); |
223
|
36
|
|
|
|
|
129
|
$CLASS2ANCESTORS{$class}=$ancestors |
224
|
|
|
|
|
|
|
} |
225
|
42
|
100
|
|
|
|
217
|
wantarray? @$ancestors: $ancestors; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub EXPORT_OK { |
229
|
149
|
|
|
149
|
|
3258
|
my $helper_class=shift; |
230
|
149
|
|
|
|
|
782
|
my($class)=$helper_class=~/^(.*)::helper$/; |
231
|
|
|
|
|
|
|
# for Hash::AutoHash::helper, @EXPORT_OK is given and function computes %EXPORT_OK |
232
|
149
|
100
|
|
|
|
443
|
if ($helper_class eq __PACKAGE__) { # NOTE: change this if you copy-and-paste into subclass |
233
|
30
|
|
|
30
|
|
210
|
no strict 'refs'; |
|
30
|
|
|
|
|
52
|
|
|
30
|
|
|
|
|
3971
|
|
234
|
113
|
|
|
|
|
154
|
my $export_ok_list=\@{$class.'::EXPORT_OK'}; |
|
113
|
|
|
|
|
370
|
|
235
|
113
|
|
|
|
|
242
|
my $export_ok_hash=\%{$class.'::EXPORT_OK'}; |
|
113
|
|
|
|
|
300
|
|
236
|
113
|
100
|
|
|
|
535
|
unless(%$export_ok_hash) { |
237
|
30
|
|
|
|
|
121
|
my $ancestors=$helper_class->_ancestors; |
238
|
30
|
|
|
|
|
71
|
for my $func (@$export_ok_list) { |
239
|
630
|
|
|
|
|
1104
|
$export_ok_hash->{$func}=_export_sym($func,$class,$ancestors); |
240
|
|
|
|
|
|
|
}} |
241
|
113
|
|
|
|
|
328
|
return @$export_ok_list; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
# for subclasses, @EXPORT_OK and %EXPORT_OK must both be computed |
244
|
36
|
|
|
|
|
52
|
my($export_ok_list,$export_ok_hash,@isa,@normal_export_ok,@rename_export_ok,%rename_export_ok); |
245
|
|
|
|
|
|
|
{ |
246
|
30
|
|
|
30
|
|
159
|
no strict 'refs'; |
|
30
|
|
|
|
|
51
|
|
|
30
|
|
|
|
|
17178
|
|
|
36
|
|
|
|
|
43
|
|
247
|
36
|
|
|
|
|
45
|
$export_ok_list=\@{$class.'::EXPORT_OK'}; |
|
36
|
|
|
|
|
110
|
|
248
|
|
|
|
|
|
|
# NG 12-11-29: 'defined @array' deprecated in 5.16 or so |
249
|
|
|
|
|
|
|
# return @$export_ok_list if defined @$export_ok_list; |
250
|
36
|
100
|
|
|
|
200
|
return @$export_ok_list if @$export_ok_list; |
251
|
6
|
|
|
|
|
8
|
$export_ok_hash=\%{$class.'::EXPORT_OK'}; |
|
6
|
|
|
|
|
22
|
|
252
|
6
|
|
|
|
|
12
|
@isa=@{$helper_class.'::ISA'}; |
|
6
|
|
|
|
|
30
|
|
253
|
6
|
|
|
|
|
11
|
@normal_export_ok=@{$class.'::NORMAL_EXPORT_OK'}; |
|
6
|
|
|
|
|
23
|
|
254
|
6
|
|
|
|
|
9
|
@rename_export_ok=@{$class.'::RENAME_EXPORT_OK'}; |
|
6
|
|
|
|
|
23
|
|
255
|
6
|
|
|
|
|
12
|
%rename_export_ok=%{$class.'::RENAME_EXPORT_OK'}; |
|
6
|
|
|
|
|
31
|
|
256
|
|
|
|
|
|
|
}; |
257
|
6
|
|
|
|
|
16
|
map {$_->EXPORT_OK} @isa; # mqke sure EXPORT_OK setup in ancestors |
|
6
|
|
|
|
|
49
|
|
258
|
6
|
|
|
|
|
53
|
my $ancestors=$helper_class->_ancestors; |
259
|
|
|
|
|
|
|
|
260
|
6
|
|
|
|
|
15
|
for my $func (@normal_export_ok) { |
261
|
14
|
|
|
|
|
39
|
$export_ok_hash->{$func}=_export_sym($func,$class,$ancestors); |
262
|
|
|
|
|
|
|
} |
263
|
6
|
|
|
|
|
38
|
while(my($caller_func,$our_func)=each %rename_export_ok) { |
264
|
6
|
|
|
|
|
15
|
$export_ok_hash->{$caller_func}=_export_sym($our_func,$class,$ancestors); |
265
|
|
|
|
|
|
|
} |
266
|
6
|
50
|
|
|
|
19
|
if (@rename_export_ok) { |
267
|
6
|
|
|
|
|
24
|
my($sub,@our_funcs)=@rename_export_ok; |
268
|
6
|
|
|
|
|
9
|
my %skip; |
269
|
6
|
100
|
|
|
|
31
|
unless (@our_funcs) { # rename list empty, so use default |
270
|
|
|
|
|
|
|
# start with all subclass-exportable functions from base classes |
271
|
2
|
50
|
|
|
|
24
|
@our_funcs=uniq |
272
|
2
|
|
|
|
|
5
|
map {UNIVERSAL::can($_,'SUBCLASS_EXPORT_OK')? $_->SUBCLASS_EXPORT_OK: ()} @isa; |
273
|
|
|
|
|
|
|
# %skip contains ones dealt with in @NORMAL_EXPORT_OK or %RENAME_EXPORT_OK |
274
|
2
|
|
|
|
|
13
|
@skip{@normal_export_ok}=(1) x @normal_export_ok; |
275
|
2
|
|
|
|
|
7
|
@skip{keys %rename_export_ok}=(1) x keys %rename_export_ok; |
276
|
|
|
|
|
|
|
# @skip{values %rename_export_ok}=(1) x values %rename_export_ok; |
277
|
|
|
|
|
|
|
} |
278
|
6
|
|
|
|
|
12
|
for my $our_func (@our_funcs) { |
279
|
40
|
|
|
|
|
55
|
local $_=$our_func; |
280
|
40
|
|
|
|
|
92
|
my $caller_func=&$sub(); # sub operates on $_ |
281
|
40
|
50
|
|
|
|
243
|
next if $skip{$caller_func}; |
282
|
40
|
|
|
|
|
117
|
$export_ok_hash->{$caller_func}=_export_sym($our_func,$class,$ancestors); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
} |
285
|
6
|
|
|
|
|
81
|
@$export_ok_list=keys %$export_ok_hash; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
sub SUBCLASS_EXPORT_OK { |
288
|
8
|
|
|
8
|
|
66
|
my $helper_class=shift; |
289
|
8
|
|
|
|
|
40
|
my($class)=$helper_class=~/^(.*)::helper$/; |
290
|
30
|
|
|
30
|
|
192
|
no strict 'refs'; |
|
30
|
|
|
|
|
68
|
|
|
30
|
|
|
|
|
3851
|
|
291
|
|
|
|
|
|
|
# for Hash::AutoHash::helper, @SUBCLASS_EXPORT_OK is given |
292
|
8
|
100
|
|
|
|
24
|
if ($helper_class eq __PACKAGE__) { # NOTE: change this if you copy-and-paste into subclass |
293
|
2
|
|
|
|
|
383
|
return @{$class.'::SUBCLASS_EXPORT_OK'}; |
|
2
|
|
|
|
|
53
|
|
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
# for subclasses, @SUBCLASS_EXPORT_OK must be computed |
296
|
6
|
|
|
|
|
10
|
my $subclass_export_ok=\@{$class.'::SUBCLASS_EXPORT_OK'}; |
|
6
|
|
|
|
|
24
|
|
297
|
|
|
|
|
|
|
# NG 12-11-29: 'defined @array' deprecated in 5.16 or so |
298
|
|
|
|
|
|
|
# return @$subclass_export_ok if defined @$subclass_export_ok; |
299
|
6
|
50
|
|
|
|
23
|
return @$subclass_export_ok if @$subclass_export_ok; |
300
|
6
|
|
|
|
|
18
|
return @$subclass_export_ok=$helper_class->EXPORT_OK; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
sub _export_sym { |
304
|
690
|
|
|
690
|
|
921
|
my($func,$class,$ancestors)=@_; |
305
|
690
|
|
|
|
|
872
|
for my $export_class (@$ancestors) { # @$ancestors includes self |
306
|
30
|
|
|
30
|
|
170
|
no strict 'refs'; |
|
30
|
|
|
|
|
54
|
|
|
30
|
|
|
|
|
44515
|
|
307
|
738
|
|
|
|
|
1196
|
my $export_sym=$export_class.'::'.$func; |
308
|
738
|
100
|
|
|
|
678
|
return $export_sym if defined *{$export_sym}{CODE}; |
|
738
|
|
|
|
|
3897
|
|
309
|
|
|
|
|
|
|
# see if ancestor renames it |
310
|
62
|
|
|
|
|
238
|
my($class)=$export_class=~/^(.*)::helper$/; |
311
|
62
|
|
|
|
|
78
|
my $export_sym=${$class.'::EXPORT_OK'}{$func}; |
|
62
|
|
|
|
|
156
|
|
312
|
62
|
100
|
|
|
|
192
|
return $export_sym if defined $export_sym; |
313
|
|
|
|
|
|
|
} |
314
|
4
|
|
|
|
|
17
|
undef; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
################################################################################# |
318
|
|
|
|
|
|
|
# constructor functions. recommended over 'new' |
319
|
|
|
|
|
|
|
################################################################################# |
320
|
|
|
|
|
|
|
# make real autohash |
321
|
|
|
|
|
|
|
# any extra params are key=>value pairs stored in object |
322
|
|
|
|
|
|
|
sub autohash_hash { |
323
|
160
|
|
|
160
|
|
32027
|
my(@hash)=@_; |
324
|
|
|
|
|
|
|
# store params in self. can do in one step since no special semantics to worry about |
325
|
160
|
|
|
|
|
670
|
my $self=bless {@hash},'Hash::AutoHash'; |
326
|
160
|
|
|
|
|
535
|
$self; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
# tie autohash |
329
|
|
|
|
|
|
|
# any extra params passed to tie |
330
|
|
|
|
|
|
|
sub autohash_tie (*@) { |
331
|
115
|
|
|
115
|
|
56073
|
my($hash_class,@hash_params)=@_; |
332
|
115
|
|
|
|
|
364
|
my $self=bless {},'Hash::AutoHash'; |
333
|
115
|
|
|
|
|
764
|
tie %$self,$hash_class,@hash_params; |
334
|
115
|
|
|
|
|
2637
|
$self; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
# wrap pre-existing hash. |
337
|
|
|
|
|
|
|
# any extra params are key=>value pairs passed to hash |
338
|
|
|
|
|
|
|
sub autohash_wrap (\%@) { |
339
|
240
|
|
|
240
|
|
52334
|
my($hash,@hash)=@_; |
340
|
|
|
|
|
|
|
# pass params to hash in loop in case it's tied hash with special semantics |
341
|
240
|
|
|
|
|
916
|
while (@hash>1) { |
342
|
498
|
|
|
|
|
2328
|
my($key,$value)=splice @hash,0,2; # shift 1st two elements |
343
|
498
|
|
|
|
|
2349
|
$hash->{$key}=$value; |
344
|
|
|
|
|
|
|
} |
345
|
240
|
|
|
|
|
1448
|
my $self=bless {},'Hash::AutoHash'; |
346
|
|
|
|
|
|
|
# if $hash is real, tie to 'alias', so autohash will alias hash |
347
|
240
|
100
|
|
|
|
1113
|
if (my $object=tied(%$hash)) { |
348
|
122
|
|
|
|
|
1109
|
tie %$self,'Tie::ToObject',$object; |
349
|
|
|
|
|
|
|
} else { |
350
|
118
|
|
|
|
|
653
|
tie %$self,'Hash::AutoHash::alias',$hash; |
351
|
|
|
|
|
|
|
} |
352
|
240
|
|
|
|
|
3355
|
$self; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
# wrap pre-existing tied object. (ie, object returned by tie), |
355
|
|
|
|
|
|
|
# any extra params are key=>value pairs passed to object's STORE method |
356
|
|
|
|
|
|
|
sub autohash_wrapobj { |
357
|
128
|
|
|
128
|
|
39846
|
my($object,@hash)=@_; |
358
|
|
|
|
|
|
|
# pass params to hash in loop in case it's tied hash with special semantics |
359
|
128
|
|
|
|
|
441
|
while (@hash>1) { |
360
|
259
|
|
|
|
|
1667
|
my($key,$value)=splice @hash,0,2; # shift 1st two elements |
361
|
259
|
|
|
|
|
831
|
$object->STORE($key,$value); |
362
|
|
|
|
|
|
|
} |
363
|
128
|
|
|
|
|
1023
|
my $self=bless {},'Hash::AutoHash'; |
364
|
128
|
|
|
|
|
988
|
tie %$self,'Tie::ToObject',$object; |
365
|
128
|
|
|
|
|
2385
|
$self; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
# tie and wrap hash in one step. any extra params passed to tie |
368
|
|
|
|
|
|
|
# kinda silly, but oh well... |
369
|
|
|
|
|
|
|
sub autohash_wraptie (\%*@) { |
370
|
128
|
|
|
128
|
|
43101
|
my($hash,$hash_class,@hash_params)=@_; |
371
|
128
|
|
|
|
|
746
|
my $object=tie %$hash,$hash_class,@hash_params; |
372
|
128
|
|
|
|
|
2936
|
my $self=bless {},'Hash::AutoHash'; |
373
|
128
|
|
|
|
|
1147
|
tie %$self,'Tie::ToObject',$object; |
374
|
128
|
|
|
|
|
2576
|
$self; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
# autohash_new - CAUTION: must come after other constructors because of prototypes |
377
|
|
|
|
|
|
|
# front-end to other constructor functions |
378
|
|
|
|
|
|
|
# cases: |
379
|
|
|
|
|
|
|
# 1) 0 params - autohash_hash |
380
|
|
|
|
|
|
|
# 2) >0 params - 1st param unblessed ARRAY - autohash_tie or autohash_wraptie |
381
|
|
|
|
|
|
|
# 0th element scalar - autohash_tie |
382
|
|
|
|
|
|
|
# 0th element HASH - autohash_wraptie |
383
|
|
|
|
|
|
|
# 3) >0 params - 1st param unblessed HASH - autohash_wrap |
384
|
|
|
|
|
|
|
# 4) >0 params - 1st param blessed HASH apparently not tied hash - autohash_wrap |
385
|
|
|
|
|
|
|
# 5) >0 params - 1st param blessed and looks like tied hash object - autohash_wrapobj |
386
|
|
|
|
|
|
|
# 6) other - autohash_hash |
387
|
|
|
|
|
|
|
sub autohash_new { |
388
|
348
|
100
|
|
348
|
|
126200
|
if (@_) { |
389
|
302
|
100
|
|
|
|
1052
|
if ('ARRAY' eq ref $_[0]) { # autohash_tie or autohash_wraptie |
390
|
94
|
|
|
|
|
167
|
my $autohash; |
391
|
94
|
|
|
|
|
175
|
my $params=shift; |
392
|
94
|
|
|
|
|
182
|
my $class_or_hash=shift @$params; |
393
|
94
|
100
|
|
|
|
307
|
unless (ref $class_or_hash) { # it's a class. so tie it |
394
|
37
|
|
|
|
|
131
|
$autohash=autohash_tie($class_or_hash,@$params); |
395
|
|
|
|
|
|
|
} else { # it's a hash. next param is class |
396
|
57
|
|
|
|
|
153
|
my $hash=$class_or_hash; |
397
|
57
|
|
|
|
|
106
|
my $class=shift @$params; |
398
|
57
|
|
|
|
|
228
|
$autohash=autohash_wraptie(%$hash,$class,@$params); |
399
|
|
|
|
|
|
|
} |
400
|
94
|
|
|
|
|
352
|
return autohash_set($autohash,@_); |
401
|
|
|
|
|
|
|
} |
402
|
208
|
100
|
100
|
|
|
1220
|
if ('HASH' eq reftype($_[0]) && !_looks_wrappable($_[0])) { |
403
|
102
|
|
|
|
|
173
|
my $hash=shift; |
404
|
102
|
|
|
|
|
5517
|
return autohash_wrap(%$hash,@_); |
405
|
|
|
|
|
|
|
} |
406
|
106
|
100
|
|
|
|
318
|
if (_looks_wrappable($_[0])) { |
407
|
54
|
|
|
|
|
197
|
return autohash_wrapobj(@_); |
408
|
|
|
|
|
|
|
}} |
409
|
|
|
|
|
|
|
# none of the above, so must be real |
410
|
98
|
|
|
|
|
306
|
autohash_hash(@_); |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
# try to decide if object tied to hash. very approximate... |
414
|
|
|
|
|
|
|
# say yes if blessed and has TIEHASH method |
415
|
260
|
100
|
|
260
|
|
1889
|
sub _looks_wrappable {blessed($_[0]) && UNIVERSAL::can($_[0],'TIEHASH');} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
################################################################################# |
418
|
|
|
|
|
|
|
# following functions provide standard hash operations on Hash::AutoHash |
419
|
|
|
|
|
|
|
# objects. they delegate to wrapped goodie |
420
|
|
|
|
|
|
|
################################################################################# |
421
|
15
|
|
|
15
|
|
32390
|
sub autohash_clear {%{$_[0]}=()} |
|
15
|
|
|
|
|
109
|
|
422
|
|
|
|
|
|
|
sub autohash_delete { |
423
|
185
|
|
|
185
|
|
3270
|
my $self=shift; |
424
|
185
|
|
|
|
|
963
|
delete @$self{@_}; |
425
|
|
|
|
|
|
|
} |
426
|
490
|
|
|
490
|
|
844020
|
sub autohash_each {each %{$_[0]}} |
|
490
|
|
|
|
|
2068
|
|
427
|
327
|
|
|
327
|
|
10512
|
sub autohash_exists {exists $_[0]->{$_[1]}} |
428
|
98
|
|
|
98
|
|
6236
|
sub autohash_keys {keys %{$_[0]}} |
|
98
|
|
|
|
|
569
|
|
429
|
95
|
|
|
95
|
|
2749
|
sub autohash_values {values %{$_[0]}} |
|
95
|
|
|
|
|
792
|
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
################################################################################# |
432
|
|
|
|
|
|
|
# convenience methods easily be built on top of keys |
433
|
|
|
|
|
|
|
################################################################################# |
434
|
26
|
100
|
|
26
|
|
5067
|
sub autohash_count {scalar(keys %{$_[0]}) || 0} |
|
26
|
|
|
|
|
159
|
|
435
|
27
|
100
|
|
27
|
|
1216
|
sub autohash_empty {scalar(%{$_[0]})? undef: 1} |
|
27
|
|
|
|
|
140
|
|
436
|
27
|
100
|
|
27
|
|
12253
|
sub autohash_notempty {scalar(%{$_[0]})? 1: undef} |
|
27
|
|
|
|
|
276
|
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
################################################################################ |
439
|
|
|
|
|
|
|
# alias - connect autohash to hash - can be used to do the opposite of wrap |
440
|
|
|
|
|
|
|
################################################################################ |
441
|
|
|
|
|
|
|
sub autohash_alias (\$\%@) { |
442
|
49
|
|
|
49
|
|
8497
|
my($autohash_ref,$hash,@hash)=@_; |
443
|
49
|
100
|
|
|
|
154
|
if (!defined $$autohash_ref) { # no autohash, so create alias from hash to autohash |
444
|
8
|
|
|
|
|
29
|
return $$autohash_ref=autohash_wrap(%$hash,@hash); |
445
|
|
|
|
|
|
|
} else { # create alias from autohash to hash |
446
|
41
|
|
|
|
|
71
|
my $autohash=$$autohash_ref; |
447
|
41
|
|
|
|
|
116
|
autohash_set($autohash,@hash); |
448
|
41
|
|
|
|
|
190
|
tie %$hash,'Hash::AutoHash::alias',$autohash; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
################################################################################ |
452
|
|
|
|
|
|
|
# functional access to tied object. works on aliased hash, also |
453
|
|
|
|
|
|
|
################################################################################ |
454
|
|
|
|
|
|
|
# sub autohash_options (\[$%]) { |
455
|
|
|
|
|
|
|
# my($ref)=@_; |
456
|
|
|
|
|
|
|
# my $autohash; |
457
|
|
|
|
|
|
|
# if ('REF' eq ref $ref) { # it's autohash (we hope :) |
458
|
|
|
|
|
|
|
# $autohash=$$ref; # dereference to get autohash |
459
|
|
|
|
|
|
|
# my $object=tied %$autohash; |
460
|
|
|
|
|
|
|
# return undef unless $object; # real hash |
461
|
|
|
|
|
|
|
# return undef if 'Hash::AutoHash::alias' eq ref $object; # aliased to real |
462
|
|
|
|
|
|
|
# return $object; # tied or aliased to tied |
463
|
|
|
|
|
|
|
# } elsif ('HASH' eq ref $ref) { # HASH may be tied to 'real object or 'alias' |
464
|
|
|
|
|
|
|
# my $object=tied %$ref; |
465
|
|
|
|
|
|
|
# return undef unless $object; |
466
|
|
|
|
|
|
|
# return $object unless 'Hash::AutoHash::alias' eq ref $object; |
467
|
|
|
|
|
|
|
# # hash aliased to autohash. recurse to get underlying tied object |
468
|
|
|
|
|
|
|
# $autohash=$object->[0]; # extract autohash from alias |
469
|
|
|
|
|
|
|
# return &autohash_options(\$autohash); # use old-style call to turn off prototyping |
470
|
|
|
|
|
|
|
# } |
471
|
|
|
|
|
|
|
# undef; |
472
|
|
|
|
|
|
|
# } |
473
|
|
|
|
|
|
|
# sub autohash_options (\[$%]) { |
474
|
|
|
|
|
|
|
# my($ref)=@_; |
475
|
|
|
|
|
|
|
# my($autohash,$hash); |
476
|
|
|
|
|
|
|
# $autohash=$$ref if 'REF' eq ref $ref; # it's autohash (we hope :) |
477
|
|
|
|
|
|
|
# $hash=$ref if 'HASH' eq ref $ref; |
478
|
|
|
|
|
|
|
# if ($hash) { # do hash case first. sometimes falls into autohash case |
479
|
|
|
|
|
|
|
# my $object=tied %$ref; |
480
|
|
|
|
|
|
|
# return undef unless $object; |
481
|
|
|
|
|
|
|
# return $object unless 'Hash::AutoHash::alias' eq ref $object; |
482
|
|
|
|
|
|
|
# # hash aliased to autohash. extract autohash from alias and fall into authohash case |
483
|
|
|
|
|
|
|
# $autohash=$object->[0]; |
484
|
|
|
|
|
|
|
# } |
485
|
|
|
|
|
|
|
# if ($autohash) { |
486
|
|
|
|
|
|
|
# my $object=tied %$autohash; |
487
|
|
|
|
|
|
|
# return undef unless $object; # real hash |
488
|
|
|
|
|
|
|
# return undef if 'Hash::AutoHash::alias' eq ref $object; # aliased to real |
489
|
|
|
|
|
|
|
# return $object; # tied or aliased to tied |
490
|
|
|
|
|
|
|
# } |
491
|
|
|
|
|
|
|
# undef; |
492
|
|
|
|
|
|
|
# } |
493
|
|
|
|
|
|
|
# sub autohash_option (\[$%]@) { |
494
|
|
|
|
|
|
|
# my($ref,$option,@params)=@_; |
495
|
|
|
|
|
|
|
# my $object=&autohash_options($ref); # use old-style call to turn off prototyping |
496
|
|
|
|
|
|
|
# return undef unless $object; |
497
|
|
|
|
|
|
|
# $object->$option(@params); |
498
|
|
|
|
|
|
|
# } |
499
|
|
|
|
|
|
|
sub autohash_tied (\[$%]@) { |
500
|
376
|
|
|
376
|
|
21183
|
my $ref=shift; |
501
|
376
|
|
|
|
|
441
|
my($autohash,$hash,$tied); |
502
|
376
|
100
|
|
|
|
953
|
$autohash=$$ref if 'REF' eq ref $ref; # it's autohash (we hope :) |
503
|
376
|
100
|
|
|
|
832
|
$hash=$ref if 'HASH' eq ref $ref; |
504
|
376
|
100
|
|
|
|
719
|
if ($hash) { # do hash case first. sometimes falls into autohash case |
505
|
171
|
|
|
|
|
213
|
$tied=tied %$ref; |
506
|
|
|
|
|
|
|
# hash aliased to autohash. extract autohash from alias and fall into authohash case |
507
|
171
|
100
|
|
|
|
434
|
$autohash=$tied->[0] if 'Hash::AutoHash::alias' eq ref $tied; |
508
|
|
|
|
|
|
|
} |
509
|
376
|
100
|
|
|
|
818
|
if ($autohash) { |
510
|
296
|
|
|
|
|
368
|
$tied=tied %$autohash; |
511
|
296
|
100
|
|
|
|
682
|
$tied=undef if 'Hash::AutoHash::alias' eq ref $tied; # aliased to real |
512
|
|
|
|
|
|
|
} |
513
|
376
|
100
|
100
|
|
|
1882
|
return $tied unless @_ && $tied; |
514
|
|
|
|
|
|
|
# have tied object and there are more params. this means 'run method on tied object' |
515
|
168
|
|
|
|
|
307
|
my($method,@params)=@_; |
516
|
168
|
|
|
|
|
826
|
$tied->$method(@params); |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
################################################################################# |
520
|
|
|
|
|
|
|
# get and set offer extended functionality for users of this interface. |
521
|
|
|
|
|
|
|
# 'set' is the useful one. 'get' provided for symmetry |
522
|
|
|
|
|
|
|
################################################################################# |
523
|
|
|
|
|
|
|
# get values for one or more keys. |
524
|
|
|
|
|
|
|
sub autohash_get { |
525
|
137
|
|
|
137
|
|
3401
|
my $self=shift; |
526
|
137
|
|
|
|
|
607
|
@$self{@_}; |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
# set one or more key=>value pairs in hash |
529
|
|
|
|
|
|
|
sub autohash_set { |
530
|
183
|
|
|
183
|
|
8818
|
my $self=shift; |
531
|
183
|
100
|
100
|
|
|
1092
|
if (@_==2 && 'ARRAY' eq ref $_[0] && 'ARRAY' eq ref $_[1]) { # separate arrays form |
|
|
|
66
|
|
|
|
|
532
|
19
|
|
|
|
|
33
|
my($keys,$values)=@_; |
533
|
19
|
|
|
|
|
62
|
for (my $i=0; $i<@$keys; $i++) { |
534
|
23
|
|
|
|
|
101
|
my($key,$value)=($keys->[$i],$values->[$i]); |
535
|
23
|
|
|
|
|
106
|
$self->{$key}=$value; |
536
|
|
|
|
|
|
|
}} else { # key=>value form |
537
|
164
|
|
|
|
|
552
|
while (@_>1) { |
538
|
255
|
|
|
|
|
1787
|
my($key,$value)=splice @_,0,2; # shift 1st two elements |
539
|
255
|
|
|
|
|
1227
|
$self->{$key}=$value; |
540
|
|
|
|
|
|
|
}} |
541
|
183
|
|
|
|
|
1328
|
$self; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
################################################################################# |
545
|
|
|
|
|
|
|
# destroy and untie rarely used but needed for full tied hash functionality. |
546
|
|
|
|
|
|
|
# destroy nop. untie calls tied object's untie method |
547
|
|
|
|
|
|
|
################################################################################# |
548
|
0
|
|
|
0
|
|
0
|
sub autohash_destroy {} |
549
|
|
|
|
|
|
|
sub autohash_untie { |
550
|
0
|
|
|
0
|
|
0
|
my $object=tied(%{$_[0]}); |
|
0
|
|
|
|
|
0
|
|
551
|
0
|
0
|
|
|
|
0
|
$object->UNTIE() if $object; |
552
|
|
|
|
|
|
|
} |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# ################################################################################# |
555
|
|
|
|
|
|
|
# # this package used to 'dup' autohash to externally supplied real hash |
556
|
|
|
|
|
|
|
# # amazing that nothing in CPAN does this! I found several 'alias' packages but |
557
|
|
|
|
|
|
|
# # none could connect new variable to old one without changing the type of old |
558
|
|
|
|
|
|
|
# ################################################################################# |
559
|
|
|
|
|
|
|
# package Hash::AutoHash::dup; |
560
|
|
|
|
|
|
|
# use strict; |
561
|
|
|
|
|
|
|
# use Tie::Hash; |
562
|
|
|
|
|
|
|
# our @ISA=qw(Tie::ExtraHash); |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
# sub TIEHASH { |
565
|
|
|
|
|
|
|
# my($class,$existing_hash)=@_; |
566
|
|
|
|
|
|
|
# bless [$existing_hash],$class; |
567
|
|
|
|
|
|
|
# } |
568
|
|
|
|
|
|
|
################################################################################# |
569
|
|
|
|
|
|
|
# this package used to 'alias' hash to externally supplied hash |
570
|
|
|
|
|
|
|
# amazing that nothing in CPAN does this! I found several 'alias' packages but |
571
|
|
|
|
|
|
|
# none could connect new variable to old one without changing the type of old |
572
|
|
|
|
|
|
|
################################################################################# |
573
|
|
|
|
|
|
|
package Hash::AutoHash::alias; |
574
|
|
|
|
|
|
|
our $VERSION=$Hash::AutoHash::VERSION; |
575
|
30
|
|
|
30
|
|
203
|
use strict; |
|
30
|
|
|
|
|
75
|
|
|
30
|
|
|
|
|
901
|
|
576
|
30
|
|
|
30
|
|
29626
|
use Tie::Hash; |
|
30
|
|
|
|
|
28462
|
|
|
30
|
|
|
|
|
2801
|
|
577
|
|
|
|
|
|
|
our @ISA=qw(Tie::ExtraHash); |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub TIEHASH { |
580
|
159
|
|
|
159
|
|
300
|
my($class,$existing_autohash)=@_; |
581
|
159
|
|
|
|
|
741
|
bless [$existing_autohash],$class; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
1; |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
__END__ |