File Coverage

blib/lib/Deep/Hash/Utils.pm
Criterion Covered Total %
statement 22 60 36.6
branch 12 38 31.5
condition 0 9 0.0
subroutine 4 7 57.1
pod 4 4 100.0
total 42 118 35.5


line stmt bran cond sub pod time code
1             package Deep::Hash::Utils;
2              
3 1     1   20435 use 5.006;
  1         4  
  1         39  
4 1     1   6 use strict;
  1         2  
  1         34  
5 1     1   5 use warnings;
  1         6  
  1         760  
6              
7             require Exporter;
8              
9             our @ISA = qw(Exporter);
10             our %EXPORT_TAGS = ( 'all' => [ qw( reach slurp nest deepvalue ) ] );
11             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
12             our @EXPORT = ();
13             our $VERSION = '0.03';
14              
15              
16             my $C;
17              
18             # Recursive version of C;
19             sub reach {
20 15     15 1 46 my $ref = shift;
21 15 100       30 if (ref $ref eq 'HASH') {
    50          
22              
23              
24 11 100       26 if (defined $C->{$ref}{v}) {
25 8 100       24 if (ref $C->{$ref}{v} eq 'HASH') {
    50          
26 4 100       7 if (my @rec = reach($C->{$ref}{v})) {
27 2         7 return ($C->{$ref}{k},@rec);
28             }
29             } elsif (ref $C->{$ref}{v} eq 'ARRAY') {
30 0 0       0 if (my @rec = reach($C->{$ref}{v})) {
31 0 0       0 if (defined $C->{$ref}{k}) {
32 0         0 return $C->{$ref}{k},@rec;
33             }
34 0         0 return @rec;
35             }
36            
37             }
38 6         7 undef $C->{$ref};
39             }
40              
41              
42 9 100       26 if (my ($k,$v) = each %$ref) {
43 6         11 $C->{$ref}{v} = $v;
44 6         13 $C->{$ref}{k} = $k;
45 6         12 return ($k,reach($v));
46             }
47              
48 3         9 return ();
49              
50              
51             } elsif (ref $ref eq 'ARRAY') {
52              
53              
54 0 0       0 if (defined $C->{$ref}{v}) {
55 0 0 0     0 if (ref $C->{$ref}{v} eq 'HASH' ||
56             ref $C->{$ref}{v} eq 'ARRAY') {
57            
58 0 0       0 if (my @rec = reach($C->{$ref}{v})) {
59 0 0       0 if (defined $C->{$ref}{k}) {
60 0         0 return $C->{$ref}{k},@rec;
61             }
62 0         0 return @rec;
63             }
64             }
65             }
66              
67              
68 0 0 0     0 if (my $v = $ref->[$C->{$ref}{i}++ || 0]) {
69 0         0 $C->{$ref}{v} = $v;
70 0         0 return (reach($v));
71             }
72              
73 0         0 return ();
74             }
75 4         15 return $ref;
76             }
77              
78              
79             # run C over entire hash and return the final list of values at once
80             sub slurp {
81 0     0 1   my $ref = shift;
82 0           my @h;
83 0           while (my @a = reach($ref)) {
84 0           push @h,\@a;
85             }
86 0           return @h;
87             }
88              
89              
90             # Define nested hash keys from the given list of values
91             sub nest {
92 0     0 1   my $hr = shift;
93 0           my $key = shift;
94 0   0       $hr->{$key} ||= {};
95 0           my $ref = $hr->{$key};
96              
97 0           while ($key = shift @_) {
98 0           $hr = $ref;
99 0 0         if (@_ > 1) {
100 0   0       $hr->{$key} ||= {};
101 0           $ref = $hr->{$key};
102             } else {
103 0           $hr->{$key} = shift;
104             }
105             }
106 0           return $hr;
107             }
108              
109              
110             # Return value at the end of the given nested hash keys and/or array indexes
111             sub deepvalue {
112 0     0 1   my $hr = shift;
113 0           while (@_) {
114 0           my $key = shift;
115 0 0         if (ref $hr eq 'HASH') {
    0          
116 0 0         return unless ($hr = $hr->{$key});
117             } elsif (ref $hr eq 'ARRAY') {
118 0 0         return unless ($hr = $hr->[$key]);
119             } else {
120 0           return;
121             }
122             }
123 0           return $hr;
124             }
125              
126              
127             1;
128             __END__