diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-08-23 14:43:52 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2019-08-23 14:45:35 +0300 |
commit | d69ba51bb8498146d07a08031de3685e6cda0768 (patch) | |
tree | e67c2e6903544dc007422fa616481c8984446da0 | |
parent | 21cbaaf979d12447c56382d353d7f03853f49907 (diff) | |
download | config-parser-d69ba51bb8498146d07a08031de3685e6cda0768.tar.gz config-parser-d69ba51bb8498146d07a08031de3685e6cda0768.tar.bz2 |
Implement BOOLEAN data type.v1.03
-rw-r--r-- | Changes | 3 | ||||
-rw-r--r-- | lib/Config/Parser.pm | 58 | ||||
-rw-r--r-- | t/ConfigSpec.pm | 1 | ||||
-rw-r--r-- | t/conf00.t | 3 | ||||
-rw-r--r-- | t/conf09.t | 8 |
5 files changed, 63 insertions, 10 deletions
@@ -1,5 +1,8 @@ | |||
1 | Revision history for Perl extension Config::Parser | 1 | Revision history for Perl extension Config::Parser |
2 | 2 | ||
3 | 1.03 Fri Aug 23 14:44:18 2019 | ||
4 | - implement the BOOLEAN data type | ||
5 | |||
3 | 1.02 Thu Aug 22 09:47:42 2019 | 6 | 1.02 Thu Aug 22 09:47:42 2019 |
4 | - use mro to track descendant classes | 7 | - use mro to track descendant classes |
5 | 8 | ||
diff --git a/lib/Config/Parser.pm b/lib/Config/Parser.pm index 0c771ed..bd230b5 100644 --- a/lib/Config/Parser.pm +++ b/lib/Config/Parser.pm | |||
@@ -7,7 +7,7 @@ use Cwd qw(abs_path); | |||
7 | use Text::ParseWords; | 7 | use Text::ParseWords; |
8 | use mro; | 8 | use mro; |
9 | 9 | ||
10 | our $VERSION = "1.02"; | 10 | our $VERSION = "1.03"; |
11 | 11 | ||
12 | sub new { | 12 | sub new { |
13 | my $class = shift; | 13 | my $class = shift; |
@@ -112,6 +112,8 @@ sub loadsynt { | |||
112 | $ret->{re} = '^[0-7]+$'; | 112 | $ret->{re} = '^[0-7]+$'; |
113 | } elsif ($val eq 'HEX') { | 113 | } elsif ($val eq 'HEX') { |
114 | $ret->{re} = '^([0-9][A-Fa-f])+$'; | 114 | $ret->{re} = '^([0-9][A-Fa-f])+$'; |
115 | } elsif ($val =~ /^BOOL(EAN)?$/) { | ||
116 | $ret->{check} = \&check_bool; | ||
115 | } else { | 117 | } else { |
116 | unshift @words, $val; | 118 | unshift @words, $val; |
117 | } | 119 | } |
@@ -142,6 +144,29 @@ sub loadsynt { | |||
142 | return $lex; | 144 | return $lex; |
143 | } | 145 | } |
144 | 146 | ||
147 | sub check_bool { | ||
148 | my ($self, $valref, undef, $locus) = @_; | ||
149 | my %bv = ( | ||
150 | yes => 1, | ||
151 | no => 0, | ||
152 | true => 1, | ||
153 | false => 0, | ||
154 | on => 1, | ||
155 | off => 0, | ||
156 | t => 1, | ||
157 | nil => 0, | ||
158 | 1 => 1, | ||
159 | 0 => 0 | ||
160 | ); | ||
161 | |||
162 | if (exists($bv{$$valref})) { | ||
163 | $$valref = $bv{$$valref}; | ||
164 | return 1; | ||
165 | } | ||
166 | $self->error("$$valref is not a valid boolean value", locus => $locus); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
145 | 1; | 170 | 1; |
146 | 171 | ||
147 | =head1 NAME | 172 | =head1 NAME |
@@ -202,7 +227,7 @@ This call first parses the B<__DATA__> section and builds validation rules, | |||
202 | then it parses the actual configuration from B<$filename>. Finally, it | 227 | then it parses the actual configuration from B<$filename>. Finally, it |
203 | applies the validation rules to the created syntax tree. If all rules pass, | 228 | applies the validation rules to the created syntax tree. If all rules pass, |
204 | the configuration is correct and the constructor returns a valid object. | 229 | the configuration is correct and the constructor returns a valid object. |
205 | Otherwise, it issues proper diagnostics and returns B<undef>. | 230 | Otherwise, it issues proper diagnostics and croaks. |
206 | 231 | ||
207 | Upon successful return, the B<$cf> object is used to obtain the actual | 232 | Upon successful return, the B<$cf> object is used to obtain the actual |
208 | configuration values as needed. | 233 | configuration values as needed. |
@@ -229,9 +254,12 @@ Creates a new parser object. Keyword arguments are: | |||
229 | 254 | ||
230 | =item B<filename> | 255 | =item B<filename> |
231 | 256 | ||
232 | Name of the file to parse. If not supplied, you will have to | 257 | Name of the file to parse. If supplied, the constructor will call |
233 | call the B<$cfg-E<gt>parse> method explicitly after you are returned a | 258 | the B<parse> and B<commit> methods automatically and will croak if |
234 | valid B<$cfg>. | 259 | the latter returns false. The B<parse> method is given B<filename>, |
260 | B<line> and B<fh> keyword-value pairs (if present) as its arguments. | ||
261 | |||
262 | If not supplied, the caller is supposed to call both methods later. | ||
235 | 263 | ||
236 | =item B<line> | 264 | =item B<line> |
237 | 265 | ||
@@ -239,11 +267,15 @@ Optional line where the configuration starts in B<filename>. It is used to | |||
239 | keep track of statement location in the file for correct diagnostics. If | 267 | keep track of statement location in the file for correct diagnostics. If |
240 | not supplied, B<1> is assumed. | 268 | not supplied, B<1> is assumed. |
241 | 269 | ||
270 | Valid only together with B<filename>. | ||
271 | |||
242 | =item B<fh> | 272 | =item B<fh> |
243 | 273 | ||
244 | File handle to read from. If it is not supplied, new handle will be | 274 | File handle to read from. If it is not supplied, new handle will be |
245 | created by using B<open> on the supplied filename. | 275 | created by using B<open> on the supplied filename. |
246 | 276 | ||
277 | Valid only together with B<filename>. | ||
278 | |||
247 | =item B<lexicon> | 279 | =item B<lexicon> |
248 | 280 | ||
249 | Dictionary of allowed configuration statements in the file. You will not | 281 | Dictionary of allowed configuration statements in the file. You will not |
@@ -329,6 +361,12 @@ Octal number. | |||
329 | 361 | ||
330 | Hex number. | 362 | Hex number. |
331 | 363 | ||
364 | =item B<BOOL> or B<BOOLEAN> | ||
365 | |||
366 | Boolean value. Allowed values are: | ||
367 | B<yes>, B<true>, B<on>, B<t>, B<1>, for C<true> and | ||
368 | B<no>, B<false>, B<off>, B<nil>, B<0>, for C<false>. | ||
369 | |||
332 | =back | 370 | =back |
333 | 371 | ||
334 | If the data type is omitted, no checking is performed unless specified | 372 | If the data type is omitted, no checking is performed unless specified |
@@ -404,6 +442,16 @@ To specify options for a section, use the reserved keyword B<__options__>. | |||
404 | Its value is the list of options as described above. After processing, the | 442 | Its value is the list of options as described above. After processing, the |
405 | keyword itself is removed from the lexicon. | 443 | keyword itself is removed from the lexicon. |
406 | 444 | ||
445 | =head1 OTHER METHODS | ||
446 | |||
447 | =head2 $cfg->check($valref, $prev, $locus) | ||
448 | |||
449 | This method implements syntax checking and translation for C<BOOLEAN> data | ||
450 | types. If B<$$valref> is one of the valid boolean values (as described | ||
451 | above), it translates it to B<1> or B<0>, stores that value in B<$valref>, | ||
452 | and returns 1. Otherwise, it emits error message using B<$cfg->error> and | ||
453 | returns 0. | ||
454 | |||
407 | =head1 SEE ALSO | 455 | =head1 SEE ALSO |
408 | 456 | ||
409 | B<Config::AST>(3). | 457 | B<Config::AST>(3). |
diff --git a/t/ConfigSpec.pm b/t/ConfigSpec.pm index 30812ed..b94c1df 100644 --- a/t/ConfigSpec.pm +++ b/t/ConfigSpec.pm | |||
@@ -16,6 +16,7 @@ __DATA__ | |||
16 | base = STRING :mandatory null | 16 | base = STRING :mandatory null |
17 | number = NUMBER :array | 17 | number = NUMBER :array |
18 | size = STRING :re='\d+(?:(?i) *[kmg])' | 18 | size = STRING :re='\d+(?:(?i) *[kmg])' |
19 | enable = BOOL | ||
19 | [load] | 20 | [load] |
20 | file = STRING :check=_check_abs_name :mandatory | 21 | file = STRING :check=_check_abs_name :mandatory |
21 | ANY = STRING | 22 | ANY = STRING |
@@ -8,7 +8,7 @@ plan(tests => 1); | |||
8 | 8 | ||
9 | my $c = new ConfigSpec; | 9 | my $c = new ConfigSpec; |
10 | ok($c->canonical, | 10 | ok($c->canonical, |
11 | q{core.base=4 core.number=[5,10] core.size="10 k" load.file="/etc/passwd" load.foobar="baz"}); | 11 | q{core.base=4 core.enable=1 core.number=[5,10] core.size="10 k" load.file="/etc/passwd" load.foobar="baz"}); |
12 | 12 | ||
13 | __DATA__ | 13 | __DATA__ |
14 | [core] | 14 | [core] |
@@ -16,6 +16,7 @@ __DATA__ | |||
16 | base = 4 | 16 | base = 4 |
17 | size = 10 k | 17 | size = 10 k |
18 | number = 10 | 18 | number = 10 |
19 | enable = true | ||
19 | [load] | 20 | [load] |
20 | file = /etc/passwd | 21 | file = /etc/passwd |
21 | foobar = baz | 22 | foobar = baz |
@@ -2,16 +2,16 @@ | |||
2 | use lib qw(t lib); | 2 | use lib qw(t lib); |
3 | use strict; | 3 | use strict; |
4 | use Test; | 4 | use Test; |
5 | use ConfigSpec; | 5 | use ConfigSpec2; |
6 | use ConfigSpec3; | 6 | use ConfigSpec3; |
7 | 7 | ||
8 | plan(tests => 2); | 8 | plan(tests => 2); |
9 | 9 | ||
10 | my $c = new ConfigSpec; | 10 | my $c2 = new ConfigSpec2; |
11 | my $c3 = new ConfigSpec3; | 11 | my $c3 = new ConfigSpec3; |
12 | 12 | ||
13 | ok($c->canonical_lexicon, | 13 | ok($c2->canonical_lexicon, |
14 | q{{"core" => {"section" => {"base" => {"default" => "null","mandatory" => 1},"number" => {"array" => 1,"re" => "^\\\\d+\\$"},"size" => {"re" => "\\\\d+(?:(?i) *[kmg])"}}},"load" => {"section" => {"*" => {},"file" => {"check" => "_check_abs_name","mandatory" => 1}}}}}); | 14 | q{{"core" => {"section" => {"base" => {"default" => "null","mandatory" => 1}}},"load" => {"section" => {"*" => {"section" => {"param" => {"mandatory" => 1,"section" => {"mode" => {"re" => "^[0-7]+\$"},"owner" => {}}}}}}}}}); |
15 | 15 | ||
16 | ok($c3->canonical_lexicon, | 16 | ok($c3->canonical_lexicon, |
17 | q{{"core" => {"section" => {"root" => {"mandatory" => 1}}},"dir" => {"section" => {"diag" => {},"store" => {},"temp" => {}}}}}); | 17 | q{{"core" => {"section" => {"root" => {"mandatory" => 1}}},"dir" => {"section" => {"diag" => {},"store" => {},"temp" => {}}}}}); |