| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Class::Accessor::Assert; |
|
2
|
1
|
|
|
1
|
|
26401
|
use 5.006; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
47
|
|
|
3
|
1
|
|
|
1
|
|
6
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
58
|
|
|
4
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
39
|
|
|
5
|
1
|
|
|
1
|
|
7
|
use base qw(Class::Accessor Class::Data::Inheritable); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1680
|
|
|
6
|
1
|
|
|
1
|
|
3522
|
use Carp qw(croak confess); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
155
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '1.41'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub _mk_accessors { |
|
10
|
1
|
|
|
1
|
|
20
|
my ( $self, $maker, @fields ) = @_; |
|
11
|
1
|
50
|
|
|
|
28
|
$self->mk_classdata("accessor_specs") |
|
12
|
|
|
|
|
|
|
unless $self->can("accessor_specs"); |
|
13
|
|
|
|
|
|
|
|
|
14
|
1
|
|
|
|
|
29
|
my %spec = $self->parse_fields(@fields); |
|
15
|
1
|
50
|
|
|
|
3
|
$self->accessor_specs( { %spec, %{ $self->accessor_specs || {} } } ); |
|
|
1
|
|
|
|
|
5
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
1
|
|
|
|
|
33
|
$self->SUPER::_mk_accessors( 'rw', keys %spec ); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
{ |
|
20
|
1
|
|
|
1
|
|
5
|
no strict 'refs'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1212
|
|
|
|
1
|
|
|
|
|
155
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# additional methods for magic array methods |
|
23
|
1
|
|
33
|
|
|
6
|
my $class = ref $self || $self; |
|
24
|
|
|
|
|
|
|
# Note how we curry the subs with the lexical "$field": |
|
25
|
|
|
|
|
|
|
# The subs are closures and therefore have access to their lexical |
|
26
|
|
|
|
|
|
|
# scope. Clarity suffers from this, but the performance should be |
|
27
|
|
|
|
|
|
|
# about 25% higher than a cleaner approach due to a saved subroutine |
|
28
|
|
|
|
|
|
|
# call for every ary_*(...) call. |
|
29
|
1
|
|
|
|
|
3
|
for my $field ( grep { $spec{$_}{array} } keys %spec ) { |
|
|
3
|
|
|
|
|
12
|
|
|
30
|
|
|
|
|
|
|
# foo_push sub |
|
31
|
0
|
|
|
|
|
0
|
*{"${class}::${field}_push"} = sub { |
|
32
|
0
|
|
|
0
|
|
0
|
my ( $self, @values ) = @_; |
|
33
|
0
|
0
|
|
|
|
0
|
$self->{$field} = [] unless defined $self->{$field}; |
|
34
|
0
|
|
|
|
|
0
|
push @{ $self->{$field} }, @values; |
|
|
0
|
|
|
|
|
0
|
|
|
35
|
0
|
|
|
|
|
0
|
}; |
|
36
|
|
|
|
|
|
|
# foo_pop sub |
|
37
|
0
|
|
|
|
|
0
|
*{"${class}::${field}_pop"} = sub { |
|
38
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
|
39
|
0
|
0
|
|
|
|
0
|
return pop @{ $self->{$field} || [] }; |
|
|
0
|
|
|
|
|
0
|
|
|
40
|
0
|
|
|
|
|
0
|
}; |
|
41
|
|
|
|
|
|
|
# foo_unshift sub |
|
42
|
0
|
|
|
|
|
0
|
*{"${class}::${field}_unshift"} = sub { |
|
43
|
0
|
|
|
0
|
|
0
|
my ( $self, @values ) = @_; |
|
44
|
0
|
0
|
|
|
|
0
|
$self->{$field} = [] unless defined $self->{$field}; |
|
45
|
0
|
|
|
|
|
0
|
unshift @{ $self->{$field} }, @values; |
|
|
0
|
|
|
|
|
0
|
|
|
46
|
0
|
|
|
|
|
0
|
}; |
|
47
|
|
|
|
|
|
|
# foo_shift sub |
|
48
|
0
|
|
|
|
|
0
|
*{"${class}::${field}_shift"} = sub { |
|
49
|
0
|
|
|
0
|
|
0
|
my ( $self ) = @_; |
|
50
|
0
|
0
|
|
|
|
0
|
return shift @{ $self->{$field} || [] }; |
|
|
0
|
|
|
|
|
0
|
|
|
51
|
0
|
|
|
|
|
0
|
}; |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
} |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub new { |
|
57
|
5
|
|
|
5
|
1
|
2720
|
my ( $self, $stuff ) = @_; |
|
58
|
5
|
100
|
|
|
|
6
|
my $not_a_void_context = eval { %{ $stuff || {} } }; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
31
|
|
|
59
|
5
|
100
|
|
|
|
305
|
croak "$stuff doesn't look much like a hash to me" if $@; |
|
60
|
4
|
50
|
|
|
|
21
|
if ( $self->can("accessor_specs") ) { |
|
61
|
4
|
|
|
|
|
13
|
my $spec = $self->accessor_specs; |
|
62
|
4
|
|
|
|
|
37
|
for my $k ( keys %$spec ) { |
|
63
|
11
|
100
|
100
|
|
|
275
|
confess "Required member $k not given to constructor" |
|
64
|
|
|
|
|
|
|
if $spec->{$k}->{required} |
|
65
|
|
|
|
|
|
|
and not exists $stuff->{$k}; |
|
66
|
10
|
100
|
100
|
|
|
225
|
confess "Member $k needs to be of type " . $spec->{$k}->{class} |
|
|
|
|
100
|
|
|
|
|
|
67
|
|
|
|
|
|
|
if exists $spec->{$k}->{class} |
|
68
|
|
|
|
|
|
|
and exists $stuff->{$k} |
|
69
|
|
|
|
|
|
|
and !UNIVERSAL::isa( $stuff->{$k}, $spec->{$k}->{class} ); |
|
70
|
|
|
|
|
|
|
} |
|
71
|
|
|
|
|
|
|
} |
|
72
|
2
|
|
|
|
|
14
|
return $self->SUPER::new($stuff); |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub set { |
|
76
|
3
|
50
|
|
3
|
1
|
1262
|
return shift->SUPER::set(@_) unless $_[0]->can("accessor_specs"); |
|
77
|
3
|
|
|
|
|
9
|
my ( $self, $key ) = splice( @_, 0, 2 ); |
|
78
|
3
|
|
|
|
|
11
|
my $spec = $self->accessor_specs; |
|
79
|
3
|
50
|
33
|
|
|
34
|
return $self->SUPER::set( $key, @_ ) |
|
80
|
|
|
|
|
|
|
if !exists $spec->{$key} |
|
81
|
|
|
|
|
|
|
or @_ > 1; # No support for arrays |
|
82
|
3
|
100
|
33
|
|
|
377
|
confess "Member $key needs to be of type " . $spec->{$key}->{class} |
|
|
|
|
66
|
|
|
|
|
|
83
|
|
|
|
|
|
|
if defined $_[0] |
|
84
|
|
|
|
|
|
|
and exists $spec->{$key}->{class} |
|
85
|
|
|
|
|
|
|
and !UNIVERSAL::isa( $_[0], $spec->{$key}->{class} ); |
|
86
|
|
|
|
|
|
|
|
|
87
|
1
|
50
|
33
|
|
|
9
|
$_[0] = [ $_[0] ] |
|
|
|
|
33
|
|
|
|
|
|
88
|
|
|
|
|
|
|
if defined $_[0] |
|
89
|
|
|
|
|
|
|
and $spec->{$key}->{array} |
|
90
|
|
|
|
|
|
|
and ref $_[0] ne 'ARRAY'; |
|
91
|
|
|
|
|
|
|
|
|
92
|
1
|
|
|
|
|
31
|
$self->{$key} = $_[0]; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub get { |
|
96
|
0
|
0
|
|
0
|
1
|
0
|
return shift->SUPER::get(@_) unless $_[0]->can("accessor_specs"); |
|
97
|
0
|
|
|
|
|
0
|
my ( $self, $key ) = splice( @_, 0, 2 ); |
|
98
|
0
|
|
|
|
|
0
|
my $spec = $self->accessor_specs; |
|
99
|
0
|
0
|
0
|
|
|
0
|
return $self->SUPER::get( $key, @_ ) |
|
100
|
|
|
|
|
|
|
if !exists $spec->{$key} |
|
101
|
|
|
|
|
|
|
or @_ > 1; # No support for arrays |
|
102
|
0
|
0
|
|
|
|
0
|
if ( $spec->{$key}{array} ) { |
|
103
|
|
|
|
|
|
|
wantarray |
|
104
|
0
|
0
|
|
|
|
0
|
? @{ $self->SUPER::get( $key, @_ ) || [] } |
|
|
0
|
0
|
|
|
|
0
|
|
|
105
|
|
|
|
|
|
|
: $self->SUPER::get( $key, @_ ); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
else { |
|
108
|
0
|
|
|
|
|
0
|
$self->SUPER::get( $key, @_ ); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub parse_fields { |
|
113
|
1
|
|
|
1
|
0
|
3
|
my ( $self, @fields ) = @_; |
|
114
|
1
|
|
|
|
|
1
|
my %spec; |
|
115
|
1
|
|
|
|
|
3
|
for my $f (@fields) { |
|
116
|
3
|
|
|
|
|
5
|
my $orig_f = $f; # For error reporting |
|
117
|
3
|
|
|
|
|
4
|
my %subspec; |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# All the tests go here |
|
120
|
3
|
|
|
|
|
9
|
$subspec{required} = $f =~ s/^\+//; |
|
121
|
3
|
100
|
|
|
|
19
|
$f =~ s/=(.*)// and $subspec{class} = $1; |
|
122
|
3
|
|
|
|
|
12
|
$subspec{array} = $f =~ s/^\@//; |
|
123
|
3
|
50
|
|
|
|
14
|
$f =~ /^\w+$/ |
|
124
|
|
|
|
|
|
|
or croak "Couldn't understand field specification $orig_f"; |
|
125
|
3
|
|
|
|
|
9
|
$spec{$f} = \%subspec; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
1
|
|
|
|
|
8
|
return %spec; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
1; |
|
131
|
|
|
|
|
|
|
__END__ |