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