File Coverage

blib/lib/Template/Reverse.pm
Criterion Covered Total %
statement 70 70 100.0
branch 24 26 92.3
condition n/a
subroutine 10 10 100.0
pod 2 2 100.0
total 106 108 98.1


line stmt bran cond sub pod time code
1             package Template::Reverse;
2              
3             # ABSTRACT: A template generator getting different parts between pair of text
4              
5 9     9   374553 use Moo;
  9         220868  
  9         65  
6 9     9   26633 use utf8;
  9         89  
  9         59  
7 9     9   5185 use Template::Reverse::Part;
  9         33  
  9         436  
8 9     9   39368 use Algorithm::Diff qw(sdiff);
  9         65420  
  9         825  
9 9     9   91 use Scalar::Util qw(blessed);
  9         19  
  9         7669  
10             our $VERSION = '0.143'; # VERSION
11              
12              
13             has 'sidelen' => (
14             is=>'rw',
15             default => sub{return 10;}
16             );
17              
18              
19             my $_WILDCARD = bless [], 'WILDCARD';
20 52     52 1 179 sub WILDCARD{return $_WILDCARD};
21             sub _isWILDCARD{
22 387     387   2047 return ref $_[0] eq 'WILDCARD';
23             }
24              
25              
26             sub detect{
27 4     4 1 5150 my $self = shift;
28 4         11 my @strs = @_;
29 4         18 my $diff = _diff($strs[0],$strs[1]);
30 4         44 my $pattern = _detect($diff,$self->sidelen());
31 4         19 return $pattern;
32             }
33              
34              
35             ### internal functions
36             sub _detect{
37 29     29   28758 my $diff = shift;
38 29         50 my $sidelen = shift;
39 29 100       98 $sidelen = 0 unless $sidelen;
40 29         44 my @d = @{$diff};
  29         157  
41 29         46 my $lastStar = 0;
42 29         42 my @res;
43 29         97 for(my $i=0; $i<@d; $i++)
44             {
45 230 100       439 if( _isWILDCARD($d[$i] ) )
46             {
47 45         67 my $from = $lastStar;
48 45         122 my $to = $i-1;
49 45 100       101 if( $sidelen ){
50 19 100       66 $from = $to-$sidelen+1 if $to-$from+1 > $sidelen;
51             }
52 45         147 my @pre = @d[$from..$to];
53            
54 45         105 my $j = @d;
55 45 100       109 if( $i+1 < @d ){
56 37         118 for( $j=$i+1; $j<@d; $j++)
57             {
58 131 100       310 if( _isWILDCARD( $d[$j] ) ){
59 19         36 last;
60             }
61             }
62             }
63 45         72 $from = $i+1;
64 45         61 $to = $j-1;
65 45 100       93 if( $sidelen ){
66 19 100       59 $to = $from + $sidelen-1 if $to-$from+1 > $sidelen;
67             }
68 45         112 my @post = @d[$from..$to];
69 45         1234 my $part = Template::Reverse::Part->new(pre=>\@pre, post=>\@post);
70 45         8868 push(@res,$part);
71 45         197 $lastStar = $i+1;
72             }
73             }
74 29         129 return \@res;
75             }
76              
77              
78             sub _diff{
79 16     16   9130 my ($a,$b) = @_;
80 16         28 my ($org_a,$org_b) = @_;
81              
82 16 50       25 $a = [map{blessed($_)?$_->as_string:$_}@{$a}];
  79         267  
  16         31  
83 16 50       29 $b = [map{blessed($_)?$_->as_string:$_}@{$b}];
  77         183  
  16         25  
84            
85 16         73 my @d = sdiff($a,$b);
86 16         3289 my @rr;
87 16         28 my $before='';
88 16         22 my $idx = 0;
89 16         32 for my $r (@d){
90 90 100       267 if( $r->[0] eq 'u' ){
91 64         113 push(@rr,$org_a->[$idx]);
92 64         78 $before = '';
93             }
94             else{
95 26 100       52 push(@rr,WILDCARD) unless _isWILDCARD($before);
96 26         53 $before = WILDCARD;
97             }
98 90 100       227 $idx++ if $r->[0] ne '+';
99            
100             }
101 16         90 return \@rr;
102             }
103              
104              
105              
106             1;
107              
108             __END__