File Coverage

blib/lib/Text/Diff3/DiffHeckel.pm
Criterion Covered Total %
statement 59 63 93.6
branch 12 14 85.7
condition 22 27 81.4
subroutine 7 7 100.0
pod 1 1 100.0
total 101 112 90.1


line stmt bran cond sub pod time code
1             package Text::Diff3::DiffHeckel;
2             # two-way diff plug-in
3 6     6   104 use 5.006;
  6         18  
  6         213  
4 6     6   32 use strict;
  6         82  
  6         158  
5 6     6   28 use warnings;
  6         9  
  6         164  
6 6     6   36 use base qw(Text::Diff3::Base);
  6         7  
  6         41  
7              
8 6     6   584 use version; our $VERSION = '0.08';
  6         15  
  6         33  
9              
10             sub diff {
11 48     48 1 59 my($self, $A, $B) = @_;
12 48         101 my $f = $self->factory;
13 48 50       104 if (! $self->_is_a_text($A)) {
14 0         0 $A = $f->create_text($A);
15             }
16 48 50       91 if (! $self->_is_a_text($B)) {
17 0         0 $B = $f->create_text($B);
18             }
19 48         146 my $diff = $f->create_list2;
20 48         124 my @uniq = (
21             [$A->first_index - 1, $B->first_index - 1],
22             [$A->last_index + 1, $B->last_index + 1]
23             );
24 48         75 my(%freq, %ap, %bp);
25 48         114 for my $lineno ($A->range) {
26 289         791 my $s = $A->at($lineno);
27 289         550 $freq{$s} += 2;
28 289         537 $ap{$s} = $lineno;
29             }
30 48         138 for my $lineno ($B->range) {
31 301         602 my $s = $B->at($lineno);
32 301         476 $freq{$s} += 3;
33 301         518 $bp{$s} = $lineno;
34             }
35 48         184 while (my($s, $x) = each %freq) {
36 354 100       743 next if $x != 5;
37 225         818 push @uniq, [$ap{$s}, $bp{$s}];
38             }
39 48         120 @uniq = sort { $a->[0] <=> $b->[0] } @uniq;
  605         777  
40 48         174 my($AL, $BL) = ($A->last_index, $B->last_index);
41 48         117 my($a1, $b1) = ($A->first_index, $B->first_index);
42 48   100     277 while ($a1 <= $AL && $b1 <= $BL && $A->eq_at($a1, $B->at($b1))) {
      100        
43 138         200 $a1++;
44 138         726 $b1++;
45             }
46 48         75 my($a0, $b0) = ($a1, $b1);
47 48         72 for (@uniq) {
48 321         281 my($auniq, $buniq) = @{$_};
  321         400  
49 321 100 66     919 next if $auniq < $a0 || $buniq < $b0;
50 90         118 ($a1, $b1) = ($auniq - 1, $buniq - 1);
51 90   100     296 while ($a0 <= $a1 && $b0 <= $b1 && $A->eq_at($a1, $B->at($b1))) {
      66        
52 0         0 $a1--;
53 0         0 $b1--;
54             }
55 90 100 100     343 if ($a0 <= $a1 && $b0 <= $b1) {
    100          
    100          
56 16         51 $diff->push($f->create_range2('c', $a0, $a1, $b0, $b1));
57             } elsif ($a0 <= $a1) {
58 15         56 $diff->push($f->create_range2('d', $a0, $a1, $b0, $b0 - 1));
59             } elsif ($b0 <= $b1) {
60 20         70 $diff->push($f->create_range2('a', $a0, $a0 - 1, $b0, $b1));
61             }
62 90         140 ($a1, $b1) = ($auniq + 1, $buniq + 1);
63 90   66     318 while ($a1 <= $AL && $b1 <= $BL && $A->eq_at($a1, $B->at($b1))) {
      100        
64 45         67 $a1++;
65 45         194 $b1++;
66             }
67 90         288 ($a0, $b0) = ($a1, $b1);
68             }
69 48         364 return $diff;
70             }
71              
72             sub _is_a_text {
73 96     96   118 my($self, $x) = @_;
74             return eval{ $x->can('first_index') }
75             && eval{ $x->can('last_index') }
76             && eval{ $x->can('range') }
77             && eval{ $x->can('at') }
78 96   33     99 && eval{ $x->can('eq_at') };
79             }
80              
81             1;
82              
83             __END__