File Coverage

blib/lib/SHARYANTO/Array/Util.pm
Criterion Covered Total %
statement 49 49 100.0
branch 17 18 94.4
condition 5 6 83.3
subroutine 8 8 100.0
pod 2 2 100.0
total 81 83 97.5


line stmt bran cond sub pod time code
1             package SHARYANTO::Array::Util;
2              
3 1     1   15774 use 5.010;
  1         3  
  1         33  
4 1     1   5 use strict;
  1         1  
  1         30  
5 1     1   3 use warnings;
  1         1  
  1         30  
6 1     1   457 use experimental 'smartmatch';
  1         696  
  1         5  
7              
8 1     1   716 use Perinci::Sub::Util qw(gen_modified_sub);
  1         1673  
  1         344  
9              
10             require Exporter;
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(
13             match_array_or_regex
14             match_regex_or_array
15             split_array
16             );
17              
18             our $DATE = '2014-10-11'; # DATE
19             our $VERSION = '0.76'; # VERSION
20              
21             our %SPEC;
22              
23             my $_str_or_re = ['any*'=>{of=>['re*','str*']}];
24              
25             $SPEC{match_array_or_regex} = {
26             v => 1.1,
27             summary => 'Check whether an item matches (list of) values/regexes',
28             description => <<'_',
29              
30             This routine can be used to match an item against a regex or a list of
31             strings/regexes, e.g. when matching against an ACL.
32              
33             Since the smartmatch (`~~`) operator can already match against a list of strings
34             or regexes, this function is currently basically equivalent to:
35              
36             if (reg($haystack) eq 'ARRAY') {
37             return $needle ~~ @$haystack;
38             } else {
39             return $needle =~ /$haystack/;
40             }
41              
42             _
43             examples => [
44             {args=>{needle=>"abc", haystack=>["abc", "abd"]}, result=>1},
45             {args=>{needle=>"abc", haystack=>qr/ab./}, result=>1},
46             {args=>{needle=>"abc", haystack=>[qr/ab./, "abd"]}, result=>1},
47             ],
48             args_as => 'array',
49             args => {
50             needle => {
51             schema => ["str*"],
52             pos => 0,
53             req => 1,
54             },
55             haystack => {
56             # XXX checking this schema might actually take longer than matching
57             # the needle! so when arg validation is implemented, provide a way
58             # to skip validating this schema
59              
60             schema => ["any*" => {
61             of => [$_str_or_re, ["array*"=>{of=>$_str_or_re}]],
62             }],
63             pos => 1,
64             req => 1,
65             },
66             },
67             result_naked => 1,
68             };
69             sub match_array_or_regex {
70 11     11 1 256 my ($needle, $haystack) = @_;
71 11         14 my $ref = ref($haystack);
72 11 100       30 if ($ref eq 'ARRAY') {
    100          
    100          
73 5         38 return $needle ~~ @$haystack;
74             } elsif (!$ref) {
75 1         16 return $needle =~ /$haystack/;
76             } elsif ($ref eq 'Regexp') {
77 4         28 return $needle =~ $haystack;
78             } else {
79 1         10 die "Invalid haystack, must be regex or array of strings/regexes";
80             }
81             }
82              
83             gen_modified_sub(
84             output_name => 'match_regex_or_array',
85             base_name => 'match_array_or_regex',
86             summary => 'Alias for match_array_or_regex',
87             );
88              
89             sub split_array {
90 1     1   5 no strict 'refs';
  1         1  
  1         218  
91              
92 6     6 1 466 my ($pat, $ary, $limit) = @_;
93              
94 6 50       17 die "BUG: Second argument must be an array" unless ref($ary) eq 'ARRAY';
95 6 100       29 $pat = qr/\A\Q$pat\E\z/ unless ref($pat) eq 'Regexp';
96              
97 6         5 my @res;
98 6         5 my $num_elems = 0;
99 6         5 my $i = 0;
100             ELEM:
101 6         16 while ($i < @$ary) {
102 15         15 push @res, [];
103             COLLECT:
104 15         15 while (1) {
105 40 100       99 if ($ary->[$i] =~ $pat) {
106 10 100       24 push @res, [map { ${"$_"} } 1..@+-1] if @+ > 1;
  6         3  
  6         20  
107 10         11 last COLLECT;
108             }
109 30         24 push @{ $res[-1] }, $ary->[$i];
  30         42  
110 30 100       60 last ELEM unless ++$i < @$ary;
111             }
112 10         10 $num_elems++;
113             LIMIT:
114 10 100 66     25 if (defined($limit) && $limit > 0 && $num_elems >= $limit) {
      100        
115 1         4 push @{ $res[-1] }, $ary->[$_] for $i..(@$ary-1);
  2         3  
116 1         2 last ELEM;
117             }
118 9         13 $i++;
119             }
120              
121 6         40 return @res;
122             }
123              
124             1;
125             # ABSTRACT: Array-related utilities
126              
127             __END__