File Coverage

blib/lib/Tie/ConfigFile.pm
Criterion Covered Total %
statement 56 77 72.7
branch 12 20 60.0
condition 6 9 66.6
subroutine 13 18 72.2
pod n/a
total 87 124 70.1


line stmt bran cond sub pod time code
1             #
2             # Copyright (C) 2014 by Tomasz Konojacki
3             #
4             # This library is free software; you can redistribute it and/or modify
5             # it under the same terms as Perl itself, either Perl version 5.18.2 or,
6             # at your option, any later version of Perl 5 you may have available.
7             #
8              
9             package Tie::ConfigFile;
10              
11 1     1   61447 use strict;
  1         3  
  1         36  
12 1     1   5 use warnings;
  1         2  
  1         33  
13              
14 1     1   912 use IO::File;
  1         1045  
  1         144  
15 1     1   6 use Carp;
  1         2  
  1         993  
16              
17             our $VERSION = '0.02';
18              
19             sub __error {
20 1     1   3 my($self, $err) = @_;
21              
22 1 50       217 croak $err if $self->{die_on_error};
23              
24             return
25 0         0 }
26              
27             sub __init {
28 3     3   6 my $self = shift;
29              
30 3 100       38 $self->{_fh} = IO::File->new(
    50          
    50          
31             $self->{filename},
32             ($self->{readonly} ? O_RDONLY : O_RDWR) |
33             ($self->{create_file} ? O_CREAT : 0)
34             ) or return __error($self, 'Unable to open file');
35              
36             # we utf-8, baby
37 3         325 $self->{_fh}->binmode(':utf8');
38              
39 3         48 return 1;
40             }
41              
42             sub __read {
43 3     3   5 my $self = shift;
44              
45             # __init will be launched only if there is no filehandle in $self->{_fh},
46             # if __init fails we return undef
47 3 50 33     27 return unless defined($self->{_fh}) || $self->__init;
48              
49 3         8 my $s = $self->{separator};
50              
51 3         134 while (defined(my $line = $self->{_fh}->getline)) {
52 6         247 chomp $line;
53              
54 6         97 my($r_key, $r_value) = split /\s*$s\s*/, $line, 2;
55              
56 6         181 $self->{_cache}->{$r_key} = $r_value;
57             }
58              
59             return
60 3         291 }
61              
62             sub __write {
63 3     3   5 my $self = shift;
64              
65             # clear the file before we write to it.
66 3         26 $self->{_fh}->truncate(0);
67 3         194 $self->{_fh}->seek(0, 0);
68              
69 3         29 for (keys %{$self->{_cache}}) {
  3         15  
70 6         47 $self->{_fh}->print($_ , $self->{separator},
71             $self->{_cache}->{$_}, "\n")
72             }
73              
74             # Due to flushing, writes are reliable even if user forgets to untie hash.
75 3         138 $self->{_fh}->flush;
76              
77 3         7 return;
78             }
79              
80             sub TIEHASH {
81 3     3   1158 my($class, %args) = @_;
82              
83 3         29 my $self = {
84             filename => undef,
85             die_on_error => 1,
86             readonly => 1,
87             create_file => 0,
88             empty_is_undef => 1,
89             separator => '=',
90             %args
91             };
92              
93 3 50       15 unless (defined $self->{filename}) {
94 0         0 return __error($self, 'Filename is not specified!');
95             }
96              
97 3         8 bless $self, $class;
98              
99 3         12 $self->__read;
100              
101 3         27 return $self;
102             }
103              
104             sub FETCH {
105 9     9   36 my($self, $key) = @_;
106              
107 9         22 my $val = $self->{_cache}->{$key};
108              
109 9 100 66     75 return if defined($val) && ($val eq '') && $self->{empty_is_undef};
      100        
110 7         33 return $val;
111             }
112              
113             sub STORE {
114 4     4   240 my($self, $key, $value) = @_;
115              
116 4 100       18 if ($self->{readonly}) {
117 1         5 return $self->__error('STORE is not allowed on read-only config file')
118             }
119              
120 3         13 $self->{_cache}->{$key} = $value;
121              
122 3         11 $self->__write;
123              
124 3         160 return;
125             }
126              
127             sub DELETE {
128 0     0   0 my($self, $key) = @_;
129              
130 0 0       0 if ($self->{readonly}) {
131 0         0 return $self->__error('DELETE is not allowed on read-only config file')
132             }
133              
134 0         0 delete $self->{_cache}->{$key};
135              
136 0         0 $self->__write;
137              
138 0         0 return;
139             }
140              
141             sub CLEAR {
142 0     0   0 my $self = shift;
143              
144 0         0 %{$self->{_cache}} = ();
  0         0  
145 0         0 $self->__write;
146              
147 0         0 return;
148             }
149              
150             sub EXISTS {
151 0     0   0 my($self, $key) = @_;
152              
153             # Empty keys have '' value, so if value is undefined, key doesn't exist.
154 0         0 return defined $self->{_cache}->{$key};
155             }
156              
157             sub FIRSTKEY {
158 0     0   0 my $self = shift;
159              
160 0         0 return (each %{$self->{_cache}})
  0         0  
161             }
162              
163             sub NEXTKEY {
164 0     0   0 my $self = shift;
165              
166 0         0 return (each %{$self->{_cache}})
  0         0  
167             }
168              
169             sub UNTIE {
170 3     3   455 my($self, $count) = @_;
171              
172 3 50       9 carp "untie attempted while $count inner references still exist" if $count;
173              
174             return
175 3         13 }
176              
177             sub DESTROY {
178 3     3   7 my $self = shift;
179              
180 3         18 $self->{_fh}->close;
181              
182             return
183 3         83 }
184              
185             'AKZ18/295-200P';
186              
187             __END__