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