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__ |