File Coverage

blib/lib/match/smart.pm
Criterion Covered Total %
statement 87 87 100.0
branch 60 64 93.7
condition 29 35 82.8
subroutine 22 22 100.0
pod 1 1 100.0
total 199 209 95.2


line stmt bran cond sub pod time code
1             package match::smart;
2              
3 2     2   14384 use 5.006001;
  2         7  
4 2     2   6 use strict;
  2         3  
  2         30  
5 2     2   6 use warnings;
  2         2  
  2         41  
6              
7 2     2   6 use B qw();
  2         2  
  2         25  
8 2     2   422 use Exporter::Tiny;
  2         2329  
  2         8  
9 2     2   183 use List::Util 1.33 qw(any all);
  2         33  
  2         142  
10 2     2   7 use Scalar::Util qw(blessed looks_like_number refaddr);
  2         2  
  2         131  
11              
12             BEGIN {
13 2     2   3 $match::smart::AUTHORITY = 'cpan:TOBYINK';
14 2         99 $match::smart::VERSION = '0.010';
15             }
16              
17             our @ISA = qw( Exporter::Tiny );
18             our @EXPORT = qw( M );
19             our @EXPORT_OK = qw( match );
20              
21             sub match
22             {
23 2     2   8 no warnings qw(uninitialized numeric);
  2         2  
  2         1417  
24            
25 1106     1106 1 87780 my ($a, $b, $seen) = @_;
26            
27 1106 100       1809 return(!defined $a) if !defined($b);
28 1063 50 66     2195 return !!$b->check($a) if blessed($b) && $b->isa("Type::Tiny");
29 1063 100 100     1914 return !!$b->MATCH($a, 1) if blessed($b) && $b->can("MATCH");
30 1053 50 66     1764 return eval 'no warnings; !!($a~~$b)' if blessed($b) && $] >= 5.010 && do { require overload; overload::Method($b, "~~") };
  60   66     202  
  60         108  
31            
32 1053 100 100     4508 if (blessed($b) and not $b->isa("Regexp"))
33             {
34 29         78 require Carp;
35 29         2405 Carp::croak("Smart matching a non-overloaded object breaks encapsulation");
36             }
37            
38 1024   100     1696 $seen ||= {};
39 1024         1010 my $refb = refaddr($b);
40 1024 100 100     2071 return refaddr($a)==$refb if $refb && $seen->{$refb}++;
41            
42 1021 100       1307 if (ref($b) eq q(ARRAY))
43             {
44 118 100       147 if (ref($a) eq q(ARRAY))
45             {
46 63 100       167 return !!0 unless @$a == @$b;
47 53         116 for my $i (0 .. $#$a)
48             {
49 690 100       718 return !!0 unless match($a->[$i], $b->[$i], $seen);
50             }
51 43         276 return !!1;
52             }
53            
54 55 100   15   145 return any { exists $a->{$_} } @$b if ref($a) eq q(HASH);
  15         98  
55 38 100   20   83 return any { $_ =~ $a } @$b if ref($a) eq q(Regexp);
  20         68  
56 32 100   15   74 return any { !defined($_) } @$b if !defined($a);
  15         53  
57 23     39   99 return any { match($a, $_) } @$b;
  39         56  
58             }
59            
60 903 100       1074 if (ref($b) eq q(HASH))
61             {
62 82 100       974 return match([sort map "$_", keys %$a], [sort map "$_", keys %$b])
63             if ref($a) eq q(HASH);
64            
65 55 100   33   157 return any { exists $b->{$_} } @$a if ref($a) eq q(ARRAY);
  33         138  
66 31 100   60   85 return any { $_ =~ $a } keys %$b if ref($a) eq q(Regexp);
  60         139  
67 21 100       46 return !!0 if !defined($a);
68 17         104 return exists $b->{$a};
69             }
70            
71 821 100       871 if (ref($b) eq q(CODE))
72             {
73 54 100   24   157 return all { !!$b->($_) } @$a if ref($a) eq q(ARRAY);
  24         274  
74 40 100   22   143 return all { !!$b->($_) } keys %$a if ref($a) eq q(HASH);
  22         224  
75 26         150 return $b->($a);
76             }
77            
78 767 100       826 if (ref($b) eq q(Regexp))
79             {
80 31 100   23   88 return any { $_ =~ $b } @$a if ref($a) eq q(ARRAY);
  23         90  
81 22 100   58   69 return any { $_ =~ $b } keys %$a if ref($a) eq q(HASH);
  58         132  
82 13         89 return $a =~ $b;
83             }
84            
85 736 50 66     1146 return !!$a->check($b) if blessed($a) && $a->isa("Type::Tiny");
86 736 100 100     1130 return !!$a->MATCH($b) if blessed($a) && $a->can("MATCH");
87 733 50 66     1050 return eval 'no warnings; !!($a~~$b)' if blessed($a) && $] >= 5.010 && do { require overload; overload::Method($a, "~~") };
  5   66     18  
  5         11  
88 733 100       910 return !defined($b) if !defined($a);
89 728 100       612 return $a == $b if _is_number($b);
90 593 100 100     529 return $a == $b if _is_number($a) && looks_like_number($b);
91            
92 583         1076 return $a eq $b;
93             }
94              
95             sub _is_number
96             {
97 1321     1321   868 my $value = shift;
98 1321 100       1736 return if ref $value;
99 1310         1948 my $flags = B::svref_2object(\$value)->FLAGS;
100 1310 100       3140 $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK );
101             }
102              
103             sub _generate_M
104             {
105 1     1   88 require Sub::Infix;
106 1         2 &Sub::Infix::infix(\&match);
107             }
108              
109             1;
110              
111             __END__