File Coverage

blib/lib/Deep/Hash/Utils.pm
Criterion Covered Total %
statement 21 59 35.5
branch 12 38 31.5
condition 0 9 0.0
subroutine 4 7 57.1
pod 4 4 100.0
total 41 117 35.0


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