File Coverage

blib/lib/Config/Maker/Path.pm
Criterion Covered Total %
statement 74 77 96.1
branch 43 50 86.0
condition 5 5 100.0
subroutine 18 18 100.0
pod 0 9 0.0
total 140 159 88.0


line stmt bran cond sub pod time code
1             package Config::Maker::Path;
2              
3 9     9   54 use utf8;
  9         16  
  9         54  
4 9     9   248 use warnings;
  9         18  
  9         217  
5 9     9   51 use strict;
  9         16  
  9         350  
6              
7 9     9   50 use Carp;
  9         17  
  9         1339  
8              
9             require Config::Maker::Path::Root;
10             require Config::Maker::Path::AnyPath;
11             require Config::Maker::Path::This;
12             require Config::Maker::Path::Parent;
13             require Config::Maker::Path::Meta;
14              
15             use overload
16 9         103 'cmp' => \&Config::Maker::truecmp,
17             '<=>' => \&Config::Maker::truecmp,
18             '""' => 'str',
19 9     9   65 fallback => 1;
  9         19  
20              
21             our $parser = $Config::Maker::parser;
22              
23             our %paths; # Cache for paths...
24              
25             our %checks; # For [$if$] directive...
26              
27             # Coversion of expressions to regexes and coderefs:
28              
29             sub _glob_to_re {
30 1976     1976   4256 local $_ = $_[0];
31              
32 1976 100       15022 /[.+^\-\$]/ ? "\\$_" :
    100          
    100          
    100          
    100          
33             /\{/ ? "(?:" :
34             /\}/ ? ")" :
35             /\*/ ? ".*" :
36             /\?/ ? "." :
37             $_;
38             }
39              
40             sub glob_to_re {
41 596     596 0 1270 my ($self, $patt) = @_;
42              
43 596 100       2771 return qr/.*/ if (!defined $patt);
44 300 50       1026 return qr/$patt/ if ($patt =~ s/^RE://);
45              
46 300 50       1581 $patt =~ s/([^\\])|(\\.)/defined $1 ? _glob_to_re($1) : $2/eg;
  1976         6545  
47 300         6361 qr/^$patt$/;
48             }
49              
50             sub code_to_sub {
51 298     298 0 668 my ($self, $code) = @_;
52              
53 298 100   987   2029 return sub { 1; } unless $code;
  987         5274  
54 6         57 Config::Maker::DBG("Code-to-sub: qq{$code}");
55 6         34 $code =~ s/\A\(//;
56 6         32 $code =~ s/\)\Z//;
57 6         44 my $sub = Config::Maker::exe("sub { $code; };");
58 6         28 return $sub;
59             }
60              
61             # Common argument parsing:
62              
63             sub bhash {
64 361     361 0 18586 my ($class, $keys) = splice @_, 0, 2;
65 361 50       1729 $keys = +{ map { $_ => 1; } @$keys } if(ref($keys) eq 'ARRAY');
  1255         4112  
66 361 50       1928 my %hash = (ref($_[0]) eq 'HASH' ? %{$_[0]} : @_);
  0         0  
67              
68 361         1427 for(keys %hash) {
69 336 50       1291 croak "Unknown argument $_"
70             unless $keys->{$_};
71             }
72 361         3011 bless \%hash, $class;
73             }
74              
75             # Public interface:
76              
77             sub new {
78 298     298 0 2063 my $self = shift->bhash([qw/-type -value -code -tail/], @_);
79              
80 298         1861 $self->{-text} = '';
81 298 100       1650 $self->{-text} .= $self->{-type} if $self->{-type};
82 298 100       1027 $self->{-text} .= ':' . $self->{-value} if $self->{-value};
83 298 100       1659 $self->{-text} .= $self->{-code} if $self->{-code};
84              
85 298         1451 $self->{-type} = $self->glob_to_re($self->{-type});
86 298         1555 $self->{-value} = $self->glob_to_re($self->{-value});
87 298         1772 $self->{-code} = $self->code_to_sub($self->{-code});
88              
89 298         1434 return $self;
90             }
91              
92             sub make {
93 1303     1303 0 2679 my ($class, $text) = @_;
94             #D# DBG "Making path from `$text'";
95 1303 100       9859 return $text if UNIVERSAL::isa($text, __PACKAGE__);
96 1183 100       33136 return $paths{$text} if($paths{$text});
97 269 50       2607 $paths{$text} = $parser->path_whole($text)
98             or croak "Invalid path: $text";
99             }
100              
101             sub match {
102 2054     2054 0 3543 my ($self, $from) = @_;
103              
104 3990 100 100     25842 grep {
105             # no warnings 'uninitialized'; # NOTEME
106 2054         6264 ($_->{-type} =~ /$self->{-type}/)
107             && ($_->{-value} =~ /$self->{-value}/)
108             && ($self->{-code}->())
109 2054         2521 } @{$from->{-children}}
110             }
111              
112             sub find {
113 2197     2197 0 5371 my ($self, $from, $gather) = @_;
114 2197   100     9394 $gather ||= [];
115              
116             #D# DBG "Pattern $self find in ".$from->id;
117 2197 100       7080 if($self->{-tail}) {
118 75         351 $self->{-tail}->find($_, $gather) for $self->match($from);
119             } else {
120 2122         5597 push @$gather, ($self->match($from));
121             }
122             #D# DBG "Returning: `" . join("', `", map $_->id, @$gather) . "'";
123              
124 2197         8429 return $gather;
125             }
126              
127             sub text {
128 2866     2866 0 32856 $_[0]->{-text};
129             }
130              
131             sub str {
132 2903     2903 0 12075 my ($self) = @_;
133 2903 100       9810 $self->text . ($self->{-tail} ? '/' . $self->{-tail}->str : '');
134             }
135              
136             sub _findtimes {
137 26 50   26   105 confess "$_[1] can't ->find" unless UNIVERSAL::can($_[1], 'find');
138 26         63 my $r = $_[1]->find($_[0]);
139 26 100       99 return 0 if @$r < $_[2];
140 13 100       38 return 1 if @_ == 3;
141 9 100       40 return 0 if @$r > $_[3];
142 4         17 return 1;
143             }
144              
145             BEGIN { # Constants must be done early enough...
146             %checks = (
147 7         21 none => sub { _findtimes($_, @_, 0,0); },
148 0         0 unique => sub { _findtimes($_, @_,0,1); },
149 7         18 one => sub { _findtimes($_, @_,1,1); },
150 12         31 exists => sub { _findtimes($_, @_,1); },
151 0         0 any => sub { 1; },
152 9     9   23607 );
153             }
154              
155             1;
156              
157             __END__