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   58050 use strict;
  1         11  
  1         28  
7              
8 1     1   4 no warnings;
  1         2  
  1         51  
9 1         67 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   5 no warnings qw(exec newline unopened);
  1         2  
  1         26  
13              
14 1     1   4 use Carp;
  1         2  
  1         51  
15 1     1   5 use List::Util qw( first );
  1         2  
  1         86  
16              
17 1     1   6 use base qw(Range::Object);
  1         1  
  1         4439  
18              
19             # Overload definitions
20              
21 1         9 use overload q{""} => 'stringify_collapsed',
22 1     1   990 fallback => 1;
  1         921  
23              
24             ### PUBLIC INSTANCE METHOD ###
25             #
26             # Returns regex for matching phone digit strings.
27             #
28              
29             sub pattern {
30 370     370 1 971 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 266 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 559 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   52 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   454 my ($self, $string) = @_;
102              
103             # First quote and delimit the values
104 266         418 my $pattern = $self->pattern;
105 266         505 for ( $string ) {
106 266         449 s/\s+//g;
107 266         1770 s/ ( $pattern ) /qw($1)/gx;
108 266         775 s/ qw\( (.*?) \) - qw\( (.*?) \) /qw($1)..qw($2)/x;
109             };
110              
111             # Then save leading * or #, if it's there
112 266         418 my $prefix = q{};
113 266 100       785 if ($string =~ $EXPLODE_REGEX) {
114 17         33 $prefix = $1;
115 17         141 $string =~ s/\Q$prefix\E//g;
116             };
117              
118             # Expand the list and add leading prefix back
119 266         672 my @items = map { $prefix . $_ }
  439         993  
120             $self->SUPER::_explode_range($string);
121              
122 266         916 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   424 my ($self, $range_ref, $value) = @_;
132              
133             # If length is different, $value can't be in range
134 288 100       617 return unless length($value) == length($range_ref->{start});
135              
136             # Unpack for brevity
137 118         168 my $start = $range_ref->{start};
138 118         172 my $end = $range_ref->{end};
139              
140             # Capture leading [*#], if any, and remove it from digit strings
141 118         261 my $prefix = $start =~ / \A ([*#]) /xms;
142 118         458 $start =~ s/ \A $prefix//xms;
143 118         312 $end =~ s/ \A $prefix//xms;
144 118         310 $value =~ s/ \A $prefix//xms;
145              
146             # Finally, compare strings
147 118   100     587 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   1141 my ($self, $first, $last) = @_;
157              
158 770         1540 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   148 my ($self, $first, $last) = @_;
168              
169             # First save leading [*#] and remove it
170 102         185 my ($prefix) = $first =~ / \A ([*#]) /xms;
171 102         156 $first =~ s/ \A [*#] //xms;
172              
173             # Increment the value and add prefix back
174 102         157 $first = $prefix . (++$first);
175              
176 102         232 return !!($first eq $last);
177             }
178              
179             1;
180              
181             __END__