line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package HTML::FormFu::ObjectUtil; |
2
|
|
|
|
|
|
|
|
3
|
401
|
|
|
401
|
|
1533
|
use strict; |
|
401
|
|
|
|
|
538
|
|
|
401
|
|
|
|
|
14306
|
|
4
|
401
|
|
|
401
|
|
2334
|
use warnings; |
|
401
|
|
|
|
|
450
|
|
|
401
|
|
|
|
|
17524
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '2.05'; # VERSION |
7
|
|
|
|
|
|
|
|
8
|
401
|
|
|
401
|
|
1367
|
use Exporter qw( import ); |
|
401
|
|
|
|
|
2182
|
|
|
401
|
|
|
|
|
12709
|
|
9
|
|
|
|
|
|
|
|
10
|
401
|
|
|
|
|
23002
|
use HTML::FormFu::Util qw( |
11
|
|
|
|
|
|
|
_parse_args require_class |
12
|
|
|
|
|
|
|
_get_elements |
13
|
|
|
|
|
|
|
_filter_components _merge_hashes |
14
|
401
|
|
|
401
|
|
2284
|
); |
|
401
|
|
|
|
|
1351
|
|
15
|
401
|
|
|
401
|
|
148817
|
use Clone (); |
|
401
|
|
|
|
|
777550
|
|
|
401
|
|
|
|
|
11750
|
|
16
|
401
|
|
|
401
|
|
160222
|
use Config::Any; |
|
401
|
|
|
|
|
2575457
|
|
|
401
|
|
|
|
|
16722
|
|
17
|
401
|
|
|
401
|
|
177110
|
use Data::Visitor::Callback; |
|
401
|
|
|
|
|
23193456
|
|
|
401
|
|
|
|
|
14015
|
|
18
|
401
|
|
|
401
|
|
2796
|
use File::Spec; |
|
401
|
|
|
|
|
549
|
|
|
401
|
|
|
|
|
13202
|
|
19
|
401
|
|
|
401
|
|
1501
|
use Scalar::Util qw( refaddr weaken blessed ); |
|
401
|
|
|
|
|
1434
|
|
|
401
|
|
|
|
|
26552
|
|
20
|
401
|
|
|
401
|
|
1740
|
use Carp qw( croak ); |
|
401
|
|
|
|
|
2411
|
|
|
401
|
|
|
|
|
607404
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our @EXPORT_OK = ( qw( |
23
|
|
|
|
|
|
|
deflator |
24
|
|
|
|
|
|
|
load_config_file load_config_filestem |
25
|
|
|
|
|
|
|
form |
26
|
|
|
|
|
|
|
get_parent |
27
|
|
|
|
|
|
|
insert_before insert_after |
28
|
|
|
|
|
|
|
clone |
29
|
|
|
|
|
|
|
name |
30
|
|
|
|
|
|
|
stash |
31
|
|
|
|
|
|
|
constraints_from_dbic |
32
|
|
|
|
|
|
|
parent |
33
|
|
|
|
|
|
|
nested_name nested_names |
34
|
|
|
|
|
|
|
remove_element |
35
|
|
|
|
|
|
|
_string_equals _object_equals |
36
|
|
|
|
|
|
|
_load_file |
37
|
|
|
|
|
|
|
), |
38
|
|
|
|
|
|
|
); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub load_config_file { |
41
|
140
|
|
|
140
|
0
|
1033
|
my ( $self, @files ) = @_; |
42
|
|
|
|
|
|
|
|
43
|
140
|
|
|
|
|
245
|
my $use_stems = 0; |
44
|
|
|
|
|
|
|
|
45
|
140
|
|
|
|
|
569
|
return _load_config( $self, $use_stems, @files ); |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub load_config_filestem { |
49
|
1
|
|
|
1
|
0
|
8
|
my ( $self, @files ) = @_; |
50
|
|
|
|
|
|
|
|
51
|
1
|
|
|
|
|
2
|
my $use_stems = 1; |
52
|
|
|
|
|
|
|
|
53
|
1
|
|
|
|
|
4
|
return _load_config( $self, $use_stems, @files ); |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub _load_config { |
57
|
141
|
|
|
141
|
|
292
|
my ( $self, $use_stems, @filenames ) = @_; |
58
|
|
|
|
|
|
|
|
59
|
141
|
100
|
66
|
|
|
1013
|
if ( scalar @filenames == 1 && ref $filenames[0] eq 'ARRAY' ) { |
60
|
1
|
|
|
|
|
3
|
@filenames = @{ $filenames[0] }; |
|
1
|
|
|
|
|
3
|
|
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
141
|
|
|
|
|
633
|
my $config_callback = $self->config_callback; |
64
|
141
|
|
|
|
|
205
|
my $data_visitor; |
65
|
|
|
|
|
|
|
|
66
|
141
|
100
|
|
|
|
415
|
if ( defined $config_callback ) { |
67
|
2
|
|
|
|
|
77
|
$data_visitor = Data::Visitor::Callback->new( %$config_callback, |
68
|
|
|
|
|
|
|
ignore_return_values => 1, ); |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
141
|
100
|
|
|
|
915
|
my $config_any_arg = $use_stems ? 'stems' : 'files'; |
72
|
141
|
100
|
|
|
|
379
|
my $config_any_method = $use_stems ? 'load_stems' : 'load_files'; |
73
|
|
|
|
|
|
|
|
74
|
141
|
|
|
|
|
188
|
my @config_file_path; |
75
|
|
|
|
|
|
|
|
76
|
141
|
100
|
|
|
|
535
|
if ( my $config_file_path = $self->config_file_path ) { |
77
|
|
|
|
|
|
|
|
78
|
4
|
100
|
|
|
|
12
|
if ( ref $config_file_path eq 'ARRAY' ) { |
79
|
3
|
|
|
|
|
11
|
push @config_file_path, @$config_file_path; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
else { |
82
|
1
|
|
|
|
|
3
|
push @config_file_path, $config_file_path; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
else { |
86
|
137
|
|
|
|
|
1503
|
push @config_file_path, File::Spec->curdir; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
141
|
|
|
|
|
484
|
for my $file (@filenames) { |
90
|
142
|
|
|
|
|
210
|
my $loaded = 0; |
91
|
142
|
|
|
|
|
612
|
my $fullpath; |
92
|
|
|
|
|
|
|
|
93
|
142
|
|
|
|
|
10378
|
foreach my $config_file_path (@config_file_path) { |
94
|
|
|
|
|
|
|
|
95
|
149
|
50
|
33
|
|
|
2046
|
if ( defined $config_file_path |
96
|
|
|
|
|
|
|
&& !File::Spec->file_name_is_absolute($file) ) |
97
|
|
|
|
|
|
|
{ |
98
|
149
|
|
|
|
|
1989
|
$fullpath = File::Spec->catfile( $config_file_path, $file ); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
else { |
101
|
0
|
|
|
|
|
0
|
$fullpath = $file; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
149
|
|
|
|
|
2630
|
my $config = Config::Any->$config_any_method( { |
105
|
|
|
|
|
|
|
$config_any_arg => [$fullpath], |
106
|
|
|
|
|
|
|
use_ext => 1, |
107
|
|
|
|
|
|
|
driver_args => { General => { -UTF8 => 1 }, }, |
108
|
|
|
|
|
|
|
} ); |
109
|
|
|
|
|
|
|
|
110
|
149
|
100
|
|
|
|
1378966
|
next if !@$config; |
111
|
|
|
|
|
|
|
|
112
|
141
|
|
|
|
|
317
|
$loaded = 1; |
113
|
141
|
|
|
|
|
214
|
my ( $filename, $filedata ) = %{ $config->[0] }; |
|
141
|
|
|
|
|
562
|
|
114
|
|
|
|
|
|
|
|
115
|
141
|
|
|
|
|
574
|
_load_file( $self, $data_visitor, $filedata ); |
116
|
141
|
|
|
|
|
1610
|
last; |
117
|
|
|
|
|
|
|
} |
118
|
142
|
100
|
|
|
|
805
|
croak "config file '$file' not found" if !$loaded; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
140
|
|
|
|
|
1204
|
return $self; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub _load_file { |
125
|
141
|
|
|
141
|
|
267
|
my ( $self, $data_visitor, $data ) = @_; |
126
|
|
|
|
|
|
|
|
127
|
141
|
100
|
|
|
|
500
|
if ( defined $data_visitor ) { |
128
|
2
|
|
|
|
|
12
|
$data_visitor->visit($data); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
141
|
100
|
|
|
|
5565
|
for my $config ( ref $data eq 'ARRAY' ? @$data : $data ) { |
132
|
142
|
|
|
|
|
4171
|
$self->populate( Clone::clone($config) ); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
141
|
|
|
|
|
362
|
return; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub form { |
139
|
29767
|
|
|
29767
|
0
|
23452
|
my ($self) = @_; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# micro optimization! this method's called a lot, so access |
142
|
|
|
|
|
|
|
# parent hashkey directly, instead of calling parent() |
143
|
29767
|
|
|
|
|
48525
|
while ( defined( my $parent = $self->{parent} ) ) { |
144
|
50876
|
|
|
|
|
72222
|
$self = $parent; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
29767
|
|
|
|
|
546429
|
return $self; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub clone { |
151
|
2
|
|
|
2
|
0
|
402
|
my ($self) = @_; |
152
|
|
|
|
|
|
|
|
153
|
2
|
|
|
|
|
25
|
my %new = %$self; |
154
|
|
|
|
|
|
|
|
155
|
2
|
|
|
|
|
5
|
$new{_elements} = [ map { $_->clone } @{ $self->_elements } ]; |
|
2
|
|
|
|
|
24
|
|
|
2
|
|
|
|
|
93
|
|
156
|
2
|
|
|
|
|
9
|
$new{attributes} = Clone::clone( $self->attributes ); |
157
|
2
|
|
|
|
|
9
|
$new{tt_args} = Clone::clone( $self->tt_args ); |
158
|
2
|
|
|
|
|
10
|
$new{model_config} = Clone::clone( $self->model_config ); |
159
|
|
|
|
|
|
|
|
160
|
2
|
50
|
|
|
|
11
|
if ( $self->can('_plugins') ) { |
161
|
2
|
|
|
|
|
2
|
$new{_plugins} = [ map { $_->clone } @{ $self->_plugins } ]; |
|
0
|
|
|
|
|
0
|
|
|
2
|
|
|
|
|
66
|
|
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
$new{languages} |
165
|
2
|
50
|
|
|
|
48
|
= ref $self->languages |
166
|
|
|
|
|
|
|
? Clone::clone( $self->languages ) |
167
|
|
|
|
|
|
|
: $self->languages; |
168
|
|
|
|
|
|
|
|
169
|
2
|
|
|
|
|
6
|
$new{default_args} = $self->default_args; |
170
|
|
|
|
|
|
|
|
171
|
2
|
|
|
|
|
6
|
my $obj = bless \%new, ref $self; |
172
|
|
|
|
|
|
|
|
173
|
2
|
|
|
|
|
3
|
map { $_->parent($obj) } @{ $new{_elements} }; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
174
|
|
|
|
|
|
|
|
175
|
2
|
|
|
|
|
5
|
return $obj; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub name { |
179
|
111
|
|
|
111
|
0
|
2294
|
my $self = shift; |
180
|
|
|
|
|
|
|
|
181
|
111
|
50
|
|
|
|
171
|
croak 'cannot use name() as a setter' if @_; |
182
|
|
|
|
|
|
|
|
183
|
111
|
|
|
|
|
147
|
return $self->parent->name; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub nested_name { |
187
|
1187
|
|
|
1187
|
0
|
1181
|
my $self = shift; |
188
|
|
|
|
|
|
|
|
189
|
1187
|
50
|
|
|
|
2071
|
croak 'cannot use nested_name() as a setter' if @_; |
190
|
|
|
|
|
|
|
|
191
|
1187
|
|
|
|
|
1904
|
return $self->parent->nested_name; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub nested_names { |
195
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
196
|
|
|
|
|
|
|
|
197
|
0
|
0
|
|
|
|
0
|
croak 'cannot use nested_names() as a setter' if @_; |
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
0
|
return $self->parent->nested_names; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub stash { |
203
|
5125
|
|
|
5125
|
0
|
5306
|
my $self = shift; |
204
|
|
|
|
|
|
|
|
205
|
5125
|
100
|
|
|
|
10845
|
$self->{stash} = {} if not exists $self->{stash}; |
206
|
5125
|
100
|
|
|
|
12426
|
return $self->{stash} if !@_; |
207
|
|
|
|
|
|
|
|
208
|
3306
|
50
|
|
|
|
5946
|
my %attrs = ( @_ == 1 ) ? %{ $_[0] } : @_; |
|
3306
|
|
|
|
|
5587
|
|
209
|
|
|
|
|
|
|
|
210
|
3306
|
|
|
|
|
5324
|
$self->{stash}->{$_} = $attrs{$_} for keys %attrs; |
211
|
|
|
|
|
|
|
|
212
|
3306
|
|
|
|
|
4794
|
return $self; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub constraints_from_dbic { |
216
|
2
|
|
|
2
|
0
|
61280
|
my ( $self, $source, $map ) = @_; |
217
|
|
|
|
|
|
|
|
218
|
2
|
|
100
|
|
|
10
|
$map ||= {}; |
219
|
|
|
|
|
|
|
|
220
|
2
|
|
|
|
|
8
|
$source = _result_source($source); |
221
|
|
|
|
|
|
|
|
222
|
2
|
|
|
|
|
62
|
for my $col ( $source->columns ) { |
223
|
8
|
|
|
|
|
645
|
_add_constraints( $self, $col, $source->column_info($col) ); |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
2
|
|
|
|
|
9
|
for my $col ( keys %$map ) { |
227
|
1
|
|
|
|
|
3
|
my $source = _result_source( $map->{$col} ); |
228
|
|
|
|
|
|
|
|
229
|
1
|
|
|
|
|
68
|
_add_constraints( $self, $col, $source->column_info($col) ); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
2
|
|
|
|
|
8
|
return $self; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub _result_source { |
236
|
3
|
|
|
3
|
|
6
|
my ($source) = @_; |
237
|
|
|
|
|
|
|
|
238
|
3
|
100
|
|
|
|
12
|
if ( blessed $source ) { |
239
|
1
|
|
|
|
|
4
|
$source = $source->result_source; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
3
|
|
|
|
|
116
|
return $source; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub _add_constraints { |
246
|
9
|
|
|
9
|
|
279
|
my ( $self, $col, $info ) = @_; |
247
|
|
|
|
|
|
|
|
248
|
9
|
100
|
|
|
|
37
|
return if !defined $self->get_field($col); |
249
|
|
|
|
|
|
|
|
250
|
7
|
50
|
|
|
|
22
|
return if !defined $info->{data_type}; |
251
|
|
|
|
|
|
|
|
252
|
7
|
|
|
|
|
18
|
my $type = lc $info->{data_type}; |
253
|
|
|
|
|
|
|
|
254
|
7
|
100
|
66
|
|
|
83
|
if ( $type =~ /(char|text|binary)\z/ && defined $info->{size} ) { |
|
|
100
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# char, varchar, *text, binary, varbinary |
257
|
3
|
|
|
|
|
9
|
_add_constraint_max_length( $self, $col, $info ); |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
elsif ( $type =~ /int/ ) { |
260
|
2
|
|
|
|
|
9
|
_add_constraint_integer( $self, $col, $info ); |
261
|
|
|
|
|
|
|
|
262
|
2
|
50
|
|
|
|
13
|
if ( $info->{extra}{unsigned} ) { |
263
|
2
|
|
|
|
|
7
|
_add_constraint_unsigned( $self, $col, $info ); |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
elsif ( $type =~ /enum|set/ && defined $info->{extra}{list} ) { |
268
|
2
|
|
|
|
|
9
|
_add_constraint_set( $self, $col, $info ); |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub _add_constraint_max_length { |
273
|
3
|
|
|
3
|
|
4
|
my ( $self, $col, $info ) = @_; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
$self->constraint( { |
276
|
|
|
|
|
|
|
type => 'MaxLength', |
277
|
|
|
|
|
|
|
name => $col, |
278
|
|
|
|
|
|
|
max => $info->{size}, |
279
|
3
|
|
|
|
|
27
|
} ); |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
sub _add_constraint_integer { |
283
|
2
|
|
|
2
|
|
5
|
my ( $self, $col, $info ) = @_; |
284
|
|
|
|
|
|
|
|
285
|
2
|
|
|
|
|
14
|
$self->constraint( { |
286
|
|
|
|
|
|
|
type => 'Integer', |
287
|
|
|
|
|
|
|
name => $col, |
288
|
|
|
|
|
|
|
} ); |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub _add_constraint_unsigned { |
292
|
2
|
|
|
2
|
|
4
|
my ( $self, $col, $info ) = @_; |
293
|
|
|
|
|
|
|
|
294
|
2
|
|
|
|
|
15
|
$self->constraint( { |
295
|
|
|
|
|
|
|
type => 'Range', |
296
|
|
|
|
|
|
|
name => $col, |
297
|
|
|
|
|
|
|
min => 0, |
298
|
|
|
|
|
|
|
} ); |
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
sub _add_constraint_set { |
302
|
2
|
|
|
2
|
|
9
|
my ( $self, $col, $info ) = @_; |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
$self->constraint( { |
305
|
|
|
|
|
|
|
type => 'Set', |
306
|
|
|
|
|
|
|
name => $col, |
307
|
|
|
|
|
|
|
set => $info->{extra}{list}, |
308
|
2
|
|
|
|
|
18
|
} ); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub parent { |
312
|
16470
|
|
|
16470
|
0
|
15066
|
my $self = shift; |
313
|
|
|
|
|
|
|
|
314
|
16470
|
100
|
|
|
|
23225
|
if (@_) { |
315
|
2468
|
|
|
|
|
3644
|
$self->{parent} = shift; |
316
|
|
|
|
|
|
|
|
317
|
2468
|
|
|
|
|
6587
|
weaken( $self->{parent} ); |
318
|
|
|
|
|
|
|
|
319
|
2468
|
|
|
|
|
4547
|
return $self; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
14002
|
|
|
|
|
58209
|
return $self->{parent}; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub get_parent { |
326
|
70
|
|
|
70
|
0
|
56
|
my $self = shift; |
327
|
|
|
|
|
|
|
|
328
|
70
|
100
|
|
|
|
117
|
return $self->parent |
329
|
|
|
|
|
|
|
if !@_; |
330
|
|
|
|
|
|
|
|
331
|
69
|
|
|
|
|
125
|
my %args = _parse_args(@_); |
332
|
|
|
|
|
|
|
|
333
|
69
|
|
|
|
|
114
|
while ( defined( my $parent = $self->parent ) ) { |
334
|
|
|
|
|
|
|
|
335
|
140
|
|
|
|
|
168
|
for my $name ( keys %args ) { |
336
|
140
|
|
|
|
|
87
|
my $value; |
337
|
|
|
|
|
|
|
|
338
|
140
|
100
|
66
|
|
|
3171
|
if ( $parent->can($name) |
|
|
|
100
|
|
|
|
|
339
|
|
|
|
|
|
|
&& defined( $value = $parent->$name ) |
340
|
|
|
|
|
|
|
&& $value eq $args{$name} ) |
341
|
|
|
|
|
|
|
{ |
342
|
67
|
|
|
|
|
216
|
return $parent; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
73
|
|
|
|
|
116
|
$self = $parent; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
2
|
|
|
|
|
7
|
return; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
sub _string_equals { |
353
|
0
|
|
|
0
|
|
|
my ( $a, $b ) = @_; |
354
|
|
|
|
|
|
|
|
355
|
0
|
0
|
|
|
|
|
return blessed($b) |
356
|
|
|
|
|
|
|
? ( refaddr($a) eq refaddr($b) ) |
357
|
|
|
|
|
|
|
: ( "$a" eq "$b" ); |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub _object_equals { |
361
|
0
|
|
|
0
|
|
|
my ( $a, $b ) = @_; |
362
|
|
|
|
|
|
|
|
363
|
0
|
0
|
|
|
|
|
return blessed($b) |
364
|
|
|
|
|
|
|
? ( refaddr($a) eq refaddr($b) ) |
365
|
|
|
|
|
|
|
: undef; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
1; |