File Coverage

blib/lib/Config/INI/RefVars/Builtins.pm
Criterion Covered Total %
statement 82 85 96.4
branch 46 64 71.8
condition 17 25 68.0
subroutine 23 24 95.8
pod 1 1 100.0
total 169 199 84.9


line stmt bran cond sub pod time code
1             # lib/Config/INI/RefVars/Builtins.pm
2             package Config::INI::RefVars::Builtins;
3              
4 31     31   472 use 5.010;
  31         80  
5 31     31   133 use strict;
  31         57  
  31         931  
6 31     31   119 use warnings;
  31         54  
  31         1533  
7              
8 31     31   179 use File::Spec::Functions;# qw(catdir catfile);
  31         61  
  31         2705  
9 31     31   154 use File::Basename qw(dirname basename);
  31         55  
  31         33183  
10              
11              
12             our $VERSION = '1.03';
13              
14              
15             sub default_dispatch_table {
16             return {
17 188     188 1 2950 catdir => \&File::Spec::Functions::catdir,
18             catfile => \&File::Spec::Functions::catfile,
19             catpath => \&_catpath,
20             ignore => \&_ignore,
21             concat => \&_concat,
22             join => \&_join,
23             substr => \&_substr,
24             x => \&_x,
25             'and' => \&_and,
26             'or' => \&_or,
27             'if' => \&_if,
28             s => \&_s,
29             tr => \&_tr,
30             m => \&_m,
31             not => \&_not,
32             eq => \&_eq,
33             dirname => \&dirname,
34             basename => \&basename,
35             };
36             }
37              
38             sub _catpath {
39 0 0   0   0 die("catpath: expected 3 arguments\n") unless @_ == 3;
40 0         0 return File::Spec::Functions::catpath(@_);
41             }
42              
43              
44             sub _clean_error {
45 2     2   6 my ($error) = @_;
46 2         4 chomp($error);
47 2         16 $error =~ s/\s+at\s+\S+\s+line\s+\d+\.?\z//;
48 2         13 return $error;
49             }
50              
51              
52             sub _ignore {
53 12     12   33 return "";
54             }
55              
56              
57             sub _concat {
58 9     9   35 return join("", @_);
59             }
60              
61              
62             sub _join {
63 14 50   14   57 return @_ ? join(shift(@_), @_) : "";
64             }
65              
66              
67             sub _substr {
68 8 100 100 8   132 die("substr: expected 2 or 3 arguments\n") if @_ < 2 || @_ > 3;
69              
70 5         7 my $warning = "";
71              
72             local $SIG{__WARN__} = sub {
73 2     2   31 $warning = _clean_error($_[0]);
74 5         28 };
75              
76 5 100       42 my $result = @_ == 2
77             ? substr($_[0], $_[1]) : substr($_[0], $_[1], $_[2]);
78              
79 5 100       75 die("substr: $warning\n") if $warning ne "";
80 3         17 return $result;
81             }
82              
83              
84             sub _x {
85 3 50   3   7 die("x: expected 2 arguments\n") if @_ != 2;
86              
87 3         6 my ($str, $n) = @_;
88              
89 3 50       8 die("x: second argument must be a non-negative integer\n")
90             unless $n =~ /^\+?[0-9]+$/;
91              
92 3         11 return $str x $n;
93             }
94              
95              
96             sub _and {
97 5     5   8 foreach my $arg (@_) {
98 8 100       16 return "" if $arg eq "";
99             }
100 3 100       9 return @_ ? $_[-1] : "";
101             }
102              
103              
104             sub _or {
105 5     5   7 foreach my $arg (@_) {
106 8 100       18 return $arg if $arg ne "";
107             }
108 2         5 return "";
109             }
110              
111              
112             sub _if {
113 6 50 33 6   20 die("if: expected 2 or 3 arguments\n") if @_ < 2 || @_ > 3;
114 6 100 100     26 return $_[0] ne "" ? $_[1] : ($_[2] // "");
115             }
116              
117              
118             sub _s {
119 10 100 66 10   44 die("s: expected 3 or 4 arguments\n") if @_ < 3 || @_ > 4;
120              
121 9         23 my ($str, $pattern, $replacement, $mods) = @_;
122 9   100     19 $mods //= "";
123              
124 9 100       66 die("s: unsupported modifier '$mods'\n") if $mods !~ /^[gimsx]*$/;
125              
126 7 100       51 die("s: regex code blocks are not allowed\n") if $pattern =~ /\(\?\??\{/;
127              
128 5         11 my $global = $mods =~ s/g//g;
129 5 100       6 my $re = eval { $mods eq "" ? qr/$pattern/ : qr/(?$mods:$pattern)/; };
  5         58  
130 5 50       11 die("s: ", _clean_error($@), "\n") if $@;
131              
132 5 100       8 if ($global) {
133 2         18 $str =~ s/$re/$replacement/g;
134             }
135             else {
136 3         21 $str =~ s/$re/$replacement/;
137             }
138 5         41 return $str;
139             }
140              
141              
142             sub _pick_tr_delim {
143 5     5   6 my @values = @_;
144              
145 31     31   225 no warnings 'qw';
  31         74  
  31         17349  
146 5         9 foreach my $delim (qw(| ! / : ; # ~ @ % ^ * + = ?)) {
147 5 50 50     6 return $delim if !grep { index($_ // "", $delim) >= 0 } @values;
  10         59  
148             }
149 0         0 die("tr: no safe delimiter found\n");
150             }
151              
152              
153             sub _tr {
154 8 100 66 8   43 die("tr: expected 3 or 4 arguments\n") if @_ < 3 || @_ > 4;
155              
156 7         14 my ($str, $search, $replacement, $mods) = @_;
157 7   100     15 $mods //= "";
158              
159 7 100       54 die("tr: unsupported modifier '$mods'\n") if $mods !~ /^[cds]*$/;
160              
161 5         10 my $delim = _pick_tr_delim($search, $replacement);
162 5         11 my $code = "\$str =~ tr${delim}${search}${delim}${replacement}${delim}${mods};";
163 5 50       294 eval "$code; 1" or die("tr: ", _clean_error($@), "\n");
164              
165 5         26 return $str;
166             }
167              
168              
169             sub _m {
170 6 50 33 6   16 die("m: expected 2 or 3 arguments\n") if @_ < 2 || @_ > 3;
171              
172 6         11 my ($str, $pattern, $mods) = @_;
173 6   50     20 $mods //= "";
174              
175 6 50       16 die("m: unsupported modifier '$mods'\n") if $mods !~ /^[imsx]*$/;
176 6 50       10 die("m: regex code blocks are not allowed\n") if $pattern =~ /\(\?\??\{/;
177              
178 6 50       8 my $re = eval { $mods eq "" ? qr/$pattern/ : qr/(?$mods:$pattern)/; };
  6         73  
179 6 50       13 die("m: ", _clean_error($@), "\n") if $@;
180              
181 6 100       59 return $str =~ $re ? "1" : "";
182             }
183              
184              
185             sub _not {
186 1 50   1   4 die("not: expected 1 argument\n") if @_ != 1;
187 1 50       4 return $_[0] eq "" ? "1" : "";
188             }
189              
190              
191             sub _eq {
192 1 50   1   3 die("eq: expected 2 arguments\n") if @_ != 2;
193 1 50       4 return $_[0] eq $_[1] ? "1" : "";
194             }
195              
196             1;
197              
198              
199             __END__