File Coverage

blib/lib/Config/Dot.pm
Criterion Covered Total %
statement 82 82 100.0
branch 20 20 100.0
condition 6 6 100.0
subroutine 14 14 100.0
pod 4 4 100.0
total 126 126 100.0


line stmt bran cond sub pod time code
1             package Config::Dot;
2              
3 6     6   58500 use strict;
  6         31  
  6         137  
4 6     6   26 use warnings;
  6         6  
  6         133  
5              
6 6     6   2319 use Class::Utils qw(set_params);
  6         136795  
  6         83  
7 6     6   2556 use Config::Utils qw(hash);
  6         4190  
  6         80  
8 6     6   326 use English qw(-no_match_vars);
  6         11  
  6         22  
9 6     6   1584 use Error::Pure qw(err);
  6         11  
  6         177  
10 6     6   26 use Readonly;
  6         22  
  6         4783  
11              
12             # Constants.
13             Readonly::Scalar my $EMPTY_STR => q{};
14              
15             our $VERSION = 0.09;
16              
17             # Constructor.
18             sub new {
19 16     16 1 8129 my ($class, @params) = @_;
20 16         35 my $self = bless {}, $class;
21              
22             # Callback.
23 16         38 $self->{'callback'} = undef;
24              
25             # Config hash.
26 16         27 $self->{'config'} = {};
27              
28             # Set conflicts detection as error.
29 16         25 $self->{'set_conflicts'} = 1;
30              
31             # Process params.
32 16         45 set_params($self, @params);
33              
34             # Check config hash.
35 14 100       179 if (! $self->_check($self->{'config'})) {
36 2         5 err 'Bad \'config\' parameter.';
37             }
38              
39             # Check callback.
40 12 100 100     59 if (defined $self->{'callback'} && ref $self->{'callback'} ne 'CODE') {
41 1         4 err 'Parameter \'callback\' isn\'t code reference.';
42             }
43              
44             # Count of lines.
45 11         61 $self->{'count'} = 0;
46              
47             # Stack.
48 11         19 $self->{'stack'} = [];
49              
50             # Object.
51 11         41 return $self;
52             }
53              
54             # Parse text or array of texts.
55             sub parse {
56 8     8 1 299 my ($self, $string_or_array_ref) = @_;
57 8         11 my @text;
58 8 100       18 if (ref $string_or_array_ref eq 'ARRAY') {
59 2         2 @text = @{$string_or_array_ref};
  2         5  
60             } else {
61 6         46 @text = split m/$INPUT_RECORD_SEPARATOR/sm,
62             $string_or_array_ref;
63             }
64 8         16 foreach my $line (@text) {
65 15         19 $self->{'count'}++;
66 15         28 $self->_parse($line);
67             }
68 6         17 return $self->{'config'};
69             }
70              
71             # Reset content.
72             sub reset {
73 4     4 1 3578 my $self = shift;
74 4         9 $self->{'config'} = {};
75 4         6 $self->{'count'} = 0;
76 4         7 return;
77             }
78              
79             # Serialize.
80             sub serialize {
81 5     5 1 19 my $self = shift;
82             return join $INPUT_RECORD_SEPARATOR,
83 5         11 $self->_serialize($self->{'config'});
84             }
85              
86             # Check structure.
87             sub _check {
88 17     17   28 my ($self, $config_hr) = @_;
89 17 100       43 if (ref $config_hr eq 'HASH') {
90 15         18 foreach my $key (sort keys %{$config_hr}) {
  15         44  
91 9 100 100     42 if (ref $config_hr->{$key} ne ''
92             && ! $self->_check($config_hr->{$key})) {
93              
94 1         3 return 0;
95             }
96             }
97 14         40 return 1;
98             } else {
99 2         6 return 0;
100             }
101             }
102              
103             # Parse string.
104             sub _parse {
105 15     15   19 my ($self, $string) = @_;
106              
107             # Remove comments on single line.
108 15         26 $string =~ s/^\s*#.*$//sm;
109              
110             # Blank space.
111 15 100       47 if ($string =~ m/^\s*$/sm) {
112 2         3 return 0;
113             }
114              
115             # Split.
116 13         32 my ($key, $val) = split m/=/sm, $string, 2;
117              
118             # Not a key.
119 13 100       25 if (length $key < 1) {
120 1         10 return 0;
121             }
122              
123             # Bad key.
124 12 100       51 if ($key !~ m/^[-\w\.:,]+\+?$/sm) {
125 1         8 err "Bad key '$key' in string '$string' at line ".
126             "'$self->{'count'}'.";
127             }
128              
129 11         22 my @tmp = split m/\./sm, $key;
130 11         32 hash($self, \@tmp, $val);
131              
132             # Ok.
133 10         226 return 1;
134             }
135              
136             # Serialize.
137             sub _serialize {
138 6     6   12 my ($self, $config_hr) = @_;
139 6         8 my @ret;
140 6         7 foreach my $key (sort keys %{$config_hr}) {
  6         13  
141 5 100       11 if (ref $config_hr->{$key} eq 'HASH') {
142 1         5 my @subkey = $self->_serialize($config_hr->{$key});
143 1         3 foreach my $subkey (@subkey) {
144 1         2 push @ret, $key.'.'.$subkey;
145             }
146             } else {
147 4 100       13 if ($config_hr->{$key} =~ m/\n/ms) {
148 1         5 err 'Unsupported stay with newline in value.';
149             }
150 3         10 push @ret, $key.'='.$config_hr->{$key};
151             }
152             }
153 5         22 return @ret;
154             }
155              
156             1;
157              
158             __END__