File Coverage

lib/Config/NameValue.pm
Criterion Covered Total %
statement 71 94 75.5
branch 33 46 71.7
condition 14 27 51.8
subroutine 13 13 100.0
pod 6 6 100.0
total 137 186 73.6


line stmt bran cond sub pod time code
1             package Config::NameValue;
2              
3             # ABSTRACT: Round trip simple name/value config file handling.
4              
5             # VERSION
6              
7              
8 2     2   206913 use strict;
  2         4  
  2         70  
9 2     2   10 use warnings;
  2         4  
  2         49  
10 2     2   9491 use namespace::autoclean;
  2         48766  
  2         15  
11              
12 2     2   140 use Carp;
  2         5  
  2         149  
13 2     2   1151 use File::Slurp qw( slurp );
  2         25976  
  2         169  
14 2     2   18 use Scalar::Util qw( blessed );
  2         3  
  2         139  
15 2     2   12 use POSIX qw( strftime );
  2         3  
  2         26  
16              
17             our $VERSION = 1.00;
18              
19             { # Quick! Hide!
20              
21             my $error;
22              
23              
24             sub new {
25              
26 4     4 1 25807 my ( $class, $file ) = @_;
27              
28 4 100 66     73 croak 'Calling new as a function is not supported'
29             unless $class && $class ne '';
30              
31 3   33     22 my $self = bless {}, ref $class || $class;
32              
33 3 100 66     23 $self->load( $file )
34             if $file && $file ne '';
35              
36 3         21 return $self;
37              
38             }
39              
40              
41             sub load {
42              
43 5     5 1 19441 my ( $self, $file ) = @_;
44              
45 5 100       41 croak 'Calling load as a function is not supported'
46             unless blessed $self;
47              
48 4 100 66     31 if ( ! $file || $file eq '' ) {
49              
50             croak 'No file to load'
51 1 50 33     27 unless exists $self->{ file } && $self->{ file } ne '';
52              
53 0         0 $file = $self->{ file };
54              
55             }
56              
57 3         22 my @lines = slurp( $file, { chomp => 1 } );
58              
59 2         423 for ( my $i = 0 ; $i < @lines ; $i++ ) {
60              
61 18         30 my $line = $lines[ $i ];
62              
63 18 100       92 next if $line =~ /^\s*(#.*)?$/; # Ignore blank lines and comment lines
64 8         24 $line =~ s/(?
65              
66 8         51 $line =~ s/^\s*(.*?)\s*$/$1/; # Strip leading and trailing whitespace
67              
68 8         39 my @data = split /\s*=\s*/, $line, 2;
69 8         34 $data[ 0 ] =~ s/^\s*(.*)/$1/;
70 8         18 $data[ 1 ] =~ s/^(["'])(.*)\1$/$2/;
71 8         14 $data[ 1 ] =~ s/\\#/#/g;
72              
73 8         58 $self->{ name }{ $data[ 0 ] } = { value => $data[ 1 ], line => $i, modified => 0 };
74              
75             }
76              
77 2         6 $self->{ file } = $file;
78 2         33 $self->{ lines } = \@lines;
79 2         7 $self->{ count } = scalar @lines;
80 2         4 $self->{ modified } = 0;
81              
82 2         8 return 1;
83              
84             } ## end sub load
85              
86              
87             sub save {
88              
89 4     4 1 11301 my ( $self, $file ) = @_;
90              
91 4 100       33 croak 'Calling save as a function is not supported'
92             unless blessed $self;
93              
94 3 100 66     30 if ( ! $file || $file eq '' ) {
    100          
95              
96             croak 'No file to save'
97 1 50 33     18 unless exists $self->{ file } && $self->{ file } ne '';
98              
99 0         0 $file = $self->{ file };
100              
101             } elsif ( $file eq $self->{ file } ) {
102              
103             croak 'No changes, not saving'
104 1 50       22 unless $self->{ modified };
105              
106             }
107              
108 1 50       6 if ( $self->{ modified } ) {
109              
110 0         0 my @modified = grep { $self->{ name }{ $_ }{ modified } } keys %{ $self->{ name } };
  0         0  
  0         0  
111              
112 0         0 for my $name ( @modified ) {
113              
114 0         0 my ( $value, $line ) = @{ $self->{ name }{ $name } }{ qw( value line ) };
  0         0  
115 0         0 $self->{ lines }[ $line ] =~ s/^(\s*(["'])$name\2\s*=\s*)(["'])(?:.*)\3\s*$/$1$3$value$3/;
116              
117             }
118             }
119              
120 1         4 my $work_file = "$file.work";
121              
122 1         1435 require IO::Handle;
123              
124 1 50       10701 open my $FH, '>', $work_file
125             or croak "Unable to open $work_file: $!";
126              
127 1         3 print $FH "$_\n" for @{ $self->{ lines } };
  1         25  
128              
129 1 50       11 $FH->close
130             or carp "Unable to close $work_file: $!\n"; # How do I test this to satisfy Devel::Cover?
131              
132 1 50       163 rename $work_file, $file
133             or croak "Unable to rename $work_file to $file: $!";
134              
135             } ## end sub save
136              
137              
138             sub get {
139              
140 7     7 1 8048 my ( $self, $name ) = @_;
141              
142 7 100       57 croak 'Calling get as a function is not supported'
143             unless blessed $self;
144              
145             croak "Nothing loaded"
146 6 100 66     65 if ! exists $self->{ count } || $self->{ count } == 0;
147              
148 5 50       14 croak "Can't get nothing (no name passed)"
149             if $name eq '';
150              
151 1         3 do { $error = "$name does not exist"; return }
  1         7  
152 5 100       18 unless exists $self->{ name }{ $name };
153              
154 4         35 return $self->{ name }{ $name }{ value };
155              
156             } ## end sub get
157              
158              
159             sub set {
160              
161 2     2 1 1898 my ( $self, $name, $value ) = @_;
162              
163 2 100       23 croak 'Calling set as a function is not supported'
164             unless blessed $self;
165              
166             croak "Nothing loaded"
167 1 50 33     21 if ! exists $self->{ count } || $self->{ count } == 0;
168              
169 0 0       0 croak "Can't set nothing (no name passed)"
170             if $name eq '';
171              
172 0 0       0 if ( ! exists $self->{ name }{ $name } ) {
173              
174             # my $date = do {
175             #
176             # my @d = localtime( time );
177             # $d[5] += 1900;
178             # $d[4]++;
179             #
180             # join '-', @d[4,3,5];
181             #
182             # };
183              
184 0         0 $value =~ s/#/\\#/;
185              
186 0         0 my $comment = sprintf '# %s added by %s on %s', $name, __PACKAGE__, strftime( '%F', gmtime );
187              
188 0         0 push @{ $self->{ lines } }, $comment;
  0         0  
189 0         0 push @{ $self->{ lines } }, "$name=\"$value\"";
  0         0  
190              
191 0         0 $self->{ count }++;
192 0         0 $self->{ name }{ $name } = { value => $value, line => $self->{ count }++, modified => 0, };
193              
194             } else {
195              
196 0         0 @{ $self->{ name }{ $name } }{ qw( value modified ) } = ( $value, 1 );
  0         0  
197              
198             }
199              
200 0         0 $self->{ modified } = 1;
201              
202 0         0 return 1;
203              
204             } ## end sub set
205              
206              
207 5     5 1 20 sub error { $error }
208              
209             } # You can come out now!
210              
211             1;
212              
213             __END__