File Coverage

blib/lib/Tie/Hash/ReadonlyStack.pm
Criterion Covered Total %
statement 80 102 78.4
branch 32 44 72.7
condition 8 12 66.6
subroutine 14 17 82.3
pod 6 6 100.0
total 140 181 77.3


line stmt bran cond sub pod time code
1             package Tie::Hash::ReadonlyStack;
2              
3             # use warnings;
4 2     2   57622 use strict;
  2         4  
  2         2518  
5              
6             $Tie::Hash::ReadonlyStack::VERSION = '0.2';
7              
8             sub clear_compiled_cache {
9 6     6 1 17 my ( $self, @keys ) = @_;
10            
11 6 100       19 if (@keys) {
12 4         5 my $count = 0;
13 4         5 for my $k (@keys) {
14 7 100       18 if (exists $self->{'compiled'}{$k}) {
15 4 50       13 delete $self->{'compiled'}{$k} if exists $self->{'compiled'}{$k};
16 4         6 $count++;
17             }
18             }
19 4 100       15 return $count if $count;
20 1         4 return;
21             }
22             else {
23 2         4 %{ $self->{'compiled'} } = ();
  2         6  
24 2         7 return 1;
25             }
26             }
27              
28             sub add_lookup_override_hash_without_clearing_cache {
29 5     5 1 9 my ( $self, $name, $hr ) = @_;
30            
31 5 100       32 return if $name eq 'readonly_hash';
32 4 100       23 return if exists $self->{'hashes'}{$name};
33              
34 2         3 unshift @{ $self->{'order'} }, $name;
  2         6  
35 2         9 $self->{'hashes'}{$name} = $hr;
36             }
37              
38             sub add_lookup_override_hash {
39 3     3 1 8 my ( $self, $name, $hr ) = @_;
40            
41 3 50       3 if ( !tied(%{$hr}) ) {
  3         16  
42 3         3 $self->clear_compiled_cache(keys %{$hr});
  3         11  
43             }
44             else {
45 0         0 for my $key ( keys %{ $self->{'compiled'} } ) {
  0         0  
46 0 0       0 if ( exists $self->{'compiled'}{$key} ) {
47 0         0 delete $self->{'compiled'}{$key};
48             }
49             }
50             }
51            
52 3         8 return $self->add_lookup_override_hash_without_clearing_cache($name, $hr);
53             }
54              
55             sub add_lookup_fallback_hash {
56 3     3 1 7 my ( $self, $name, $hr ) = @_;
57 3 100       13 return if $name eq 'readonly_hash';
58 2 100       10 return if exists $self->{'hashes'}{$name};
59              
60 1         1 push @{ $self->{'order'} }, $name;
  1         3  
61 1         4 $self->{'hashes'}{$name} = $hr;
62             }
63              
64             sub del_lookup_hash {
65 5     5 1 10 my ( $self, $name, $only_if_exists ) = @_;
66 5 100       18 return if $name eq 'readonly_hash';
67 4 100 66     16 return if $only_if_exists && !exists $self->{'hashes'}{$name};
68              
69 3         8 delete $self->{'hashes'}{$name};
70 3         8 @{ $self->{'order'} } = grep { $_ ne $name } @{ $self->{'order'} };
  3         10  
  6         16  
  3         7  
71 3         4 for my $key ( keys %{ $self->{'compiled'} } ) {
  3         9  
72 5 100 66     37 if ( exists $self->{'compiled'}{$key}{'found_in'} && $self->{'compiled'}{$key}{'found_in'} eq $name ) {
73 1         4 delete $self->{'compiled'}{$key};
74             }
75             }
76 3         28 return 1;
77             }
78              
79             sub get_keys_not_in_stack {
80 2     2 1 3 my ($self) = @_;
81              
82 2 100       3 return map { !exists $self->{'compiled'}{$_}{'found_in'} ? $_ : () } keys %{ $self->{'compiled'} };
  3         23  
  2         7  
83             }
84              
85             sub TIEHASH {
86 1     1   185 my ( $class, $mainhash ) = @_;
87 1         9 return bless {
88             'compiled' => {},
89             'hashes' => { 'readonly_hash' => $mainhash },
90             'order' => ['readonly_hash']
91             }, $class;
92             }
93              
94             # tied to a read only handle (gdbm) or one you do not want updated (DBI) ?
95             sub STORE {
96 4     4   12 my ( $self, $key, $val ) = @_;
97 4         19 $self->{'compiled'}{$key}{'value'} = $val;
98             }
99              
100             sub DELETE {
101 2     2   3 my ( $self, $key ) = @_;
102 2 50       7 return if !exists $self->{'compiled'}{$key};
103              
104 2         4 my $val = $self->{'compiled'}{$key}{'value'};
105              
106 2         5 delete $self->{'compiled'}{$key};
107 2         7 return $val;
108             }
109              
110             sub CLEAR {
111 0     0   0 my ($self) = @_;
112 0         0 delete $self->{'compiled'};
113              
114 0         0 for my $hash_name ( @{ $self->{'order'} } ) {
  0         0  
115 0 0       0 next if $hash_name eq 'readonly_hash';
116 0 0       0 untie $self->{'hashes'}{$hash_name} if tied( $self->{'hashes'}{$hash_name} );
117 0         0 delete $self->{'hashes'}{$hash_name};
118             }
119             }
120              
121             sub EXISTS {
122 5     5   15 my ( $self, $key ) = @_;
123              
124 5 100 66     26 return 1 if exists $self->{'compiled'}{$key} && exists $self->{'compiled'}{$key}{'value'};
125              
126 4         6 for my $hash_name ( @{ $self->{'order'} } ) {
  4         8  
127 4 50       16 return 1 if exists $self->{'hashes'}{$hash_name}{$key};
128             }
129              
130 4         17 return;
131             }
132              
133             sub FETCH {
134 20     20   40 my ( $self, $key ) = @_;
135              
136 20 100 66     724 return $self->{'compiled'}{$key}{'value'} if exists $self->{'compiled'}{$key} && exists $self->{'compiled'}{$key}{'value'};
137              
138 8         10 for my $hash_name ( @{ $self->{'order'} } ) {
  8         16  
139 11 100       29 if ( exists $self->{'hashes'}{$hash_name}{$key} ) {
140 8         21 $self->{'compiled'}{$key}{'found_in'} = $hash_name;
141 8         19 $self->{'compiled'}{$key}{'value'} = $self->{'hashes'}{$hash_name}{$key};
142 8         36 return $self->{'compiled'}{$key}{'value'};
143             }
144             }
145              
146 0         0 return;
147             }
148              
149             sub SCALAR {
150 0     0   0 return scalar %{ shift->{'compiled'} };
  0         0  
151             }
152              
153             sub FIRSTKEY {
154 2     2   2 my $self = shift;
155 2         3 my $c = keys %{ $self->{'compiled'} }; # reset each() iterator
  2         5  
156 2         2 each %{ $self->{'compiled'} };
  2         9  
157             }
158              
159             sub NEXTKEY {
160 3     3   4 return each %{ shift->{'compiled'} };
  3         17  
161             }
162              
163             sub UNTIE {
164 0     0     my $self = shift;
165 0           delete $self->{'compiled'};
166 0           for my $hash_name ( @{ $self->{'order'} } ) {
  0            
167 0 0         untie $self->{'hashes'}{$hash_name} if tied( $self->{'hashes'}{$hash_name} );
168 0           delete $self->{'hashes'}{$hash_name};
169             }
170 0           delete $self->{'order'};
171 0           delete $self->{'hashes'};
172             }
173              
174             # sub DESTROY {
175             # my $self = shift;
176             # }
177              
178             1;