line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Diff3::Diff3; |
2
|
|
|
|
|
|
|
# diff3 component |
3
|
6
|
|
|
6
|
|
89
|
use 5.006; |
|
6
|
|
|
|
|
18
|
|
|
6
|
|
|
|
|
233
|
|
4
|
6
|
|
|
6
|
|
45
|
use strict; |
|
6
|
|
|
|
|
19
|
|
|
6
|
|
|
|
|
179
|
|
5
|
6
|
|
|
6
|
|
32
|
use warnings; |
|
6
|
|
|
|
|
16
|
|
|
6
|
|
|
|
|
201
|
|
6
|
|
|
|
|
|
|
|
7
|
6
|
|
|
6
|
|
29
|
use base qw(Text::Diff3::Base); |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
49
|
|
8
|
|
|
|
|
|
|
|
9
|
6
|
|
|
6
|
|
833
|
use version; our $VERSION = '0.08'; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
21
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# the three-way diff procedure based on the GNU diff3.c by Randy Smith. |
12
|
|
|
|
|
|
|
sub diff3 { |
13
|
21
|
|
|
21
|
1
|
34
|
my($self, $text0, $text2, $text1) = @_; |
14
|
21
|
|
|
|
|
50
|
my $f = $self->factory; |
15
|
21
|
50
|
|
|
|
52
|
if (! $self->_is_a_text($text0)) { |
16
|
0
|
|
|
|
|
0
|
$text0 = $f->create_text($text0); |
17
|
|
|
|
|
|
|
} |
18
|
21
|
50
|
|
|
|
44
|
if (! $self->_is_a_text($text2)) { |
19
|
0
|
|
|
|
|
0
|
$text0 = $f->create_text($text2); |
20
|
|
|
|
|
|
|
} |
21
|
21
|
50
|
|
|
|
40
|
if (! $self->_is_a_text($text1)) { |
22
|
0
|
|
|
|
|
0
|
$text0 = $f->create_text($text1); |
23
|
|
|
|
|
|
|
} |
24
|
21
|
|
|
|
|
72
|
my $diffp = $f->create_diff; |
25
|
21
|
|
|
|
|
59
|
my @diff2 = ( |
26
|
|
|
|
|
|
|
$diffp->diff($text2, $text0), |
27
|
|
|
|
|
|
|
$diffp->diff($text2, $text1), |
28
|
|
|
|
|
|
|
); |
29
|
21
|
|
|
|
|
66
|
my $diff3 = $f->create_list3; |
30
|
21
|
|
|
|
|
67
|
my $range3 = $f->create_null_range3; |
31
|
21
|
|
66
|
|
|
65
|
while (! $diff2[0]->is_empty || ! $diff2[1]->is_empty) { |
32
|
|
|
|
|
|
|
# find a continual range in text2 $lo2..$hi2 |
33
|
|
|
|
|
|
|
# changed by text0 or by text1. |
34
|
|
|
|
|
|
|
# |
35
|
|
|
|
|
|
|
# diff2[0] 222 222222222 |
36
|
|
|
|
|
|
|
# text2 ...L!!!!!!!!!!!!!!!!!!!!H... |
37
|
|
|
|
|
|
|
# diff2[1] 222222 22 2222222 |
38
|
33
|
|
|
|
|
83
|
my @range2 = ([], []); |
39
|
33
|
100
|
|
|
|
82
|
my $i = |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
40
|
|
|
|
|
|
|
$diff2[0]->is_empty ? 1 |
41
|
|
|
|
|
|
|
: $diff2[1]->is_empty ? 0 |
42
|
|
|
|
|
|
|
: $diff2[0]->first->loA <= $diff2[1]->first->loA ? 0 |
43
|
|
|
|
|
|
|
: 1; |
44
|
33
|
|
|
|
|
51
|
my $j = $i; |
45
|
33
|
|
|
|
|
36
|
my $k = $i ^ 1; |
46
|
33
|
|
|
|
|
87
|
my $hi = $diff2[$j]->first->hiA; |
47
|
33
|
|
|
|
|
39
|
push @{$range2[$j]}, $diff2[$j]->shift; |
|
33
|
|
|
|
|
88
|
|
48
|
33
|
|
100
|
|
|
90
|
while (! $diff2[$k]->is_empty && $diff2[$k]->first->loA <= $hi + 1) { |
49
|
10
|
|
|
|
|
31
|
my $hi_k = $diff2[$k]->first->hiA; |
50
|
10
|
|
|
|
|
13
|
push @{$range2[$k]}, $diff2[$k]->shift; |
|
10
|
|
|
|
|
26
|
|
51
|
10
|
50
|
|
|
|
37
|
if ($hi < $hi_k) { |
52
|
0
|
|
|
|
|
0
|
$hi = $hi_k; |
53
|
0
|
|
|
|
|
0
|
$j = $k; |
54
|
0
|
|
|
|
|
0
|
$k = $k ^ 1; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
} |
57
|
33
|
|
|
|
|
109
|
my $lo2 = $range2[$i][ 0]->loA; |
58
|
33
|
|
|
|
|
96
|
my $hi2 = $range2[$j][-1]->hiA; |
59
|
|
|
|
|
|
|
# take the corresponding ranges in text0 $lo0..$hi0 |
60
|
|
|
|
|
|
|
# and in text1 $lo1..$hi1. |
61
|
|
|
|
|
|
|
# |
62
|
|
|
|
|
|
|
# text0 ..L!!!!!!!!!!!!!!!!!!!!!!!!!!!!H... |
63
|
|
|
|
|
|
|
# diff2[0] 222 222222222 |
64
|
|
|
|
|
|
|
# text2 ...00!1111!000!!00!111111... |
65
|
|
|
|
|
|
|
# diff2[1] 222222 22 2222222 |
66
|
|
|
|
|
|
|
# text1 ...L!!!!!!!!!!!!!!!!H... |
67
|
33
|
|
|
|
|
36
|
my($lo0, $hi0); |
68
|
33
|
100
|
|
|
|
31
|
if (@{$range2[0]}) { |
|
33
|
|
|
|
|
97
|
|
69
|
21
|
|
|
|
|
55
|
$lo0 = $range2[0][ 0]->loB - $range2[0][ 0]->loA + $lo2; |
70
|
21
|
|
|
|
|
53
|
$hi0 = $range2[0][-1]->hiB - $range2[0][-1]->hiA + $hi2; |
71
|
|
|
|
|
|
|
} else { |
72
|
12
|
|
|
|
|
32
|
$lo0 = $range3->hi0 - $range3->hi2 + $lo2; |
73
|
12
|
|
|
|
|
30
|
$hi0 = $range3->hi0 - $range3->hi2 + $hi2; |
74
|
|
|
|
|
|
|
} |
75
|
33
|
|
|
|
|
38
|
my($lo1, $hi1); |
76
|
33
|
100
|
|
|
|
28
|
if (@{$range2[1]}) { |
|
33
|
|
|
|
|
68
|
|
77
|
22
|
|
|
|
|
58
|
$lo1 = $range2[1][ 0]->loB - $range2[1][ 0]->loA + $lo2; |
78
|
22
|
|
|
|
|
60
|
$hi1 = $range2[1][-1]->hiB - $range2[1][-1]->hiA + $hi2; |
79
|
|
|
|
|
|
|
} else { |
80
|
11
|
|
|
|
|
30
|
$lo1 = $range3->hi1 - $range3->hi2 + $lo2; |
81
|
11
|
|
|
|
|
31
|
$hi1 = $range3->hi1 - $range3->hi2 + $hi2; |
82
|
|
|
|
|
|
|
} |
83
|
33
|
|
|
|
|
112
|
$range3 = $f->create_range3( |
84
|
|
|
|
|
|
|
undef, $lo0, $hi0, $lo1, $hi1, $lo2, $hi2 |
85
|
|
|
|
|
|
|
); |
86
|
|
|
|
|
|
|
# detect type of changes. |
87
|
33
|
100
|
|
|
|
83
|
if (! @{$range2[0]}) { |
|
33
|
100
|
|
|
|
61
|
|
|
21
|
100
|
|
|
|
52
|
|
88
|
12
|
|
|
|
|
29
|
$range3->type('1'); |
89
|
|
|
|
|
|
|
} elsif (! @{$range2[1]}) { |
90
|
11
|
|
|
|
|
30
|
$range3->type('0'); |
91
|
|
|
|
|
|
|
} elsif ($hi0 - $lo0 != $hi1 - $lo1) { |
92
|
2
|
|
|
|
|
7
|
$range3->type('A'); |
93
|
|
|
|
|
|
|
} else { |
94
|
8
|
|
|
|
|
19
|
$range3->type('2'); |
95
|
8
|
|
|
|
|
18
|
for my $d (0 .. $hi0 - $lo0) { |
96
|
13
|
100
|
|
|
|
33
|
if (! $text0->eq_at($lo0 + $d, $text1->at($lo1 + $d))) { |
97
|
2
|
|
|
|
|
6
|
$range3->type('A'); |
98
|
2
|
|
|
|
|
3
|
last; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
33
|
|
|
|
|
80
|
$diff3->push($range3); |
103
|
|
|
|
|
|
|
} |
104
|
21
|
|
|
|
|
138
|
return $diff3; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub _is_a_text { |
108
|
63
|
|
|
63
|
|
67
|
my($self, $x) = @_; |
109
|
63
|
|
33
|
|
|
61
|
return eval{ $x->can('at') } && eval{ $x->can('eq_at') }; |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
1; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
__END__ |