File Coverage

lib/Config/Parser/Ini.pm
Criterion Covered Total %
statement 50 67 74.6
branch 13 26 50.0
condition 5 8 62.5
subroutine 7 8 87.5
pod 2 2 100.0
total 77 111 69.3


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