File Coverage

blib/lib/Catmandu/Fix/vacuum.pm
Criterion Covered Total %
statement 48 48 100.0
branch 23 26 88.4
condition 18 21 85.7
subroutine 8 8 100.0
pod 0 1 0.0
total 97 104 93.2


line stmt bran cond sub pod time code
1             package Catmandu::Fix::vacuum;
2              
3 1     1   120079 use Catmandu::Sane;
  1         4  
  1         8  
4              
5             our $VERSION = '1.2020';
6              
7 1     1   7 use Catmandu::Util qw(is_value is_hash_ref is_array_ref);
  1         2  
  1         66  
8 1     1   7 use Scalar::Util qw(refaddr);
  1         2  
  1         42  
9 1     1   5 use Moo;
  1         3  
  1         6  
10 1     1   360 use namespace::clean;
  1         2  
  1         4  
11              
12             with 'Catmandu::Fix::Inlineable';
13              
14             sub _visit {
15 10     10   16 my ($self, $v) = @_;
16 10 100 66     62 (is_hash_ref($v) && %$v) || (is_array_ref($v) && @$v);
      66        
17             }
18              
19             sub _empty {
20 27     27   46 my ($self, $v) = @_;
21 27 100 100     274 !defined($v)
      100        
      66        
      100        
      100        
22             || (is_value($v) && $v !~ /\S/)
23             || (is_hash_ref($v) && !%$v)
24             || (is_array_ref($v) && !@$v);
25             }
26              
27             sub fix {
28 1     1 0 228 my ($self, $data) = @_;
29              
30 1 50       5 return $data unless $self->_visit($data);
31              
32 1         4 my @stack = ($data);
33 1         3 my %seen;
34              
35 1         4 while (@stack) {
36 16         24 my $d = pop @stack;
37 16         37 my $id = refaddr($d);
38              
39 16 100       31 if ($seen{$id}) {
40 8 100       37 if (is_hash_ref($d)) {
    50          
41 6         17 for my $k (keys %$d) {
42 7 100       18 delete $d->{$k} if $self->_empty($d->{$k});
43             }
44             }
45             elsif (is_array_ref($d)) {
46 2         4 my @vals = grep {!$self->_empty($_)} @$d;
  2         8  
47 2         8 splice(@$d, 0, @$d, @vals);
48             }
49             }
50             else {
51 8         22 $seen{$id} = 1;
52 8         10 push @stack, $d;
53              
54 8 100       35 if (is_hash_ref($d)) {
    50          
55 6         16 for my $k (keys %$d) {
56 15         25 my $v = $d->{$k};
57 15 100       26 if ($self->_empty($v)) {
    100          
58 8         21 delete $d->{$k};
59             }
60             elsif ($self->_visit($v)) {
61 6         16 push @stack, $v;
62             }
63             }
64             }
65             elsif (is_array_ref($d)) {
66 2         3 my @vals;
67 2         4 for my $v (@$d) {
68 3 100       6 next if $self->_empty($v);
69 2         13 push @vals, $v;
70 2 100       6 push @stack, $v if $self->_visit($v);
71             }
72 2         12 splice @$d, 0, @$d, @vals;
73             }
74             }
75             }
76              
77 1         7 $data;
78             }
79              
80             1;
81              
82             __END__
83              
84             =pod
85              
86             =head1 NAME
87              
88             Catmandu::Fix::vacuum - delete all empty fields from your data
89              
90             =head1 SYNOPSIS
91              
92             # Delete all the empty fields
93             #
94             # input:
95             #
96             # foo: ''
97             # bar: []
98             # relations: {}
99             # test: 123
100             #
101             vacuum()
102            
103             # output:
104             #
105             # test: 123
106             #
107              
108             =head1 SEE ALSO
109              
110             L<Catmandu::Fix>
111              
112             =cut