File Coverage

blib/lib/ctflags/memory.pm
Criterion Covered Total %
statement 34 77 44.1
branch 4 16 25.0
condition 3 5 60.0
subroutine 8 15 53.3
pod 0 10 0.0
total 49 123 39.8


line stmt bran cond sub pod time code
1             package ctflags::memory;
2              
3             our $VERSION = '0.01';
4              
5 1     1   13 use 5.006;
  1         3  
  1         31  
6 1     1   4 use strict;
  1         2  
  1         29  
7 1     1   4 use warnings;
  1         1  
  1         73  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12              
13             # this package is supposed to be private to ctflags and companion
14             # packages, not used from any other module so it uses directly
15             # @EXPORT. Anyway, the function names used are not going to cause
16             # too many namespace pollution problems.
17             our @EXPORT = qw( set_ctflag
18             get_ctflag
19             restrict_ctflags
20             allowed_ctflags
21             is_ctflag_allowed
22             set_ctflag_alias
23             resolve_ctflag_alias
24             set_ctflag_call
25             get_ctflag_call );
26              
27              
28 1     1   432 use ctflags::check;
  1         3  
  1         1122  
29              
30             my %memory;
31             my %meta;
32             my %alias;
33             my %call;
34              
35             # In most of ctflags subrutines, argument checking is done indirectly
36             # when subrutines here, in ctflags::memory are called, and so all of
37             # the public subrutines here implement checks for the validity of its
38             # arguments.
39             #
40             # Only helper functions which name begins with an underscore, like
41             # '_is_allowed' bellow, are exent from these checks and their use is
42             # discouraged outside this module
43              
44              
45             # checks that the use of a flag has not been forbided inside a
46             # namespace or dies.
47              
48             sub _is_allowed ($$) {
49 21     21   30 my ($ns, $flag)=@_;
50 21 50 33     77 !exists $meta{$ns.':restricted'}
51             or index($meta{$ns.':restricted'}, $flag)>=0
52             or die "ctflag '$flag' is not allowed in namespace '$ns'\n";
53             }
54              
55              
56             # public interface for _is_allowed. Just checks for the validity of
57             # its arguments
58              
59             sub is_ctflag_allowed ($$) {
60 0     0 0 0 check_ns $_[0];
61 0         0 check_flag $_[1];
62 0         0 &_is_allowed
63             }
64              
65              
66             # change value of ctflag
67              
68             sub set_ctflag ($$$ ) {
69 4     4 0 6 my ($ns, $flag, $value)=@_;
70 4         12 check_ns $ns;
71 4         10 check_flag $flag;
72 4         21 check_value $value;
73 4         10 _is_allowed $ns, $flag;
74 4         17 $memory{$ns.':'.$flag}=int($value);
75             }
76              
77              
78             # retrieve value of ctflag
79              
80             sub get_ctflag ($$) {
81 17     17 0 28 my ($ns, $flagext)=@_;
82 17         54 check_ns $ns;
83 17         65 my ($flag, $default)=$flagext=~/($flag_re)($value_re)?/o;
84 17         39 check_flag $flag;
85 17         37 check_value $default;
86 17         28 _is_allowed $ns, $flag;
87 17         28 my $m=$memory{$ns.":".$flag};
88 17 100 100     78 int(defined $m ? $m : ($default || 0));
89             }
90              
91             sub extend_flagsetext ($$) {
92 0     0 0 0 my ($fse, $ns)=@_;
93 0         0 check_ns($ns);
94 0         0 check_flagsetext($fse);
95              
96 0 0       0 if ($fse eq '*') {
97 0         0 return join ('', allowed_ctflags($ns))
98             }
99              
100 0 0       0 if ($fse=~/^!(.*)/) {
101 0         0 my $inv=$1;
102 0         0 return join('',
103 0         0 (grep {index($inv, $_)<0 } allowed_ctflags($ns)));
104             }
105              
106 0         0 return $fse;
107             }
108              
109             # restrict which ctflags are allowed inside a namepace
110              
111              
112             sub restrict_ctflags ($$) {
113 0     0 0 0 my $ns=shift;
114 0         0 check_ns $ns;
115 0         0 my $flagset=extend_flagsetext(shift, $ns);
116 0         0 $meta{$ns.':restricted'}=$flagset;
117             }
118              
119              
120             # returns an array with the allowed ctflags inside a namespace
121              
122             sub allowed_ctflags ($ ) {
123 0     0 0 0 my $ns=shift;
124 0         0 check_ns $ns;
125 0 0       0 return split('', $meta{$ns.':restricted'})
126             if (exists $meta{$ns.':restricted'});
127 0         0 return ('a'..'z','A'..'Z')
128             }
129              
130              
131             # creates an alias (long name composed of more than one letter) for a
132             # ctflag
133              
134             sub set_ctflag_alias ($$$ ) {
135 0     0 0 0 my ($ns, $alias, $flag)=@_;
136 0         0 check_alias $alias;
137 0         0 check_ns $ns;
138 0 0       0 unless (defined $flag) {
139 0         0 delete $alias{$ns.':'.$alias};
140             return
141 0         0 }
142 0         0 check_flag $flag;
143 0         0 _is_allowed $ns, $flag;
144 0         0 $alias{$ns.':'.$alias}=$flag;
145             }
146              
147              
148             # returns the value of an aliased ctflag from its alias name
149              
150             sub resolve_ctflag_alias ($$) {
151 0     0 0 0 my ($ns, $alias)=@_;
152 0         0 check_ns $ns;
153 0         0 check_alias $alias;
154 0 0       0 exists $alias{$ns.':'.$alias}
155             or die "ctflag alias '$alias' not defined in namespace '$ns'\n";
156 0         0 return get_ctflag($ns, $alias{$ns.':'.$alias});
157             }
158              
159             sub set_ctflag_call ($$$) {
160 0     0 0 0 my ($ns, $flagsetext, $sub)=@_;
161 0         0 check_ns $ns;
162 0         0 my $flags=extend_flagsetext($flagsetext, $ns);
163 0         0 check_sub $sub;
164 0         0 foreach my $f (split //, $flags) {
165 0         0 _is_allowed $ns, $f;
166 0         0 $call{$ns.':'.$f}=$sub;
167             }
168             }
169              
170             sub get_ctflag_call ($$) {
171 6     6 0 10 my ($ns, $flag) =@_;
172 6         13 check_ns($ns);
173 6         15 check_flag($flag);
174 6         10 my $n=$ns.':'.$flag;
175 6 50       12 if (exists $call{$n}) {
176 0         0 return $call{$n};
177             }
178 6         13 return undef;
179             }
180              
181             1;
182             __END__