line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
3
|
|
|
3
|
|
1661
|
use v5.12.0; |
|
3
|
|
|
|
|
13
|
|
2
|
3
|
|
|
3
|
|
14
|
use warnings; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
131
|
|
3
|
|
|
|
|
|
|
package Config::INI::Reader 0.029; |
4
|
|
|
|
|
|
|
|
5
|
3
|
|
|
3
|
|
1064
|
use Mixin::Linewise::Readers 0.110; |
|
3
|
|
|
|
|
53410
|
|
|
3
|
|
|
|
|
14
|
|
6
|
|
|
|
|
|
|
# ABSTRACT: a subclassable .ini-file parser |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#pod =head1 SYNOPSIS |
9
|
|
|
|
|
|
|
#pod |
10
|
|
|
|
|
|
|
#pod If F contains: |
11
|
|
|
|
|
|
|
#pod |
12
|
|
|
|
|
|
|
#pod admin = rjbs |
13
|
|
|
|
|
|
|
#pod |
14
|
|
|
|
|
|
|
#pod [rjbs] |
15
|
|
|
|
|
|
|
#pod awesome = yes |
16
|
|
|
|
|
|
|
#pod height = 5' 10" |
17
|
|
|
|
|
|
|
#pod |
18
|
|
|
|
|
|
|
#pod [mj] |
19
|
|
|
|
|
|
|
#pod awesome = totally |
20
|
|
|
|
|
|
|
#pod height = 23" |
21
|
|
|
|
|
|
|
#pod |
22
|
|
|
|
|
|
|
#pod Then when your program contains: |
23
|
|
|
|
|
|
|
#pod |
24
|
|
|
|
|
|
|
#pod my $hash = Config::INI::Reader->read_file('family.ini'); |
25
|
|
|
|
|
|
|
#pod |
26
|
|
|
|
|
|
|
#pod C<$hash> will contain: |
27
|
|
|
|
|
|
|
#pod |
28
|
|
|
|
|
|
|
#pod { |
29
|
|
|
|
|
|
|
#pod '_' => { admin => 'rjbs' }, |
30
|
|
|
|
|
|
|
#pod rjbs => { |
31
|
|
|
|
|
|
|
#pod awesome => 'yes', |
32
|
|
|
|
|
|
|
#pod height => q{5' 10"}, |
33
|
|
|
|
|
|
|
#pod }, |
34
|
|
|
|
|
|
|
#pod mj => { |
35
|
|
|
|
|
|
|
#pod awesome => 'totally', |
36
|
|
|
|
|
|
|
#pod height => '23"', |
37
|
|
|
|
|
|
|
#pod }, |
38
|
|
|
|
|
|
|
#pod } |
39
|
|
|
|
|
|
|
#pod |
40
|
|
|
|
|
|
|
#pod =head1 DESCRIPTION |
41
|
|
|
|
|
|
|
#pod |
42
|
|
|
|
|
|
|
#pod Config::INI::Reader is I config module implementing I |
43
|
|
|
|
|
|
|
#pod slightly different take on the undeniably easy to read L<".ini" file |
44
|
|
|
|
|
|
|
#pod format|Config::INI>. Its default behavior is quite similar to that of |
45
|
|
|
|
|
|
|
#pod L, on which it is based. |
46
|
|
|
|
|
|
|
#pod |
47
|
|
|
|
|
|
|
#pod The chief difference is that Config::INI::Reader is designed to be subclassed |
48
|
|
|
|
|
|
|
#pod to allow for side-effects and self-reconfiguration to occur during the course |
49
|
|
|
|
|
|
|
#pod of reading its input. |
50
|
|
|
|
|
|
|
#pod |
51
|
|
|
|
|
|
|
#pod =cut |
52
|
|
|
|
|
|
|
|
53
|
3
|
|
|
3
|
|
1038
|
use Carp (); |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
2767
|
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
our @CARP_NOT = qw(Mixin::Linewise::Readers); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
#pod =head1 METHODS FOR READING CONFIG |
58
|
|
|
|
|
|
|
#pod |
59
|
|
|
|
|
|
|
#pod These methods are all that most users will need: they read configuration from a |
60
|
|
|
|
|
|
|
#pod source of input, then they return the data extracted from that input. There |
61
|
|
|
|
|
|
|
#pod are three reader methods, C, C, and C. |
62
|
|
|
|
|
|
|
#pod The first two are implemented in terms of the third. It iterates over lines in |
63
|
|
|
|
|
|
|
#pod a file, calling methods on the reader when events occur. Those events are |
64
|
|
|
|
|
|
|
#pod detailed below in the L section. |
65
|
|
|
|
|
|
|
#pod |
66
|
|
|
|
|
|
|
#pod All of the reader methods return an unblessed reference to a hash. |
67
|
|
|
|
|
|
|
#pod |
68
|
|
|
|
|
|
|
#pod All throw an exception when they encounter an error. |
69
|
|
|
|
|
|
|
#pod |
70
|
|
|
|
|
|
|
#pod =head2 read_file |
71
|
|
|
|
|
|
|
#pod |
72
|
|
|
|
|
|
|
#pod my $hash_ref = Config::INI::Reader->read_file($filename); |
73
|
|
|
|
|
|
|
#pod |
74
|
|
|
|
|
|
|
#pod Given a filename, this method returns a hashref of the contents of that file. |
75
|
|
|
|
|
|
|
#pod |
76
|
|
|
|
|
|
|
#pod =head2 read_string |
77
|
|
|
|
|
|
|
#pod |
78
|
|
|
|
|
|
|
#pod my $hash_ref = Config::INI::Reader->read_string($string); |
79
|
|
|
|
|
|
|
#pod |
80
|
|
|
|
|
|
|
#pod Given a string, this method returns a hashref of the contents of that string. |
81
|
|
|
|
|
|
|
#pod |
82
|
|
|
|
|
|
|
#pod =head2 read_handle |
83
|
|
|
|
|
|
|
#pod |
84
|
|
|
|
|
|
|
#pod my $hash_ref = Config::INI::Reader->read_handle($io_handle); |
85
|
|
|
|
|
|
|
#pod |
86
|
|
|
|
|
|
|
#pod Given an IO::Handle, this method returns a hashref of the contents of that |
87
|
|
|
|
|
|
|
#pod handle. |
88
|
|
|
|
|
|
|
#pod |
89
|
|
|
|
|
|
|
#pod =cut |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub read_handle { |
92
|
12
|
|
|
12
|
1
|
20457
|
my ($invocant, $handle) = @_; |
93
|
|
|
|
|
|
|
|
94
|
12
|
100
|
|
|
|
57
|
my $self = ref $invocant ? $invocant : $invocant->new; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# parse the file |
97
|
12
|
|
|
|
|
280
|
LINE: while (my $line = $handle->getline) { |
98
|
66
|
100
|
100
|
|
|
1492
|
if ($handle->input_line_number == 1 && $line =~ /\A\x{FEFF}/) { |
99
|
1
|
|
|
|
|
188
|
Carp::confess("input handle appears to start with a BOM"); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
65
|
|
|
|
|
1018
|
$self->preprocess_line(\$line); |
103
|
|
|
|
|
|
|
|
104
|
65
|
100
|
|
|
|
111
|
next LINE if $self->can_ignore($line, $handle); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# Handle section headers |
107
|
54
|
100
|
|
|
|
89
|
if (defined (my $name = $self->parse_section_header($line, $handle))) { |
108
|
|
|
|
|
|
|
# Create the sub-hash if it doesn't exist. |
109
|
|
|
|
|
|
|
# Without this sections without keys will not |
110
|
|
|
|
|
|
|
# appear at all in the completed struct. |
111
|
13
|
|
|
|
|
30
|
$self->change_section($name); |
112
|
13
|
|
|
|
|
191
|
next LINE; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
41
|
100
|
|
|
|
77
|
if (my ($name, $value) = $self->parse_value_assignment($line, $handle)) { |
116
|
39
|
|
|
|
|
85
|
$self->set_value($name, $value); |
117
|
39
|
|
|
|
|
593
|
next LINE; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
2
|
|
|
|
|
19
|
$self->handle_unparsed_line($line, $handle); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
9
|
|
|
|
|
221
|
$self->finalize; |
124
|
|
|
|
|
|
|
|
125
|
9
|
|
|
|
|
91
|
return $self->{data}; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#pod =head1 METHODS FOR SUBCLASSING |
129
|
|
|
|
|
|
|
#pod |
130
|
|
|
|
|
|
|
#pod These are the methods you need to understand and possibly change when |
131
|
|
|
|
|
|
|
#pod subclassing Config::INI::Reader to handle a different format of input. |
132
|
|
|
|
|
|
|
#pod |
133
|
|
|
|
|
|
|
#pod =head2 current_section |
134
|
|
|
|
|
|
|
#pod |
135
|
|
|
|
|
|
|
#pod my $section_name = $reader->current_section; |
136
|
|
|
|
|
|
|
#pod |
137
|
|
|
|
|
|
|
#pod This method returns the name of the current section. If no section has yet |
138
|
|
|
|
|
|
|
#pod been set, it returns the result of calling the C method. |
139
|
|
|
|
|
|
|
#pod |
140
|
|
|
|
|
|
|
#pod =cut |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub current_section { |
143
|
39
|
|
66
|
39
|
1
|
112
|
$_[0]->{section} // $_[0]->starting_section; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
#pod =head2 parse_section_header |
147
|
|
|
|
|
|
|
#pod |
148
|
|
|
|
|
|
|
#pod my $name = $reader->parse_section_header($line, $handle); |
149
|
|
|
|
|
|
|
#pod |
150
|
|
|
|
|
|
|
#pod Given a line of input, this method decides whether the line is a section-change |
151
|
|
|
|
|
|
|
#pod declaration. If it is, it returns the name of the section to which to change. |
152
|
|
|
|
|
|
|
#pod If the line is not a section-change, the method returns false. |
153
|
|
|
|
|
|
|
#pod |
154
|
|
|
|
|
|
|
#pod =cut |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub parse_section_header { |
157
|
54
|
100
|
|
54
|
1
|
162
|
return $1 if $_[1] =~ /^\s*\[\s*(.+?)\s*\]\s*$/; |
158
|
41
|
|
|
|
|
78
|
return; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
#pod =head2 change_section |
162
|
|
|
|
|
|
|
#pod |
163
|
|
|
|
|
|
|
#pod $reader->change_section($section_name); |
164
|
|
|
|
|
|
|
#pod |
165
|
|
|
|
|
|
|
#pod This method is called whenever a section change occurs in the file. |
166
|
|
|
|
|
|
|
#pod |
167
|
|
|
|
|
|
|
#pod The default implementation is to change the current section into which data is |
168
|
|
|
|
|
|
|
#pod being read and to initialize that section to an empty hashref. |
169
|
|
|
|
|
|
|
#pod |
170
|
|
|
|
|
|
|
#pod =cut |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub change_section { |
173
|
13
|
|
|
13
|
1
|
22
|
my ($self, $section) = @_; |
174
|
|
|
|
|
|
|
|
175
|
13
|
|
|
|
|
24
|
$self->{section} = $section; |
176
|
|
|
|
|
|
|
|
177
|
13
|
100
|
|
|
|
31
|
if (!exists $self->{data}{$section}) { |
178
|
11
|
|
|
|
|
24
|
$self->{data}{$section} = {}; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
#pod =head2 parse_value_assignment |
183
|
|
|
|
|
|
|
#pod |
184
|
|
|
|
|
|
|
#pod my ($name, $value) = $reader->parse_value_assignment($line, $handle); |
185
|
|
|
|
|
|
|
#pod |
186
|
|
|
|
|
|
|
#pod Given a line of input, this method decides whether the line is a property |
187
|
|
|
|
|
|
|
#pod value assignment. If it is, it returns the name of the property and the value |
188
|
|
|
|
|
|
|
#pod being assigned to it. If the line is not a property assignment, the method |
189
|
|
|
|
|
|
|
#pod returns false. |
190
|
|
|
|
|
|
|
#pod |
191
|
|
|
|
|
|
|
#pod =cut |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
sub parse_value_assignment { |
194
|
3
|
100
|
|
3
|
1
|
1579
|
return ($1, $2) if $_[1] =~ /^\s*([^=\s\pC][^=\pC]*?)\s*=\s*(.*?)\s*$/; |
|
3
|
|
|
41
|
|
38
|
|
|
3
|
|
|
|
|
38
|
|
|
41
|
|
|
|
|
254
|
|
195
|
2
|
|
|
|
|
6
|
return; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
#pod =head2 set_value |
199
|
|
|
|
|
|
|
#pod |
200
|
|
|
|
|
|
|
#pod $reader->set_value($name, $value); |
201
|
|
|
|
|
|
|
#pod |
202
|
|
|
|
|
|
|
#pod This method is called whenever an assignment occurs in the file. The default |
203
|
|
|
|
|
|
|
#pod behavior is to change the value of the named property to the given value. |
204
|
|
|
|
|
|
|
#pod |
205
|
|
|
|
|
|
|
#pod =cut |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub set_value { |
208
|
39
|
|
|
39
|
1
|
60
|
my ($self, $name, $value) = @_; |
209
|
|
|
|
|
|
|
|
210
|
39
|
|
|
|
|
72
|
$self->{data}{ $self->current_section }{$name} = $value; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
#pod =head2 starting_section |
214
|
|
|
|
|
|
|
#pod |
215
|
|
|
|
|
|
|
#pod my $section = Config::INI::Reader->starting_section; |
216
|
|
|
|
|
|
|
#pod |
217
|
|
|
|
|
|
|
#pod This method returns the name of the starting section. The default is: C<_> |
218
|
|
|
|
|
|
|
#pod |
219
|
|
|
|
|
|
|
#pod =cut |
220
|
|
|
|
|
|
|
|
221
|
12
|
|
|
12
|
1
|
43
|
sub starting_section { q{_} } |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
#pod =head2 can_ignore |
224
|
|
|
|
|
|
|
#pod |
225
|
|
|
|
|
|
|
#pod do_nothing if $reader->can_ignore($line, $handle) |
226
|
|
|
|
|
|
|
#pod |
227
|
|
|
|
|
|
|
#pod This method returns true if the given line of input is safe to ignore. The |
228
|
|
|
|
|
|
|
#pod default implementation ignores lines that contain only whitespace or comments. |
229
|
|
|
|
|
|
|
#pod |
230
|
|
|
|
|
|
|
#pod This is run I L. |
231
|
|
|
|
|
|
|
#pod |
232
|
|
|
|
|
|
|
#pod =cut |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
sub can_ignore { |
235
|
65
|
|
|
65
|
1
|
94
|
my ($self, $line, $handle) = @_; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# Skip comments and empty lines |
238
|
65
|
100
|
|
|
|
347
|
return $line =~ /\A\s*(?:;|$)/ ? 1 : 0; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
#pod =head2 preprocess_line |
242
|
|
|
|
|
|
|
#pod |
243
|
|
|
|
|
|
|
#pod $reader->preprocess_line(\$line); |
244
|
|
|
|
|
|
|
#pod |
245
|
|
|
|
|
|
|
#pod This method is called to preprocess each line after it's read but before it's |
246
|
|
|
|
|
|
|
#pod parsed. The default implementation just strips inline comments. Alterations |
247
|
|
|
|
|
|
|
#pod to the line are made in place. |
248
|
|
|
|
|
|
|
#pod |
249
|
|
|
|
|
|
|
#pod =cut |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub preprocess_line { |
252
|
65
|
|
|
65
|
1
|
90
|
my ($self, $line) = @_; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# Remove inline comments |
255
|
65
|
|
|
|
|
68
|
${$line} =~ s/\s+;.*$//g; |
|
65
|
|
|
|
|
121
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#pod =head2 handle_unparsed_line |
259
|
|
|
|
|
|
|
#pod |
260
|
|
|
|
|
|
|
#pod $reader->handle_unparsed_line( $line, $handle ); |
261
|
|
|
|
|
|
|
#pod |
262
|
|
|
|
|
|
|
#pod This method is called when the reader encounters a line that doesn't look like |
263
|
|
|
|
|
|
|
#pod anything it recognizes. By default, it throws an exception. |
264
|
|
|
|
|
|
|
#pod |
265
|
|
|
|
|
|
|
#pod =cut |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub handle_unparsed_line { |
268
|
2
|
|
|
2
|
1
|
6
|
my ($self, $line, $handle) = @_; |
269
|
2
|
|
|
|
|
5
|
my $lineno = $handle->input_line_number; |
270
|
2
|
|
|
|
|
219
|
Carp::croak "Syntax error at line $lineno: '$line'"; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
#pod =head2 finalize |
274
|
|
|
|
|
|
|
#pod |
275
|
|
|
|
|
|
|
#pod $reader->finalize; |
276
|
|
|
|
|
|
|
#pod |
277
|
|
|
|
|
|
|
#pod This method is called when the reader has finished reading in every line of the |
278
|
|
|
|
|
|
|
#pod file. |
279
|
|
|
|
|
|
|
#pod |
280
|
|
|
|
|
|
|
#pod =cut |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
9
|
1
|
|
sub finalize { } |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
#pod =head2 new |
285
|
|
|
|
|
|
|
#pod |
286
|
|
|
|
|
|
|
#pod my $reader = Config::INI::Reader->new; |
287
|
|
|
|
|
|
|
#pod |
288
|
|
|
|
|
|
|
#pod This method returns a new reader. This generally does not need to be called by |
289
|
|
|
|
|
|
|
#pod anything but the various C methods, which create a reader object only |
290
|
|
|
|
|
|
|
#pod ephemerally. |
291
|
|
|
|
|
|
|
#pod |
292
|
|
|
|
|
|
|
#pod =cut |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub new { |
295
|
12
|
|
|
12
|
1
|
1312
|
my ($class) = @_; |
296
|
|
|
|
|
|
|
|
297
|
12
|
|
|
|
|
27
|
my $self = { data => {}, }; |
298
|
|
|
|
|
|
|
|
299
|
12
|
|
|
|
|
89
|
bless $self => $class; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
#pod =head1 ORIGIN |
303
|
|
|
|
|
|
|
#pod |
304
|
|
|
|
|
|
|
#pod Originaly derived from L, by Adam Kennedy. |
305
|
|
|
|
|
|
|
#pod |
306
|
|
|
|
|
|
|
#pod =cut |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
1; |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
__END__ |