File Coverage

blib/lib/Blessed/Merge.pm
Criterion Covered Total %
statement 66 66 100.0
branch 42 42 100.0
condition 18 18 100.0
subroutine 11 11 100.0
pod 2 2 100.0
total 139 139 100.0


line stmt bran cond sub pod time code
1             package Blessed::Merge;
2              
3 4     4   420725 use 5.006;
  4         37  
4 4     4   17 use strict;
  4         8  
  4         66  
5 4     4   15 use warnings;
  4         6  
  4         212  
6              
7             our $VERSION = '0.10';
8              
9 4     4   22 use Scalar::Util qw/reftype/;
  4         6  
  4         183  
10 4     4   26 use Carp qw/croak/;
  4         7  
  4         155  
11 4     4   1498 use Combine::Keys qw/combine_keys/;
  4         59144  
  4         31  
12              
13             sub new {
14 5 100 100 5 1 3588 my ($pkg, $args) = (shift, reftype $_[0] || "" eq 'HASH' ? $_[0] : {@_});
15 5         15 my $self = bless $args, $pkg;
16 5   100     44 $self->{$_} = $self->{$_} // 1 foreach (qw/same blessed/);
17 5   100     29 $self->{$_} = $self->{$_} // 0 foreach(qw/unique_array unique_hash/);
18 5         18 return $self;
19             }
20              
21             sub merge {
22 8     8 1 8217 my ($self, $base_bless, $new) = (shift, ref $_[0], shift);
23             map {
24 8 100       15 if ( $self->{same} ) {
  10         23  
25 9 100       167 croak 'Attempting to merge two different *packages*' unless $base_bless eq ref $_;
26             }
27 9         33 $new = $self->_merge({%$new}, $_);
28             } @_;
29 7 100       44 return $self->{blessed} ? bless $new, $base_bless : $new;
30             }
31              
32             sub _merge {
33 69     69   223 my ($self, $new, $merger) = @_;
34 69 100       122 return $new unless defined $merger;
35 61   100     142 my $new_ref = reftype($new) || '';
36 61   100     113 my $merger_ref = reftype($merger) || 'SCALAR';
37             $merger_ref eq 'HASH' ? do {
38 31 100       46 $new = {} if ( $new_ref ne 'HASH' );
39             return {
40             $self->{unique_hash}
41             ? $self->_unique_merge($merger_ref, $new, $merger)
42 31 100       104 : map +( $_ => $self->_merge( $new->{$_}, $merger->{$_} ) ), combine_keys($new, $merger)
43             };
44 61 100       147 } : $merger_ref eq 'ARRAY' ? do {
    100          
45             $new_ref eq 'ARRAY' ? do {
46 11 100   11   14 my $length = sub {$_[0] < $_[1] ? $_[1] : $_[0]}->(scalar @{$new}, scalar @{$merger});
  11         22  
  11         14  
  11         34  
47             [ $self->{unique_array}
48             ? $self->_unique_merge($merger_ref, $new, $merger, $length)
49 11 100       41 : map { $self->_merge($new->[$_], $merger->[$_]) } 0 .. $length - 1
  6         13  
50             ];
51 13 100       23 } : [ map { $self->_merge('', $_ ) } @{ $merger } ]; # destroy da references
  6         7  
  2         3  
52             } : $merger;
53             }
54              
55             sub _unique_merge {
56 28     28   49 my ($s, $r, $n, $m, $l) = @_;
57 28 100       44 ($r eq 'ARRAY') && do {
58 9         10 my (@z, %u, $x1, $x2);
59 9         17 for (my $i = 0; $i < $l; $i++) {
60             my $c = grep {
61 24         31 my ($x) = reftype(\$_);
  48         72  
62 48 100 100     115 $x eq 'SCALAR' ? !$_ || exists $u{$_} ? 1 : do { $u{$_} = 1; push @z, $_; } : 0;
  27 100       35  
  27         42  
63             } ($n->[$i], $m->[$i]);
64 24 100       48 do { ($x1, $x2) = (reftype($n->[$i]), reftype($m->[$i])); $c == 0 }
  5 100       14  
  5 100       19  
    100          
65             ? $x1 eq $x2
66             ? push @z, $s->_merge($n->[$i], $m->[$i])
67             : push @z, $n->[$i], $m->[$i]
68             : $x1
69             ? push @z, $n->[$i]
70             : push @z, $m->[$i] if $c != 2;
71             }
72 9         36 return @z;
73             };
74 19         20 my %z = %{ $n };
  19         41  
75             map {
76 31   100     67 my $x = reftype($m->{$_}) || 'SCALAR';
77             exists $z{$_} ? $x ne 'SCALAR' && $x eq reftype($z{$_})
78 31 100 100     98 ? do { $z{$_} = $s->_merge($z{$_}, $m->{$_}) } : '*\o/*' : do { $z{$_} = $m->{$_} }
  21 100       41  
  4         8  
79 19         25 } keys %{ $m };
  19         35  
80 19         76 return %z;
81             }
82              
83             1;
84              
85             __END__