File Coverage

blib/lib/Hash/Subset.pm
Criterion Covered Total %
statement 72 73 98.6
branch 38 40 95.0
condition n/a
subroutine 14 14 100.0
pod 10 10 100.0
total 134 137 97.8


line stmt bran cond sub pod time code
1             package Hash::Subset;
2              
3 1     1   67608 use strict;
  1         12  
  1         28  
4 1     1   5 use warnings;
  1         3  
  1         31  
5              
6 1     1   4 use Exporter qw(import);
  1         2  
  1         859  
7              
8             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
9             our $DATE = '2022-07-27'; # DATE
10             our $DIST = 'Hash-Subset'; # DIST
11             our $VERSION = '0.007'; # VERSION
12              
13             our @EXPORT_OK = qw(
14             hash_subset
15             hashref_subset
16             hash_subset_without
17             hashref_subset_without
18              
19             merge_hash_subset
20             merge_overwrite_hash_subset
21             merge_ignore_hash_subset
22             merge_hash_subset_without
23             merge_overwrite_hash_subset_without
24             merge_ignore_hash_subset_without
25             );
26              
27             sub _routine {
28 26     26   57 my ($which, $hash, @keys_srcs) = @_;
29              
30 26         83 my $reverse = $which =~ /_without\z/;
31 26         49 my $return_ref = $which =~ /\Ahashref_/;
32              
33 26         32 my %subset;
34 26 100       88 %subset = %$hash if $reverse;
35              
36 26         46 for my $keys_src (@keys_srcs) {
37 31         47 my $ref = ref $keys_src;
38 31 100       84 if ($ref eq 'ARRAY') {
    100          
    100          
    50          
39 14 100       28 if ($reverse) {
40 7         15 for (@$keys_src) {
41 9         22 delete $subset{$_};
42             }
43             } else {
44 7         14 for (@$keys_src) {
45 13 50       35 $subset{$_} = $hash->{$_} if exists $hash->{$_};
46             }
47             }
48             } elsif ($ref eq 'HASH') {
49 6 100       15 if ($reverse) {
50 3         9 for (keys %$keys_src) {
51 7         12 delete $subset{$_};
52             }
53             } else {
54 3         12 for (keys %$keys_src) {
55 7 100       19 $subset{$_} = $hash->{$_} if exists $hash->{$_};
56             }
57             }
58             } elsif ($ref eq 'Regexp') {
59 5 100       12 if ($reverse) {
60 2         6 for (keys %subset) {
61 6 100       26 delete $subset{$_} if $_ =~ $keys_src;
62             }
63             } else {
64 3         9 for (keys %$hash) {
65 10 100       38 $subset{$_} = $hash->{$_} if $_ =~ $keys_src;
66             }
67             }
68             } elsif ($ref eq 'CODE') {
69 6 100       10 if ($reverse) {
70 3         8 for (keys %$hash) {
71 10 100       41 delete $subset{$_} if $keys_src->($_, $hash->{$_});
72             }
73             } else {
74 3         9 for (keys %$hash) {
75 10 100       39 $subset{$_} = $hash->{$_} if $keys_src->($_, $hash->{$_});
76             }
77             }
78             } else {
79 0         0 die "Key source ($keys_src) must be a hashref/arrayref/Regexp/coderef";
80             }
81             } # for $keys_src
82              
83 26 100       62 if ($return_ref) {
84 8         43 return \%subset;
85             } else {
86 18         101 return %subset;
87             }
88             }
89              
90 9     9 1 1233 sub hash_subset { _routine('hash_subset' , @_) }
91 4     4 1 10 sub hashref_subset { _routine('hashref_subset', @_) }
92 9     9 1 2621 sub hash_subset_without { _routine('hash_subset_without' , @_) }
93 4     4 1 12 sub hashref_subset_without { _routine('hashref_subset_without', @_) }
94              
95             sub merge_hash_subset {
96 2     2 1 2963 my ($h1, $h2, @keys_src) = @_;
97 2         8 my %subset = hash_subset($h2, @keys_src);
98 2         8 for my $key (keys %subset) {
99 4 100       17 die "Duplicate key when merging hash subset key '$key'" if exists $h1->{$key};
100 3         7 $h1->{$key} = $subset{$key};
101             }
102             }
103              
104             sub merge_hash_subset_without {
105 2     2 1 2798 my ($h1, $h2, @keys_src) = @_;
106 2         6 my %subset = hash_subset_without($h2, @keys_src);
107 2         6 for my $key (keys %subset) {
108 4 100       20 die "Duplicate key when merging hash subset key '$key'" if exists $h1->{$key};
109 3         5 $h1->{$key} = $subset{$key};
110             }
111             }
112              
113             sub merge_overwrite_hash_subset {
114 1     1 1 2093 my ($h1, $h2, @keys_src) = @_;
115 1         5 my %subset = hash_subset($h2, @keys_src);
116 1         4 for my $key (keys %subset) {
117 2         4 $h1->{$key} = $subset{$key};
118             }
119             }
120              
121             sub merge_overwrite_hash_subset_without {
122 1     1 1 2239 my ($h1, $h2, @keys_src) = @_;
123 1         5 my %subset = hash_subset_without($h2, @keys_src);
124 1         3 for my $key (keys %subset) {
125 2         5 $h1->{$key} = $subset{$key};
126             }
127             }
128              
129             sub merge_ignore_hash_subset {
130 1     1 1 2251 my ($h1, $h2, @keys_src) = @_;
131 1         5 my %subset = hash_subset($h2, @keys_src);
132 1         4 for my $key (keys %subset) {
133 2 100       7 next if exists $h1->{$key};
134 1         4 $h1->{$key} = $subset{$key};
135             }
136             }
137              
138             sub merge_ignore_hash_subset_without {
139 1     1 1 2249 my ($h1, $h2, @keys_src) = @_;
140 1         5 my %subset = hash_subset_without($h2, @keys_src);
141 1         5 for my $key (keys %subset) {
142 2 100       9 next if exists $h1->{$key};
143 1         2 $h1->{$key} = $subset{$key};
144             }
145             }
146              
147             1;
148             # ABSTRACT: Produce subset of a hash
149              
150             __END__