File Coverage

blib/lib/bitflag/ct.pm
Criterion Covered Total %
statement 69 101 68.3
branch 32 58 55.1
condition 0 3 0.0
subroutine 10 16 62.5
pod 0 5 0.0
total 111 183 60.6


line stmt bran cond sub pod time code
1             package bitflag::ct;
2            
3 1     1   46644 use 5.008007;
  1         3  
  1         33  
4 1     1   4 use strict;
  1         2  
  1         22  
5 1     1   3 use warnings;
  1         6  
  1         90  
6            
7             require Exporter;
8            
9             our @ISA = qw(Exporter);
10            
11             our @EXPORT_OK = qw ( getmask );
12             our @EXPORT = qw( );
13             our $VERSION = 0.01;
14            
15 1     1   5 no strict 'refs';
  1         2  
  1         1059  
16            
17             my %pkgDefaultHandle;
18             my ($caller);
19            
20             sub inithandle # constructor
21             {
22 2     2 0 3 my $class = shift;
23 2         4 my $option = takeHASH(shift);
24 2 50       5 $option->{sm} = delete $option->{startmask} if exists $option->{startmask};
25 2 100       5 $option->{sm} = 1 unless exists $option->{sm};
26 2         8 bless { option=>$option, flagmap => {}}, $class;
27             }
28            
29             {
30             sub takeHASH
31             {
32 8     8 0 10 my $v = shift;
33 8 50       31 ref($v) eq 'HASH' ? $v : ref($v) eq 'ARRAY' ? {@$v} : undef;
    100          
34             }
35            
36             sub casealias
37             {
38             {
39 54     54   161 'uc' => sub {uc $_[0]},
40 0     0   0 'ucfirst' => sub {ucfirst $_[0]},
41 0     0   0 'lc' => sub {lc $_[0]},
42             }
43 4     4 0 77 }
44             }
45            
46             sub import
47             {
48 6     6   1140 my $class = shift;
49 6         11 $caller = caller; # i.e. = caller[0]
50 6         12 my $option = takeHASH ($_[0]);
51            
52 6 100       18 if ( defined $option )
53             {
54 3         4 shift;
55             # for compatibility wrt. "package bitflag"
56 3 100       7 if ( $option->{ic} ) { $option->{alias} = 'uc' }
  2         7  
57 3 100       8 if ( exists $option->{alias} )
58             {
59 2 50       4 if (exists casealias->{$option->{alias}} )
    0          
60             {
61 2         4 $option->{alias} = casealias->{$option->{alias}}
62             }
63             elsif (defined $option->{alias})
64             {
65 0 0       0 die sprintf('$option->{alias}=%s must be a CODE',$option->{alias})
66             unless ref($option->{alias}) eq 'CODE';
67             }
68             }
69             }
70            
71            
72 2         7 *{$caller.'::getmask'} = \&{$class.'::getmask'}
  2         5  
  6         26  
73 6 100       17 unless defined *{$caller.'::getmask'};
74            
75 6         6 my $handle;
76             my $handle_isnew; # = 0;
77            
78 6 50       12 if ( exists $option->{handle} )
79             {
80 0         0 my $refhandle= delete $option->{handle};
81             # die "handle=>$refhandle must be a ref\n" unless ref($refhandle);
82            
83 0 0       0 if
    0          
84             (
85 0         0 $handle_isnew =
86             ref($refhandle)? ref($$refhandle) ne $class : !defined(*{$caller.'::'.$refhandle})
87             )
88             {
89             # create and call import with handle
90            
91 0 0 0     0 if ( $option->{default} && exists $pkgDefaultHandle{$caller} )
92             {
93 0         0 delete $option->{default};
94 0         0 $option = {%{$pkgDefaultHandle{$caller}{option}},@$option}
  0         0  
95             }
96            
97             # create new $handle by constructor
98 0         0 $handle = $class->inithandle($option);
99            
100 0 0       0 if (ref($refhandle))
101             {
102             # usage case : handle => \$variable_for_handle
103 0         0 $$refhandle = $handle;
104             }
105             else
106             {
107             # usage case : handle => 'symbolname_for_handle'
108 0     0   0 *{$caller.'::'.$refhandle} = sub () {$handle};
  0         0  
  0         0  
109             }
110             }
111             else
112             {
113             # recall import with already created handle
114            
115 0 0       0 if (ref($refhandle))
116             {
117             # usage case : handle => \$variable_for_handle
118 0         0 $handle = $$refhandle;
119             }
120             else
121             {
122             # usage case : handle => 'symbolname_for_handle'
123 0         0 $handle = &{$caller.'::'.$refhandle};
  0         0  
124             }
125             }
126             }
127             else
128             {
129 6 100       17 if ($handle_isnew = !(exists $pkgDefaultHandle{$caller}))
130             {
131 2         5 $handle = $class->inithandle($option);
132 2         5 $pkgDefaultHandle{$caller} = $handle;
133            
134             }
135             else
136             {
137 4         8 $handle = $pkgDefaultHandle{$caller};
138             }
139             }
140            
141 6 100       10 unless ($handle_isnew)
142             {
143             # @{$handle->{option}}{keys %$option} = values %$option;
144             # but as 'sm' is the only key to be considered ..
145 4 100       9 if ( exists $option->{sm} )
146             {
147 1         3 $handle->{option}{sm} = $option->{sm};
148             }
149 4         6 $option = $handle->{option};
150             }
151            
152 6 50       54 return unless @_;
153 6 100       39 my $mask = ($_[0] =~ qr{\A\d+\Z}) ? shift : $option->{sm};
154 6         18 my $alias = $handle->{option}{alias};
155            
156 6         10 foreach my $flagname (@_)
157             {
158 22 50       22 if ( exists ${$caller.'::'}{$flagname} )
  22         63  
159             {
160 0         0 my $elsecode = \&{$caller.'::'.$flagname};
  0         0  
161 0         0 undef *{$caller.'::'.$flagname};
  0         0  
162 0         0 delete ${$caller.'::'}{$flagname};
  0         0  
163 0         0 *{$caller.'::'.$flagname} =
164             sub
165             {
166 0     0   0 my ($context) = @_;
167 0 0       0 $context==$handle ? $mask : $elsecode->(@_);
168 0         0 };
169            
170             # print "\$mask=$mask\t\$elsecode=$elsecode =run=> ".&$elsecode."\n";
171             }
172             else
173             {
174 22     0   57 *{$caller.'::'.$flagname} = sub {$mask};
  22         92  
  0         0  
175             }
176 22 50       56 $handle->{flagmap}{defined $alias ? $alias->($flagname) : $flagname} = $mask;
177 22         35 $mask <<= 1
178             }
179            
180 6         227 $handle->{option}{sm} = $mask;
181             }
182            
183             sub getmask
184             {
185 13     13 0 5345 my $cand = shift;
186 13 50       38 my $handle = ref($cand) ? $cand : $pkgDefaultHandle{$cand};
187 13 50       31 die 'getmask needs a preceding "use bitflag::ct"' unless defined $handle;
188 13         14 undef $cand;
189 13         30 my $option= $handle->{option};
190 13         15 my $r = 0;
191 13         37 my $alias= $option->{alias};
192 13 50       48 my $nameslist = defined $alias ? [map $alias->($_),@_] : \@_;
193 13         64 foreach my $v (@$nameslist)
194             {
195 32 100       111 if ( exists $handle->{flagmap}{$v} )
196             {
197 30         62 $r |= $handle->{flagmap}{$v}
198             }
199             else
200             {
201 2         25 warn "unknown flagname: $v\n";
202             }
203             }
204             $r
205 13         46 }
206            
207             sub pkghandle
208             {
209 0     0 0   $pkgDefaultHandle{$_[1]}
210             }
211            
212             1;
213             __END__