File Coverage

blib/lib/Config/Dot/Array.pm
Criterion Covered Total %
statement 92 92 100.0
branch 26 26 100.0
condition 9 9 100.0
subroutine 14 14 100.0
pod 4 4 100.0
total 145 145 100.0


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