File Coverage

blib/lib/Number/Range/Regex/TrivialRange.pm
Criterion Covered Total %
statement 58 58 100.0
branch 25 28 89.2
condition n/a
subroutine 8 8 100.0
pod 0 2 0.0
total 91 96 94.7


line stmt bran cond sub pod time code
1             # Number::Range::Regex::TrivialRange
2             #
3             # Copyright 2012 Brian Szymanski. All rights reserved. This module is
4             # free software; you can redistribute it and/or modify it under the same
5             # terms as Perl itself.
6              
7             package Number::Range::Regex::TrivialRange;
8              
9             # one range, expressible in the form $header.$range.$trailer, where
10             # header = \d+
11             # range = [\d-\d]
12             # trailer = \\d+
13             # e.g. 12[3-8]\d\d
14              
15 14     14   88 use strict;
  14         28  
  14         714  
16 14     14   74 use vars qw ( @ISA @EXPORT @EXPORT_OK $VERSION );
  14         24  
  14         1446  
17             eval { require warnings; }; #it's ok if we can't load warnings
18              
19             require Exporter;
20 14     14   156 use base 'Exporter';
  14         24  
  14         1839  
21             @ISA = qw( Exporter Number::Range::Regex::SimpleRange );
22              
23             $VERSION = '0.32';
24              
25 14     14   97 use Number::Range::Regex::SimpleRange;
  14         42  
  14         878  
26 14     14   81 use Number::Range::Regex::Util ':all';
  14         26  
  14         5356  
27 14     14   87 use Number::Range::Regex::Util::inf qw ( neg_inf pos_inf _is_negative );
  14         26  
  14         32132  
28              
29             sub new {
30 976     976 0 4785 my ($class, $min, $max, $passed_opts) = @_;
31              
32 976         2553 my $opts = option_mangler( $passed_opts );
33              
34 976         1977 my $base = $opts->{base};
35 976         2477 my $base_digits = $opts->{base_digits} = base_digits($base);
36 976         3657 my $base_max = $opts->{base_max} = substr($base_digits, -1);
37 976         3861 my $base_digits_regex = $opts->{base_digits_regex} = _calculate_digit_range( 0, $base_max, $base_digits );
38              
39 976         8793 return bless { min => $min, max => $max, opts => $opts }, $class;
40             }
41              
42             sub regex {
43 5483     5483 0 9010 my ($self, $passed_opts) = @_;
44              
45 5483         17678 my $opts = option_mangler( $self->{opts}, $passed_opts );
46              
47 5483 100       15137 my $zeroes_maybe = $opts->{no_leading_zeroes} ? '' : '0*';
48              
49 5483 100       20657 if( _is_negative( $self->{min} ) ) {
50 134         296 my $pmin = abs $self->{max};
51             # -'-inf' == 'inf' according to perl. that's no good for us
52             #TODO: is the above still true with Util/inf.pm ?
53 134 100       337 my $pmax = ($self->{min} == neg_inf) ? pos_inf : abs $self->{min};
54 134         663 my $re_part = Number::Range::Regex::TrivialRange->new( $pmin, $pmax )->
55             regex( { no_leading_zeroes => 1, no_sign => 1 } );
56 134         3093 return qr/-$zeroes_maybe$re_part/;
57             } else {
58 5349 100       19210 my $sign_maybe = $opts->{no_sign} ? '' : '[+]?';
59 5349 100       13378 if($self->{min} eq $self->{max}) {
60 512         12951 return qr/$sign_maybe$zeroes_maybe$self->{min}/;
61             } else {
62             #note: because of the nature of a trivial range, max must also be positive
63 4837         7982 my $ndigits = length $self->{min};
64 4837 100       12977 if($self->{max} == pos_inf) {
65             # for a trivial range extending to +inf, min must be /^10+$/
66 77         143 my $trailer;
67 77 100       159 if($opts->{no_leading_zeroes}) {
68 55 50       104 die "internal error" if $ndigits <= 1;
69 55         69 $ndigits--; #change the first '\d' to '[1-9]'
70 55         110 $trailer = "[1-$opts->{base_max}]";
71 55         73 $zeroes_maybe = '';
72             } else {
73 22         36 $trailer = '';
74             }
75 77 100       226 $trailer .= $ndigits == 0 ? '' :
    50          
76             $ndigits == 1 ? $opts->{base_digits_regex} :
77             "$opts->{base_digits_regex}\{$ndigits,\}";
78 77         1628 return qr/$sign_maybe$zeroes_maybe$trailer/;
79             } else {
80 4760 50       12848 die "internal error" if $ndigits != length $self->{max};
81 4760         6238 my $nsame = 0;
82 4760         10539 for(; $nsame<$ndigits; $nsame++) {
83 10700 100       45902 last if substr($self->{min}, $nsame, 1) ne substr($self->{max}, $nsame, 1);
84             }
85 4760         8899 my $static_header = substr($self->{min}, 0, $nsame);
86 4760         7211 my $dig_min = substr($self->{min}, $nsame, 1);
87 4760         13645 my $dig_max = substr($self->{max}, $nsame, 1);
88 4760         10755 my $digit_range = "[$dig_min-$dig_max]";
89 4760         7569 my $extra_digits = $ndigits-$nsame-1;
90 4760 100       16084 my $trailer = $extra_digits == 0 ? '' :
    100          
91             $extra_digits == 1 ? $opts->{base_digits_regex} :
92             "$opts->{base_digits_regex}\{$extra_digits\}";
93 4760         172922 return qr/$sign_maybe$zeroes_maybe$static_header$digit_range$trailer/;
94             }
95             }
96             }
97             }
98              
99             # touches/union/intersect/subtract/etc. inherit from SimpleRange.pm
100              
101             1;
102