line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Hash::Mogrify; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
26244
|
use 5.006; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
41
|
|
4
|
1
|
|
|
1
|
|
7
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
97
|
|
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
75
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Hash::Mogrify - Perl extension for modifying hashes |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 SYNOPSIS |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
use Hash::Mogrify qw(kmap vmap hmap); |
14
|
|
|
|
|
|
|
# or :all |
15
|
|
|
|
|
|
|
or |
16
|
|
|
|
|
|
|
use Hash::Mogrify qw(kmap vmap hmap :force :nowarning :dieonerror); |
17
|
|
|
|
|
|
|
# to set global bitmaps |
18
|
|
|
|
|
|
|
or |
19
|
|
|
|
|
|
|
use Hash::Mogrify qw(:all :const); |
20
|
|
|
|
|
|
|
# also get constants for setting local bitmaps. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my %hash = ( foo => 'bar', |
23
|
|
|
|
|
|
|
quuz => 'quux', |
24
|
|
|
|
|
|
|
bla => 'bulb',); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my %newhash = kmap { $_ =~ s/foo/food/ } %hash; |
27
|
|
|
|
|
|
|
my $newhashref = vmap { $_ =~ s/bulb/burp/ } %hash; |
28
|
|
|
|
|
|
|
my $samehashref = hmap { $_[0] =~ s/foo/food/; $_[1] =~ s/bulb/burp/ } \%hash; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
## setting local bitmaps |
31
|
|
|
|
|
|
|
my %newhash = kmap { $_ =~ s/foo/food/ } %hash, NOWARNING | FORCE; |
32
|
|
|
|
|
|
|
# to enable nowarning and force for this action. |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
kmap { $_ =~ s/foo/food/ } \%hash, DIEONERR |
35
|
|
|
|
|
|
|
# to let kmap die on error. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
ktrans { foo => 'food' }, \%hash; |
38
|
|
|
|
|
|
|
# Change key foo into key food. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 DESCRIPTION |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Hash::Mogrify contains functions for changes parts of hashes, change/mogrify it's keys or it's values. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
The functions are flexible in design. |
45
|
|
|
|
|
|
|
The functions kmap, vmap and hmap return a hash/list in list context and a hash-reference in scalar context. |
46
|
|
|
|
|
|
|
The first argument to these functions is a code block to mogrify the hash, the second either a hash or a hashref. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
If a hash(list) is provided as an argument a new hash is created. When a hash-reference (e.a \%hash) is provided the original hash is changed. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
The function ktrans works similar to kmap, except that it takes a hashref as translation table instead of a codeblock. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
By default no function overwrites existing keys and warns about this when trying. |
53
|
|
|
|
|
|
|
this can be changed by setting the global or local bitmap. |
54
|
|
|
|
|
|
|
The global bitmap can be set on load by the following keys: |
55
|
|
|
|
|
|
|
:nowarning # do not warn about errors |
56
|
|
|
|
|
|
|
:dieonerror # die incase you're trying to override an existing key |
57
|
|
|
|
|
|
|
:force # override existing keys (overrrides :dieonerror). |
58
|
|
|
|
|
|
|
The local bitmap can be set by adding to the end of the function, there are the following constants: |
59
|
|
|
|
|
|
|
NOWARNING |
60
|
|
|
|
|
|
|
FORCE |
61
|
|
|
|
|
|
|
DIEONERR |
62
|
|
|
|
|
|
|
The local bitmap will completely override the global bitmap. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
More options might be provided in later versions. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=head2 EXPORT |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
None by default. |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
71
|
|
|
|
|
|
|
|
72
|
1
|
|
|
1
|
|
5
|
use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION $GLOBALMAP); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1245
|
|
73
|
|
|
|
|
|
|
require Exporter; |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
78
|
|
|
|
|
|
|
'all' => [ qw( |
79
|
|
|
|
|
|
|
hmap |
80
|
|
|
|
|
|
|
kmap |
81
|
|
|
|
|
|
|
vmap |
82
|
|
|
|
|
|
|
ktrans |
83
|
|
|
|
|
|
|
) ], |
84
|
|
|
|
|
|
|
'const' => [ qw( |
85
|
|
|
|
|
|
|
FORCE |
86
|
|
|
|
|
|
|
NOWARNING |
87
|
|
|
|
|
|
|
DIEONERR |
88
|
|
|
|
|
|
|
) ], |
89
|
|
|
|
|
|
|
nowarning => [], |
90
|
|
|
|
|
|
|
force => [], |
91
|
|
|
|
|
|
|
dieonerror => [],); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} }, @{ $EXPORT_TAGS{'const'} }); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
@EXPORT = (); |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
$VERSION = '0.03'; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub FORCE() { 1; } |
100
|
|
|
|
|
|
|
sub NOWARNING() { 2; } |
101
|
|
|
|
|
|
|
sub DIEONERR() { 4; } |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
$GLOBALMAP = 0; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub import { |
106
|
2
|
50
|
|
2
|
|
3715
|
$GLOBALMAP |= FORCE if(grep /:force/, @_); |
107
|
2
|
100
|
|
|
|
11
|
$GLOBALMAP |= NOWARNING if(grep /:nowarning/, @_); |
108
|
2
|
50
|
|
|
|
9
|
$GLOBALMAP |= DIEONERR if(grep /:dieonerror/, @_); |
109
|
2
|
|
|
|
|
2901
|
Hash::Mogrify->export_to_level(1, @_); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub kmap(&@) { |
113
|
3
|
|
|
3
|
0
|
1086
|
my $code = shift; |
114
|
3
|
|
|
|
|
4
|
my $hash = $_[0]; |
115
|
3
|
|
|
|
|
4
|
my $bitmap; |
116
|
3
|
100
|
|
|
|
9
|
if(!ref $hash) { |
117
|
1
|
50
|
|
|
|
5
|
$bitmap = shift if((scalar @_) % 2); |
118
|
1
|
|
|
|
|
3
|
$hash = { @_ }; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
3
|
|
|
|
|
2
|
my $temp; |
122
|
3
|
|
|
|
|
4
|
for (keys %{$hash}) { |
|
3
|
|
|
|
|
10
|
|
123
|
11
|
|
|
|
|
17
|
my $value = $hash->{$_}; |
124
|
11
|
|
|
|
|
26
|
$code->($_, $value); |
125
|
11
|
100
|
|
|
|
46
|
_double($temp, $_, $bitmap) or return; |
126
|
9
|
|
|
|
|
22
|
$temp->{$_} = $value; |
127
|
|
|
|
|
|
|
} |
128
|
1
|
|
|
|
|
2
|
%{$hash} = %{$temp}; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
2
|
|
129
|
|
|
|
|
|
|
|
130
|
1
|
50
|
|
|
|
6
|
return %{$hash} if(wantarray); |
|
0
|
|
|
|
|
0
|
|
131
|
1
|
|
|
|
|
5
|
return $hash; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub vmap(&@) { |
135
|
1
|
|
|
1
|
0
|
972
|
my $code = shift; |
136
|
1
|
|
|
|
|
2
|
my $hash = $_[0]; |
137
|
1
|
|
|
|
|
1
|
my $bitmap; # we don't use this, but maybe once :) |
138
|
1
|
50
|
|
|
|
4
|
if(!ref $hash) { |
139
|
1
|
50
|
|
|
|
3
|
$bitmap = shift if((scalar @_) % 2); |
140
|
1
|
|
|
|
|
4
|
$hash = { @_ }; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
1
|
|
|
|
|
1
|
my $temp; |
144
|
1
|
|
|
|
|
2
|
for my $key (keys(%{ $hash })) { |
|
1
|
|
|
|
|
3
|
|
145
|
4
|
|
|
|
|
6
|
$_ = $hash->{$key}; |
146
|
4
|
|
|
|
|
7
|
$code->($key, $_); |
147
|
4
|
|
|
|
|
14
|
$temp->{$key} = $_; |
148
|
|
|
|
|
|
|
} |
149
|
1
|
|
|
|
|
2
|
%{$hash} = %{$temp}; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
3
|
|
150
|
|
|
|
|
|
|
|
151
|
1
|
50
|
|
|
|
5
|
return %{$hash} if(wantarray); |
|
1
|
|
|
|
|
6
|
|
152
|
0
|
|
|
|
|
0
|
return $hash; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub hmap(&@) { |
156
|
1
|
|
|
1
|
0
|
1315
|
my $code = shift; |
157
|
1
|
|
|
|
|
2
|
my $hash = $_[0]; |
158
|
1
|
|
|
|
|
1
|
my $bitmap; |
159
|
1
|
50
|
|
|
|
4
|
if(!ref $hash) { |
160
|
0
|
0
|
|
|
|
0
|
$bitmap = shift if(@_ % 2); |
161
|
0
|
|
|
|
|
0
|
$hash = { @_ }; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
1
|
|
|
|
|
2
|
my $temp; |
165
|
1
|
|
|
|
|
2
|
for my $key (keys(%{ $hash })) { |
|
1
|
|
|
|
|
18
|
|
166
|
4
|
|
|
|
|
8
|
my $value = $hash->{$key}; |
167
|
4
|
|
|
|
|
11
|
$code->($key, $value); |
168
|
4
|
50
|
|
|
|
21
|
_double($temp, $key, $bitmap) or return; |
169
|
4
|
|
|
|
|
11
|
$temp->{$key} = $value; |
170
|
|
|
|
|
|
|
} |
171
|
1
|
|
|
|
|
3
|
%{$hash} = %{$temp}; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
172
|
|
|
|
|
|
|
|
173
|
1
|
50
|
|
|
|
5
|
return %{$hash} if(wantarray); |
|
0
|
|
|
|
|
0
|
|
174
|
1
|
|
|
|
|
4
|
return $hash; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub ktrans($@) { |
178
|
1
|
|
|
1
|
0
|
367
|
my $table = shift; |
179
|
1
|
|
|
|
|
2
|
my $hash = $_[0]; |
180
|
|
|
|
|
|
|
|
181
|
1
|
|
|
|
|
1
|
my $bitmap; |
182
|
1
|
50
|
|
|
|
7
|
if(!ref $hash) { |
183
|
1
|
50
|
|
|
|
5
|
$bitmap = shift if(@_ % 2); |
184
|
1
|
|
|
|
|
4
|
$hash = { @_ }; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
1
|
|
|
|
|
2
|
my $temp = { %{$hash} }; |
|
1
|
|
|
|
|
4
|
|
188
|
1
|
|
|
|
|
2
|
for my $old (keys(%{ $table })) { |
|
1
|
|
|
|
|
4
|
|
189
|
2
|
50
|
|
|
|
6
|
next if(!exists $temp->{$old}); |
190
|
2
|
|
|
|
|
3
|
my $new = $table->{$old}; |
191
|
|
|
|
|
|
|
|
192
|
2
|
50
|
|
|
|
4
|
_double($temp, $new, $bitmap) or return; |
193
|
|
|
|
|
|
|
|
194
|
2
|
|
|
|
|
4
|
my $value = $temp->{$old}; |
195
|
2
|
|
|
|
|
4
|
delete $temp->{$old}; |
196
|
2
|
|
|
|
|
8
|
$temp->{$new} = $value; |
197
|
|
|
|
|
|
|
} |
198
|
1
|
|
|
|
|
2
|
%{$hash} = %{$temp}; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
4
|
|
199
|
|
|
|
|
|
|
|
200
|
1
|
50
|
|
|
|
5
|
return %{$hash} if(wantarray); |
|
1
|
|
|
|
|
8
|
|
201
|
0
|
|
|
|
|
0
|
return $hash; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# check if a hashkey exists, and act depending on global&local settings |
205
|
|
|
|
|
|
|
sub _double { |
206
|
17
|
|
|
17
|
|
25
|
my ($hash, $key, $bitmap) = @_; |
207
|
17
|
50
|
|
|
|
32
|
my $map = defined($bitmap) ? $bitmap : $GLOBALMAP; |
208
|
|
|
|
|
|
|
|
209
|
17
|
100
|
|
|
|
61
|
return 1 if(!exists $hash->{$key}); |
210
|
2
|
50
|
|
|
|
5
|
if(!($map & NOWARNING)) { |
211
|
0
|
0
|
|
|
|
0
|
warn('Attempting to override existing key, failing.') if(!$map & FORCE); |
212
|
0
|
0
|
|
|
|
0
|
warn('Attempting to override existing key, forcing.') if($map & FORCE); |
213
|
|
|
|
|
|
|
} |
214
|
2
|
50
|
|
|
|
7
|
return 1 if($map & FORCE); |
215
|
2
|
50
|
|
|
|
6
|
die 'Died, trying to override existing key' if($map & DIEONERR); |
216
|
2
|
|
|
|
|
11
|
return; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
1; |
219
|
|
|
|
|
|
|
__END__ |