File Coverage

blib/lib/Class/props.pm
Criterion Covered Total %
statement 70 79 88.6
branch 40 50 80.0
condition 19 29 65.5
subroutine 14 14 100.0
pod 1 1 100.0
total 144 173 83.2


line stmt bran cond sub pod time code
1             package Class::props ;
2             $VERSION = 2.41 ;
3 9     9   523 use 5.006_001 ;
  9         23  
4 9     9   49 use strict ;
  9         15  
  9         187  
5            
6             # This file uses the "Perlish" coding style
7             # please read http://perl.4pro.net/perlish_coding_style.html
8              
9             ; use Carp
10 9     9   37 ; $Carp::Internal{+__PACKAGE__}++
  9         14  
  9         2497  
11              
12             ; sub import
13 15     15   111 { my $tool = shift
14 15         76 ; $tool->add_to(scalar caller, @_)
15             }
16              
17             ; sub add_to
18 15     15 1 34 { my ($tool, $pkg, @args) = @_
19 15         326 ; foreach my $prop ( @args )
20 43         82 { $prop = $tool->_init_prop_param( $prop )
21 43         69 ; $tool->_add_prop( $pkg, $prop )
22             }
23             }
24              
25             ; sub _init_prop_param
26 54     54   78 { my ( $tool, $prop ) = @_
27 54 100       115 ; $prop = { name => $prop }
28             unless ref $prop eq 'HASH'
29             ; $$prop{name} = [ $$prop{name} ]
30 54 100       125 unless ref $$prop{name} eq 'ARRAY'
31             ; $$prop{allowed} &&= [ $$prop{allowed} ]
32 54 50 50     150 unless ref $$prop{allowed} eq 'ARRAY'
33 54         92 ; $prop
34             }
35            
36             ; sub _add_prop
37 54     54   79 { my ( $tool, $pkg, $prop ) = @_
38             ; my $gr = delete $$prop{group}
39 54         82 ; my $to_tie = ( defined $$prop{default}
40             || defined $$prop{protected}
41             || defined $$prop{allowed}
42             || defined $$prop{validation}
43             || defined $$prop{post_process}
44             )
45 54   66     251 ; foreach my $n ( @{$$prop{name}} ) # foreach property
  54         60  
  54         81  
46 9         2345 { no strict 'refs'
47 9     9   77 ; *{$pkg.'::'.$n}
  9         16  
  64         3123  
48             = sub : lvalue
49 235 50   235   6531 { (@_ > 2) && croak qq(Too many arguments for "$n" property, died)
50             ; my $scalar
51             = $tool =~ /^Class/ ? $gr
52 22   66     83 ? \${(ref $_[0]||$_[0]).'::'.$gr}{$n}
53 52   66     215 : \${(ref $_[0]||$_[0]).'::'.$n}
54             : $tool =~ /^Package/ ? $gr
55 15         42 ? \${$pkg.'::'.$gr}{$n}
56 62         160 : \${$pkg.'::'.$n}
57             : $gr
58             ? \$_[0]{$gr}{$n}
59 235 100       811 : \$_[0]{$n}
    100          
    100          
    100          
    100          
60 235         294 ; my $Tscalar
61 235 100       324 ; if ( $to_tie )
62 168         464 { tie $$Tscalar
63             , 'Class::props::Tie'
64             , $_[0] # [0] object/class
65             , $n # [1] prop name
66             , $scalar # [2] lvalue ref
67             , $prop # [3] options ref
68             }
69             else
70 67         80 { $Tscalar = $scalar
71             }
72 235 100       762 ; @_ == 2
73             ? ( $$Tscalar = $_[1] )
74             : $$Tscalar
75             }
76 64         214 }
77             }
78              
79             ; package Class::props::Tie
80             ; use Carp
81 9     9   55 ; $Carp::Internal{+__PACKAGE__}++
  9         13  
  9         525  
82             ; use strict
83              
84 9     9   48 ; sub TIESCALAR
  9         11  
  9         4955  
85 168     168   480 { bless \@_, shift
86             }
87            
88             ; sub FETCH
89             { my $val = do
90 102 100   102   940 { if ( defined ${$_[0][2]} )
  102 50       103  
  102         259  
91 58         67 { ${$_[0][2]}
  58         109  
92             }
93             elsif ( defined $_[0][3]{default} )
94             { my $def = ref $_[0][3]{default} eq 'CODE'
95             ? $_[0][3]{default}( $_[0][0] )
96             : $_[0][3]{default}
97 44 100       126 ; $_[0][3]{no_strict}
98 44 50       139 ? ${$_[0][2]} = $def
  0         0  
99             : $_[0]->STORE( $def )
100             }
101             else
102             { undef
103 0         0 }
104             }
105 102         133 ; local $_ = $val
106             ; defined $_[0][3]{post_process}
107 102 100       330 ? $_[0][3]{post_process}( $_[0][0], $val )
108             : $val
109             }
110              
111             ; sub STORE
112 128   100 128   1057 { my $from_FETCH = (caller(1))[3]
113             && (caller(1))[3] =~ /::FETCH$/
114 128 100       309 ; my $default = $from_FETCH
115             ? 'default '
116             : ''
117 128 100 100     360 ; if ( $_[0][3]{protected} # if protected
      66        
118             &&! $from_FETCH # bypass for default
119             &&! $Class::props::force # bypass deliberately
120             )
121 18         26 { my ($OK, $f)
122 18         33 ; until ( $OK )
123 36 100       78 { last unless my $caller = caller($f++)
124 30         114 ; $OK = $caller->can($_[0][1])
125             }
126 18 100       559 ; $OK || croak qq("$_[0][1]" is a read-only property, died)
127             }
128 122 0 33     232 ; if ( $_[0][3]{allowed} # if restricted
      33        
129             &&! $from_FETCH # bypass for default
130             &&! $Class::props::force # bypass deliberately
131             )
132 0         0 { my ($OK, $f)
133 0         0 ; until ( $OK )
134 0 0       0 { last unless my $caller = (caller($f++))[3]
135 0         0 ; $OK = grep { $caller =~ qr/$_/ } @{$_[0][3]{allowed}}
  0         0  
  0         0  
136             }
137 0 0       0 ; $OK || croak qq("$_[0][1]" is a read-only property, died)
138             }
139 122         169 ; local $_ = $_[1]
140 122 100 66     298 ; if ( defined $_[0][3]{validation} # validation subref
141             && defined $_ # bypass for undef (reset to default)
142             )
143 41 100       97 { $_[0][3]{validation}( $_[0][0], $_)
144             || croak qq(Invalid ${default}value for "$_[0][1]" property, died)
145             }
146 116         242 ; ${$_[0][2]} = $_
  116         334  
147             }
148              
149             1 ;
150              
151             __END__