File Coverage

blib/lib/Range/Object/Extension.pm
Criterion Covered Total %
statement 57 57 100.0
branch 4 4 100.0
condition 3 3 100.0
subroutine 16 16 100.0
pod 3 3 100.0
total 83 83 100.0


line stmt bran cond sub pod time code
1             package Range::Object::Extension;
2              
3             # This is basically what common::sense does, but without the pragma itself
4             # to remain compatible with Perls older than 5.8
5              
6 1     1   45231 use strict;
  1         3  
  1         628  
7              
8 1     1   7 no warnings;
  1         2  
  1         75  
9 1         68 use warnings qw(FATAL closed internal debugging pack malloc portable
10             prototype inplace io pipe unpack deprecated glob digit
11 1     1   9 printf reserved taint closure semicolon);
  1         2  
12 1     1   3 no warnings qw(exec newline unopened);
  1         2  
  1         22  
13              
14 1     1   6 use Carp;
  1         1  
  1         105  
15 1     1   5 use List::Util qw( first );
  1         2  
  1         112  
16              
17 1     1   4 use base qw(Range::Object);
  1         4  
  1         712  
18              
19             # Overload definitions
20              
21 1         5 use overload q{""} => 'stringify_collapsed',
22 1     1   1956 fallback => 1;
  1         1402  
23              
24             ### PUBLIC INSTANCE METHOD ###
25             #
26             # Returns regex for matching phone digit strings.
27             #
28              
29             sub pattern {
30 370     370 1 1612 return qr/
31             # Can't have anything but space or dash before digits
32             (?
33              
34             # First digit is mandatory, it can be *, # or 0-9
35             [*#0-9]
36              
37             # Up to 14 digits can follow
38             [0-9]{0,14}
39              
40             # Can't have dash, space or end of line after digits
41             (?=
42             (?: [- ] | \z )
43             )
44             /xms;
45             }
46              
47             ### PUBLIC INSTANCE METHOD ###
48             #
49             # Returns regex that is used to separate items in a range list.
50             # Default for Extensions is comma (,) or semicolon (;).
51             #
52              
53             sub separator {
54 104     104 1 350 return qr/
55             # Comma or semicolon
56             [,;]
57              
58             # If there is any whitespace, eat it all up
59             \s*
60             /xms;
61             }
62              
63             ### PUBLIC INSTANCE METHOD ###
64             #
65             # Returns default range delimiter for current class.
66             #
67              
68 308     308 1 668 sub delimiter { '-' }
69              
70             ############## PRIVATE METHODS BELOW ##############
71              
72             ### PRIVATE INSTANCE METHOD ###
73             #
74             # Returns default list separator for use with stringify() and
75             # stringify_collapsed()
76             #
77              
78 18     18   74 sub _list_separator { q{,} }
79              
80             ### PRIVATE INSTANCE METHOD ###
81             #
82             # Expands a list of phone digit strings.
83             #
84              
85             my $EXPLODE_REGEX
86             = qr/\A
87             qw\( # Literal 'qw('
88             ([#*]) # Match and save first * or #
89             \d+ # Then match some digits...
90             \) # Closing parentheses for 1st qw()
91              
92             \.\. # Literal '..'
93              
94             qw\( # Literal 'qw('
95             \1 # Match the * or # we saved above
96             \d+ # Some digits again
97             \) # Close parentheses for 2nd qw()
98             \z/xms;
99              
100             sub _explode_range {
101 266     266   484 my ($self, $string) = @_;
102              
103             # First quote and delimit the values
104 266         481 my $pattern = $self->pattern;
105 266         602 for ( $string ) {
106 266         685 s/\s+//g;
107 266         3489 s/ ( $pattern ) /qw($1)/gx;
108 266         1144 s/ qw\( (.*?) \) - qw\( (.*?) \) /qw($1)..qw($2)/x;
109             };
110              
111             # Then save leading * or #, if it's there
112 266         373 my $prefix = q{};
113 266 100       2500 if ($string =~ $EXPLODE_REGEX) {
114 17         38 $prefix = $1;
115 17         194 $string =~ s/\Q$prefix\E//g;
116             };
117              
118             # Expand the list and add leading prefix back
119 266         884 my @items = map { $prefix . $_ }
  439         9470  
120             $self->SUPER::_explode_range($string);
121              
122 266         1465 return @items;
123             }
124              
125             ### PRIVATE INSTANCE METHOD ###
126             #
127             # Tests if a single value is within boundaries of collapsed range item.
128             #
129              
130             sub _is_in_range_hashref {
131 288     288   389 my ($self, $range_ref, $value) = @_;
132              
133             # If length is different, $value can't be in range
134 288 100       921 return unless length($value) == length($range_ref->{start});
135              
136             # Unpack for brevity
137 118         182 my $start = $range_ref->{start};
138 118         167 my $end = $range_ref->{end};
139              
140             # Capture leading [*#], if any, and remove it from digit strings
141 118         290 my $prefix = $start =~ / \A ([*#]) /xms;
142 118         585 $start =~ s/ \A $prefix//xms;
143 118         389 $end =~ s/ \A $prefix//xms;
144 118         597 $value =~ s/ \A $prefix//xms;
145              
146             # Finally, compare strings
147 118   100     1342 return ( ($value ge $start) && ($value le $end) );
148             }
149              
150             ### PRIVATE INSTANCE METHOD ###
151             #
152             # Tests if two values are equal using string comparison.
153             #
154              
155             sub _equal_value {
156 770     770   1202 my ($self, $first, $last) = @_;
157              
158 770         2409 return !!($first eq $last);
159             }
160              
161             ### PRIVATE INSTANCE METHOD ###
162             #
163             # Tests if two values are consequent.
164             #
165              
166             sub _next_in_range {
167 102     102   137 my ($self, $first, $last) = @_;
168              
169             # First save leading [*#] and remove it
170 102         481 my ($prefix) = $first =~ / \A ([*#]) /xms;
171 102         172 $first =~ s/ \A [*#] //xms;
172              
173             # Increment the value and add prefix back
174 102         184 $first = $prefix . (++$first);
175              
176 102         355 return !!($first eq $last);
177             }
178              
179             1;
180              
181             __END__