File Coverage

blib/lib/Regexp/Common/number.pm
Criterion Covered Total %
statement 55 55 100.0
branch 24 28 85.7
condition 13 21 61.9
subroutine 13 13 100.0
pod 0 4 0.0
total 105 121 86.7


line stmt bran cond sub pod time code
1             package Regexp::Common::number;
2              
3 72     72   849 use 5.10.0;
  72         290  
4              
5 72     72   397 use strict;
  72         160  
  72         1501  
6 72     72   354 use warnings;
  72         163  
  72         2004  
7 72     72   356 no warnings 'syntax';
  72         159  
  72         2241  
8              
9 72     72   364 use Config;
  72         148  
  72         2948  
10 72     72   394 use Regexp::Common qw /pattern clean no_defaults/;
  72         174  
  72         440  
11              
12             our $VERSION = '2017060201';
13              
14              
15             sub _croak {
16 4     4   23 require Carp;
17 4         325 goto &Carp::croak;
18             }
19              
20             my $digits = join ("", 0 .. 9, "A" .. "Z");
21              
22             sub int_creator {
23 13908     13908 0 31422 my $flags = $_ [1];
24             my ($sep, $group, $base, $places, $sign) =
25 13908         36384 @{$flags} {qw /-sep -group -base -places -sign/};
  13908         61880  
26              
27             # Deal with the bases.
28 13908 50 33     90995 _croak "Base must be between 1 and 36" unless $base >= 1 &&
29             $base <= 36;
30 13908         43956 my $chars = substr $digits, 0, $base;
31              
32 13908 50 33     88820 $sep = ',' if exists $flags -> {-sep} && !defined $flags -> {-sep};
33              
34 13908         30056 my $max = $group;
35 13908 100       40593 $max = $2 if $group =~ /^\s*(\d+)\s*,\s*(\d+)\s*$/;
36              
37 13908 100       46548 my $quant = $places ? "{$places}" : "+";
38              
39 13908 100       87837 return $sep ? qq {(?k:(?k:$sign)(?k:[$chars]{1,$max}} .
40             qq {(?:$sep} . qq {[$chars]{$group})*))}
41             : qq {(?k:(?k:$sign)(?k:[$chars]$quant))}
42             }
43              
44             sub real_creator {
45             my ($base, $places, $radix, $sep, $group, $expon, $sign) =
46 45     45 0 136 @{$_[1]}{-base, -places, -radix, -sep, -group, -expon, -sign};
  45         174  
47 45 100 100     246 _croak "Base must be between 1 and 36"
48             unless $base >= 1 && $base <= 36;
49             $sep = ',' if exists $_[1]->{-sep}
50 43 100 66     257 && !defined $_[1]->{-sep};
51 43 100 66     204 if ($base > 14 && $expon =~ /^[Ee]$/) {$expon = 'G'}
  14         28  
52 43 100       99 foreach ($radix, $sep, $expon) {$_ = "[$_]" if 1 == length}
  129         328  
53 43         111 my $chars = substr $digits, 0, $base;
54 43 100       389 return $sep
55             ? qq {(?k:(?i)(?k:$sign)(?k:(?=$radix?[$chars])} .
56             qq {(?k:[$chars]{1,$group}(?:(?:$sep)[$chars]{$group})*)} .
57             qq {(?:(?k:$radix)(?k:[$chars]{$places}))?)} .
58             qq {(?:(?k:$expon)(?k:(?k:$sign)(?k:[$chars]+))|))}
59             : qq {(?k:(?i)(?k:$sign)(?k:(?=$radix?[$chars])} .
60             qq {(?k:[$chars]*)(?:(?k:$radix)(?k:[$chars]{$places}))?)} .
61             qq {(?:(?k:$expon)(?k:(?k:$sign)(?k:[$chars]+))|))};
62             }
63             sub decimal_creator {
64             my ($base, $places, $radix, $sep, $group, $sign) =
65 3721     3721 0 8239 @{$_[1]}{-base, -places, -radix, -sep, -group, -sign};
  3721         10368  
66 3721 100 100     17006 _croak "Base must be between 1 and 36"
67             unless $base >= 1 && $base <= 36;
68             $sep = ',' if exists $_[1]->{-sep}
69 3719 50 33     16400 && !defined $_[1]->{-sep};
70 3719 100       6720 foreach ($radix, $sep) {$_ = "[$_]" if 1 == length}
  7438         15805  
71 3719         7127 my $chars = substr $digits, 0, $base;
72 3719 50       16284 return $sep
73             ? qq {(?k:(?i)(?k:$sign)(?k:(?=$radix?[$chars])} .
74             qq {(?k:[$chars]{1,$group}(?:(?:$sep)[$chars]{$group})*)} .
75             qq {(?:(?k:$radix)(?k:[$chars]{$places}))?))}
76             : qq {(?k:(?i)(?k:$sign)(?k:(?=$radix?[$chars])} .
77             qq {(?k:[$chars]*)(?:(?k:$radix)(?k:[$chars]{$places}))?))}
78             }
79              
80              
81             pattern name => [qw (num int -sep= -base=10 -group=3 -sign=[-+]?)],
82             create => \&int_creator,
83             ;
84              
85             pattern name => [qw (num real -base=10), '-places=0,',
86             qw (-radix=[.] -sep= -group=3 -expon=E -sign=[-+]?)],
87             create => \&real_creator,
88             ;
89              
90             pattern name => [qw (num decimal -base=10), '-places=0,',
91             qw (-radix=[.] -sep= -group=3 -sign=[-+]?)],
92             create => \&decimal_creator,
93             ;
94              
95             sub real_synonym {
96 288     288 0 679 my ($name, $base) = @_;
97             pattern name => ['num', $name, '-places=0,', '-radix=[.]',
98             '-sep=', '-group=3', '-expon=E', '-sign=[-+]?'],
99 17     17   30 create => sub {my %flags = (%{$_[1]}, -base => $base);
  17         108  
100 17         61 real_creator (undef, \%flags);
101             }
102 288         1611 ;
103             }
104              
105              
106             real_synonym (hex => 16);
107             real_synonym (dec => 10);
108             real_synonym (oct => 8);
109             real_synonym (bin => 2);
110              
111              
112             # 2147483647 == 2^31 - 1
113             # 9223372036854775807 == 2^63 - 1
114             pattern name => [qw (num square)],
115             create => sub {
116 72     72   680 use re 'eval';
  72         188  
  72         13552  
117             my $sixty_four_bits = $Config {use64bitint};
118             #
119             # CPAN testers claim it fails on 5.8.8 and darwin 9.0.
120             #
121             my $num = $sixty_four_bits
122             ? '0*(?:(?:9(?:[0-1][0-9]{17}' .
123             '|2(?:[0-1][0-9]{16}' .
124             '|2(?:[0-2][0-9]{15}' .
125             '|3(?:[0-2][0-9]{14}' .
126             '|3(?:[0-6][0-9]{13}' .
127             '|7(?:[0-1][0-9]{12}' .
128             '|20(?:[0-2][0-9]{10}' .
129             '|3(?:[0-5][0-9]{9}' .
130             '|6(?:[0-7][0-9]{8}' .
131             '|8(?:[0-4][0-9]{7}' .
132             '|5(?:[0-3][0-9]{6}' .
133             '|4(?:[0-6][0-9]{5}' .
134             '|7(?:[0-6][0-9]{4}' .
135             '|7(?:[0-4][0-9]{3}' .
136             '|5(?:[0-7][0-9]{2}' .
137             '|80(?:[0-6])))))))))))))))))|[1-8]?[0-9]{0,18})'
138             : '0*(?:2(?:[0-0][0-9]{8}' .
139             '|1(?:[0-3][0-9]{7}' .
140             '|4(?:[0-6][0-9]{6}' .
141             '|7(?:[0-3][0-9]{5}' .
142             '|4(?:[0-7][0-9]{4}' .
143             '|8(?:[0-2][0-9]{3}' .
144             '|3(?:[0-5][0-9]{2}' .
145             '|6(?:[0-3][0-9]{1}' .
146             '|4[0-7])))))))))|1?[0-9]{1,9}';
147             qr {($num)(?(?{length $^N && sqrt ($^N) == int sqrt ($^N)})|(?!))}
148             },
149             ;
150              
151             pattern name => [qw (num roman)],
152             create => '(?xi)(?=[MDCLXVI])
153             (?k:M{0,4}
154             (?:C[DM]|D?C{0,4})?
155             (?:X[LC]|L?X{0,4})?
156             (?:I[VX]|V?I{0,4})?)'
157             ;
158              
159             1;
160              
161             __END__