File Coverage

blib/lib/Tie/File/Hashify.pm
Criterion Covered Total %
statement 74 81 91.3
branch 23 32 71.8
condition 17 24 70.8
subroutine 16 16 100.0
pod n/a
total 130 153 84.9


line stmt bran cond sub pod time code
1              
2             package Tie::File::Hashify;
3              
4 4     4   203456 use strict;
  4         10  
  4         164  
5 4     4   26 use warnings;
  4         9  
  4         128  
6              
7 4     4   25 use Carp;
  4         13  
  4         249  
8 4     4   24 use IO::File;
  4         8  
  4         5311  
9              
10             our $VERSION = '0.03';
11              
12              
13             sub TIEHASH {
14 6     6   2976 my ($class, $path, %options) = @_;
15              
16 6         52 my $self = bless {
17             hash => {},
18             format => $options{format},
19             parse => $options{parse},
20             path => $path,
21             ro => $options{ro},
22             dirty => 0,
23             }, $class;
24              
25 6 50 66     171 if($path and -e $path and $options{parse}) {
      66        
26 5 50       34 my $io = new IO::File($path) or croak "Can't read $path. $!.\n";
27              
28 5         543 while(my $line = $io->getline) {
29 24 50 33     1403 next unless defined $line and length($line);
30              
31 24         28 my ($key, $value);
32              
33             # Use callback for parsing.
34 24 100 66     117 if(ref($options{parse}) eq 'CODE') {
    50          
35 9         11 ($key, $value) = &{$options{parse}}($line);
  9         24  
36             }
37              
38             # Parse line using a regular expression.
39             elsif(ref($options{parse}) eq '' or uc(ref($options{parse})) eq 'REGEXP') {
40 15 100       80 my $re = ref($options{parse}) ? $options{parse} : qr/^$options{parse}$/;
41 15         93 ($key, $value) = ($line =~ $re);
42             }
43              
44             # Croak.
45             else {
46 0         0 croak 'Can\'t use ', lc(ref($options{parse})), " for parsing.\n";
47             }
48              
49 24 100 66     332 if(defined $key and length $key) {
50 16 50       447 $self->{hash}->{$key} = $value if(length $key);
51             }
52             }
53              
54 5         185 $io->close;
55             }
56              
57 6         98 return $self;
58             }
59              
60              
61             sub FETCH {
62 26     26   977 my ($self, $key) = @_;
63 26         140 return $self->{hash}->{$key};
64             }
65              
66              
67             sub STORE {
68 4     4   807 my ($self, $key, $value) = @_;
69              
70 4 100       202 croak "Can't store in read-only mode" if($self->{ro});
71              
72 3         8 $self->{dirty} = !0;
73              
74 3         15 return $self->{hash}->{$key} = $value;
75             }
76              
77              
78             sub EXISTS {
79 2     2   7 my ($self, $key) = @_;
80 2         9 return exists($self->{hash}->{$key});
81             }
82              
83              
84             sub DELETE {
85 2     2   797 my ($self, $key) = @_;
86              
87 2 100       129 croak "Can't delete in read-only mode" if($self->{ro});
88              
89 1         2 $self->{dirty} = !0;
90              
91 1         7 return delete($self->{hash}->{$key});
92             }
93              
94              
95             sub CLEAR {
96 1     1   1332 my ($self) = @_;
97              
98 1 50       135 croak "Can't clear in read-only mode" if($self->{ro});
99              
100 0         0 $self->{dirty} = !0;
101              
102 0         0 %{$self->{hash}} = ();
  0         0  
103             }
104              
105              
106             sub FIRSTKEY {
107 2     2   281 my ($self) = @_;
108 2         4 my ($key) = each %{$self->{hash}};
  2         6  
109 2         11 return $key;
110             }
111              
112              
113             sub NEXTKEY {
114 8     8   1036 my ($self) = @_;
115              
116 8         12 my ($k, $v) = each %{$self->{hash}};
  8         19  
117              
118 8         29 return $k;
119             }
120              
121              
122             sub SCALAR {
123 2     2   10 my ($self) = @_;
124              
125 2         6 my $format = $self->{format};
126              
127 2 50       13 if(defined $format) {
128 2         5 my $text = '';
129              
130 2         4 values %{$self->{hash}};
  2         7  
131              
132 2         4 while(my ($key, $value) = each %{$self->{hash}}) {
  7         54  
133             # Format using callback.
134 5 100       17 if(ref($format) eq 'CODE') {
    50          
135 4         5 $text .= &{$format}($key, $value) . "\n";
  4         12  
136             }
137              
138             # Format using sprintf and a format string.
139             elsif(ref($format) eq '') {
140 1         9 $text .= sprintf($format, $key, $value) . "\n";
141             }
142              
143             # Croak.
144             else {
145 0         0 croak 'Can\'t use ' . ref($format) . " as format.\n";
146             }
147             }
148              
149 2         12 return $text;
150             }
151              
152             else {
153 0         0 return %{$self->{hash}};
  0         0  
154             }
155             }
156              
157              
158             sub _store {
159 12     12   21 my ($self) = @_;
160              
161 12         26 my $path = $self->{path};
162              
163 12 100 100     547 if($path and $self->{dirty} and $self->{format} and !$self->{ro}) {
      100        
      66        
164 1 50       10 my $io = new IO::File('>' . $path) or croak "Can't write $path. $!.\n";
165              
166 1         186 $io->print($self->SCALAR);
167 1         17 $io->close;
168              
169 1         62 $self->{dirty} = 0;
170             }
171             }
172              
173              
174             sub UNTIE {
175 6     6   21 my ($self) = @_;
176              
177 6         24 $self->_store;
178             }
179              
180              
181             sub DESTROY {
182 6     6   541 my ($self) = @_;
183              
184 6         18 $self->_store;
185             }
186              
187              
188             !0;
189              
190             __END__