File Coverage

blib/lib/String/Util/Match.pm
Criterion Covered Total %
statement 28 28 100.0
branch 14 14 100.0
condition n/a
subroutine 5 5 100.0
pod 2 2 100.0
total 49 49 100.0


line stmt bran cond sub pod time code
1             package String::Util::Match;
2              
3 1     1   69266 use strict;
  1         11  
  1         29  
4 1     1   10 use warnings;
  1         2  
  1         26  
5              
6 1     1   4 use Exporter qw(import);
  1         2  
  1         604  
7              
8             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
9             our $DATE = '2023-06-19'; # DATE
10             our $DIST = 'String-Util-Match'; # DIST
11             our $VERSION = '0.003'; # VERSION
12              
13             our @EXPORT_OK = qw(
14             match_array_or_regex
15             num_occurs
16             );
17              
18             our %SPEC;
19              
20             $SPEC{':package'} = {
21             v => 1.1,
22             summary => 'String utilities related to matching',
23             };
24              
25             my $_str_or_re = ['any*'=>{of=>['re*','str*']}];
26              
27             $SPEC{match_array_or_regex} = {
28             v => 1.1,
29             summary => 'Check whether an item matches (list of) values/regexes',
30             description => <<'_',
31              
32             This routine can be used to match an item against a regex or a list of
33             strings/regexes, e.g. when matching against an ACL.
34              
35             Since the smartmatch (`~~`) operator can already match against a list of strings
36             or regexes, this function is currently basically equivalent to:
37              
38             if (ref($haystack) eq 'ARRAY') {
39             return $needle ~~ @$haystack;
40             } else {
41             return $needle =~ /$haystack/;
42             }
43              
44             except that the smartmatch operator covers more cases and is currently
45             deprecated in the current perl versions and might be removed in future versions.
46              
47             _
48             examples => [
49             {args=>{needle=>"abc", haystack=>["abc", "abd"]}, result=>1},
50             {args=>{needle=>"abc", haystack=>qr/ab./}, result=>1},
51             {args=>{needle=>"abc", haystack=>[qr/ab./, "abd"]}, result=>1},
52             ],
53             args_as => 'array',
54             args => {
55             needle => {
56             schema => ["str*"],
57             pos => 0,
58             req => 1,
59             },
60             haystack => {
61             # XXX checking this schema might actually take longer than matching
62             # the needle! so when arg validation is implemented, provide a way
63             # to skip validating this schema
64              
65             schema => ["any*" => {
66             of => [$_str_or_re, ["array*"=>{of=>$_str_or_re}]],
67             }],
68             pos => 1,
69             req => 1,
70             },
71             },
72             result_naked => 1,
73             };
74             sub match_array_or_regex {
75 9     9 1 1128 my ($needle, $haystack) = @_;
76 9         18 my $ref = ref($haystack);
77 9 100       30 if ($ref eq 'ARRAY') {
    100          
    100          
78 5         8 for (@$haystack) {
79 9 100       19 if (ref $_ eq 'Regexp') {
80 2 100       15 return 1 if $needle =~ $_;
81             } else {
82 7 100       25 return 1 if $needle eq $_;
83             }
84             }
85 2         9 return 0;
86             } elsif (!$ref) {
87 1         17 return $needle =~ /$haystack/;
88             } elsif ($ref eq 'Regexp') {
89 2         16 return $needle =~ $haystack;
90             } else {
91 1         10 die "Invalid haystack, must be regex or array of strings/regexes";
92             }
93             }
94              
95             $SPEC{num_occurs} = {
96             v => 1.1,
97             summary => "Count how many times a substring occurs (or a regex pattern matches) a string",
98             args => {
99             string => {
100             schema => 'str*',
101             req => 1,
102             pos => 0,
103             },
104             substring => {
105             schema => $_str_or_re,
106             req => 1,
107             pos => 1,
108             },
109             },
110             args_as => 'array',
111             result => {
112             schema => 'uint*',
113             },
114             result_naked => 1,
115             };
116             sub num_occurs {
117 4     4 1 2398 my ($string, $substr) = @_;
118              
119 4 100       14 if (ref $substr eq 'Regexp') {
120 1         1 my $n = 0;
121 1         16 $n++ while $string =~ /$substr/g;
122 1         4 return $n;
123             } else {
124 3         4 my $n = 0;
125 3         50 $n++ while $string =~ /\Q$substr\E/g;
126 3         15 return $n;
127             }
128             }
129              
130             1;
131             # ABSTRACT: String utilities related to matching
132              
133             __END__