File Coverage

lib/Config/Parser/Ini.pm
Criterion Covered Total %
statement 51 68 75.0
branch 14 28 50.0
condition 5 8 62.5
subroutine 7 8 87.5
pod 2 2 100.0
total 79 114 69.3


line stmt bran cond sub pod time code
1             package Config::Parser::Ini;
2 10     10   339820 use strict;
  10         67  
  10         351  
3 10     10   61 use warnings;
  10         15  
  10         325  
4 10     10   63 use parent 'Config::Parser';
  10         20  
  10         67  
5 10     10   443 use Carp;
  10         14  
  10         568  
6 10     10   56 use Text::ParseWords;
  10         18  
  10         7369  
7            
8             sub parse {
9 20     20 1 454 my $self = shift;
10 20   33     76 $self->{_filename} = shift // confess "No filename given";
11 20         118 local %_ = @_;
12 20         168 $self->debug(1, "parsing $self->{_filename}");
13 20         218 $self->_readconfig($self->{_filename}, %_);
14 20         78 return $self;
15             }
16              
17 0     0 1 0 sub filename { shift->{_filename} }
18            
19             # _readconfig(FILE)
20             sub _readconfig {
21 20     20   31 my $self = shift;
22 20         30 my $file = shift;
23 20         43 local %_ = @_;
24 20         38 my $fh = delete $_{fh};
25 20         29 my $need_close;
26              
27 20         75 $self->debug(1, "reading file $file");
28 20 100       133 unless ($fh) {
29             open($fh, "<", $file)
30 9 50       320 or do {
31 0         0 $self->error("can't open configuration file $file: $!");
32 0         0 $self->{_error_count}++;
33 0         0 return 0;
34             };
35 9         31 $need_close = 1;
36             }
37            
38 20   100     94 my $line = delete $_{line} // 0;
39 20         39 my @path;
40             my $include;
41            
42 20         267 while (<$fh>) {
43 135         28315 ++$line;
44 135         188 chomp;
45 135 50       332 if (/\\$/) {
46 0         0 chop;
47 0         0 $_ .= <$fh>;
48 0         0 redo;
49             }
50              
51 135         564 s/^\s+//;
52 135         360 s/\s+$//;
53 135         182 s/#.*//;
54 135 100       310 next if ($_ eq "");
55            
56 116         375 my $locus = new Text::Locus($file, $line);
57            
58 116 100       3553 if (/^\[(.+?)\]$/) {
    50          
59 37         114 @path = parse_line('\s+', 0, $1);
60 37 50 66     2715 if (@path == 1 && $path[0] eq 'include') {
61 0         0 $include = 1;
62             } else {
63 37         61 $include = 0;
64 37         220 $self->add_node(\@path,
65             new Config::AST::Node::Section(locus => $locus));
66             }
67             } elsif (/([\w_-]+)\s*=\s*(.*)/) {
68 79         261 my ($k, $v) = ($1, $2);
69 79 50       176 $k = lc($k) if $self->{_ci}; #FIXME:private member
70            
71 79 50       123 if ($include) {
72 0 0       0 if ($k eq 'path') {
    0          
    0          
73 0         0 $self->_readconfig($v);
74             } elsif ($k eq 'pathopt') {
75 0 0       0 $self->_readconfig($v) if -f $v;
76             } elsif ($k eq 'glob') {
77 0         0 foreach my $file (bsd_glob($v, 0)) {
78 0         0 $self->_readconfig($file);
79             }
80             } else {
81 0         0 $self->error("keyword \"$k\" is unknown", locus => $locus);
82 0         0 $self->{_error_count}++;
83             }
84             } else {
85 79         290 $self->add_value([@path, $k], $v, $locus);
86             }
87             } else {
88 0         0 $self->error("malformed line", locus => $locus);
89 0         0 $self->{_error_count}++;
90             }
91             }
92 20 100       4270 close $fh if $need_close;
93             }
94              
95             1;
96              
97             =head1 NAME
98              
99             Config::Parser::Ini - configuration file parser for ini-style files
100              
101             =head1 SYNOPSIS
102              
103             $cfg = new Config::Parser::Ini($filename);
104              
105             $val = $cfg->get('dir', 'tmp');
106              
107             print $val->value;
108              
109             print $val->locus;
110              
111             $val = $cfg->tree->Dir->Tmp;
112              
113             =head1 DESCRIPTION
114              
115             An I is a textual file consisting of settings
116             grouped into one or more sections. A I has the form
117              
118             KEYWORD = VALUE
119              
120             where I is the setting name and I is its value.
121             Syntactically, I is anything to the right of the equals sign and up
122             to the linefeed character terminating the line (ASCII 10), not including
123             the leading and trailing whitespace characters.
124              
125             Each setting occupies one line. Very long lines can be split over several
126             physical lines by ending each line fragment except the last with a backslash
127             character appearing right before the linefeed character.
128              
129             A I
begins with a section declaration in the following form:
130              
131             [NAME NAME...]
132              
133             Here, square brackets form part of the syntax. Any number of Is
134             can be present inside the square brackets. The first I must follow the
135             usual rules for a valid identifier name. Rest of Is can contain any
136             characters, provided that any I that includes non-alphanumeric characters
137             is enclosed in a pair of double-quotes. Any double-quotes and backslash
138             characters appearing within the quoted string must be escaped by prefixing
139             them with a single backslash.
140              
141             The B module is a framework for parsing such files.
142              
143             In the simplest case, the usage of this module is as simple as in the following
144             fragment:
145              
146             use Config::Parser::Ini;
147             my $cf = new Config::Parser::Ini(filename => "config.ini");
148              
149             On success, this returns a valid B object. On error,
150             the diagnostic message is issued using the B method (see the description
151             of the method in B(3)) and the module croaks.
152              
153             This usage, although simple, has one major drawback - no checking is performed
154             on the input file, except for the syntax check. To fix this, you can supply
155             a dictionary (or I) of allowed keywords along with their values.
156             Such a dictionary is itself a valid ini file, where the value of each
157             keyword describes its properties. The dictionary is placed in the B<__DATA__>
158             section of the source file which invokes the B constructor.
159              
160             Expanding the example above:
161              
162             use Config::Parser::Ini;
163             my $cf = new Config::Parser::Ini(filename => "config.ini");
164              
165             __DATA__
166             [core]
167             root = STRING :default /
168             umask = OCTAL
169             [user]
170             uid = NUMBER
171             gid = NUMBER
172              
173             This code specifies that the configuration file can contain at most two
174             sections: C<[core]> and C<[user]>. Two keywords are defined within each
175             section. Data types are specified for each keyword, so the parser will
176             bail out in case of type mismatches. If the B setting is not
177             present in the configuration, the default one will be created with the
178             value C.
179              
180             It is often advisable to create a subclass of B and
181             use it for parsing. For instance:
182              
183             package App::MyConf;
184             use Config::Parser::Ini;
185             1;
186             __DATA__
187             [core]
188             root = STRING :default /
189             umask = OCTAL
190             [user]
191             uid = NUMBER
192             gid = NUMBER
193              
194             Then, to parse the configuration file, it will suffice to do:
195              
196             $cf = my App::MyConf(filename => "config.ini");
197              
198             One advantage of this approach is that it will allow you to install
199             additional validation for the configuration statements using the
200             B<:check> option. The argument to this option is the name of a
201             method which will be invoked after parsing the statement in order
202             to verify its value. It is described in detail below (see the section
203             B in the documentation of B).
204             For example, if you wish to ensure that the value of the C setting
205             in C section points to an existing directory, you would do:
206              
207             package App::MyConf;
208             use Config::Parser::Ini;
209              
210             sub dir_exists {
211             my ($self, $valref, $prev_value, $locus) = @_;
212              
213             unless (-d $$valref) {
214             $self->error("$$valref: directory does not exist",
215             locus => $locus);
216             return 0;
217             }
218             return 1;
219             }
220             1;
221             __DATA__
222             [core]
223             root = STRING :default / :check=dir_exists
224             umask = OCTAL
225             [user]
226             uid = NUMBER
227             gid = NUMBER
228              
229             =head1 CONSTRUCTOR
230              
231             $cfg = new Config::Parser::Ini(%opts)
232              
233             Creates a new parser object. Keyword arguments are:
234              
235             =over 4
236              
237             =item B
238              
239             Name of the file to parse. If not supplied, you will have to
240             call the B<$cfg-Eparse> method explicitly after you are returned a
241             valid B<$cfg>.
242              
243             =item B
244              
245             Optional line where the configuration starts in B. It is used to
246             keep track of statement location in the file for correct diagnostics. If
247             not supplied, B<1> is assumed.
248              
249             =item B
250              
251             File handle to read from. If it is not supplied, new handle will be
252             created by using B on the supplied filename.
253              
254             =item B
255              
256             Dictionary of allowed configuration statements in the file. You will not
257             need this parameter. It is listed here for completeness sake. Refer to
258             the B constructor for details.
259              
260             =back
261              
262             =head1 METHODS
263              
264             All methods are inherited from B. Please see its
265             documentation for details.
266              
267             =head1 SEE ALSO
268              
269             B(3), B(3).
270              
271             =cut