File Coverage

blib/lib/Brick/Numbers.pm
Criterion Covered Total %
statement 49 59 83.0
branch 3 16 18.7
condition 7 24 29.1
subroutine 14 19 73.6
pod 0 1 0.0
total 73 119 61.3


line stmt bran cond sub pod time code
1             package Brick::Numbers;
2 5     5   27 use strict;
  5         6  
  5         175  
3              
4 5     5   18 use base qw(Exporter);
  5         8  
  5         471  
5 5     5   22 use vars qw($VERSION);
  5         8  
  5         265  
6              
7             $VERSION = '0.905';
8              
9             package Brick::Bucket;
10 5     5   20 use strict;
  5         7  
  5         394  
11              
12              
13             =encoding utf8
14              
15             =head1 NAME
16              
17             Brick - This is the description
18              
19             =head1 SYNOPSIS
20              
21             use Brick;
22              
23             =head1 DESCRIPTION
24              
25             =cut
26              
27             =over 4
28              
29             =item number_within_range( HASHREF )
30              
31             Hash fields:
32              
33             minimum - the lower bound
34             maximum - the higher bound
35             inclusive - true includes bounds, false excludes bounds
36              
37             =cut
38              
39             sub number_within_range {
40 2     2 0 4 my( $bucket, $setup ) = @_;
41              
42 2         4 my @missing = sort grep { ! defined $setup->{$_} } qw( minimum maximum );
  4         9  
43              
44 2 50       3 if( @missing ) {
45 5     5   22 no warnings 'uninitialized';
  5         6  
  5         1747  
46 0 0       0 croak( sprintf "number_within_range missing %s%s attibute%s",
    0          
47             $missing[0],
48             $missing[1] ? " and $missing[1]" : '',
49             $missing[1] ? 's' : ''
50             );
51             }
52              
53 2         6 my $format_sub = $bucket->_is_decimal_integer( $setup );
54              
55             my $range_sub = $setup->{inclusive} ?
56 2 100       8 $bucket->_inclusive_within_numeric_range( $setup )
57             :
58             $bucket->_exclusive_within_numeric_range( $setup );
59              
60 2         5 my $composed_sub = $bucket->__compose_satisfy_all( $format_sub, $range_sub );
61              
62 2         5 $bucket->__make_constraint( $composed_sub, $setup );
63             }
64              
65             sub _is_only_decimal_digits {
66 0     0   0 my( $bucket, $setup ) = @_;
67              
68 0         0 my @caller = $bucket->__caller_chain_as_list();
69              
70             my $sub = $bucket->_matches_regex( {
71             description => "The $setup->{field} value only has decimal digits",
72             field => $setup->{field},
73 0   0     0 name => $setup->{name} || $caller[0]{'sub'},
74             regex => qr/
75             \A
76             \d+ # digits only
77             \z
78             /x,
79             } );
80              
81 0         0 my $composed = $bucket->__compose_satisfy_all( $sub );
82              
83             $bucket->add_to_bucket( {
84 0         0 name => $caller[0]{'sub'},
85             code => $composed,
86             } );
87             }
88              
89             sub _is_decimal_integer {
90 2     2   3 my( $bucket, $setup ) = @_;
91              
92 2         5 my @caller = $bucket->__caller_chain_as_list();
93              
94 5     5   30 no warnings 'uninitialized';
  5         7  
  5         4945  
95             my $sub = $bucket->_matches_regex( {
96             description => "The $setup->{field} is an integer in base 10",
97             field => $setup->{field},
98 2   33     20 name => $setup->{name} || $caller[0]{'sub'},
99             regex => qr/
100             \A
101             (?:[+-])? # optional leading sign
102             \d+
103             \z
104             /x,
105             } );
106              
107 2         10 my $composed = $bucket->__compose_satisfy_all( $sub );
108              
109             $bucket->add_to_bucket( {
110 2         7 name => $caller[0]{'sub'},
111             code => $composed,
112             } );
113             }
114              
115             sub _inclusive_within_numeric_range {
116 1     1   2 my( $bucket, $setup ) = @_;
117              
118 1         2 my @caller = $bucket->__caller_chain_as_list();
119              
120             $bucket->add_to_bucket( {
121             name => $setup->{name} || $caller[0]{'sub'},
122             description => "Find number within the range [$setup->{minimum}, $setup->{maximum}] inclusively",
123 1   33     11 fields => [ $setup->{field} ],
124             code => $bucket->__compose_satisfy_all(
125             $bucket->_numeric_equal_or_greater_than( $setup ),
126             $bucket->_numeric_equal_or_less_than( $setup ),
127             ),
128             } );
129             }
130              
131             sub _exclusive_within_numeric_range {
132 1     1   2 my( $bucket, $setup ) = @_;
133              
134 1         3 my @caller = $bucket->__caller_chain_as_list();
135              
136             $bucket->add_to_bucket( {
137             name => $setup->{name} || $caller[0]{'sub'},
138             description => "Find number within the range [$setup->{minimum}, $setup->{maximum}] exclusively",
139 1   33     9 fields => [ $setup->{field} ],
140             code => $bucket->__compose_satisfy_all(
141             $bucket->_numeric_strictly_greater_than( $setup ),
142             $bucket->_numeric_strictly_less_than( $setup ),
143             ),
144             } );
145              
146             }
147              
148             sub _numeric_equal_or_greater_than {
149 1     1   1 my( $bucket, $setup ) = @_;
150              
151 1         3 my @caller = $bucket->__caller_chain_as_list();
152              
153             $bucket->add_to_bucket({
154             name => $setup->{name} || $caller[0]{'sub'},
155             description => "The number is equal to or greater than $setup->{minimum}",
156             fields => [ $setup->{field} ],
157             code => sub {
158             die {
159             message => "The number in $setup->{field} was $_[0]->{ $setup->{field} }, but should have been greater than or equal to $setup->{minimum}",
160             failed_field => $setup->{field},
161             handler => $caller[0]{'sub'},
162             } unless $_[0]->{ $setup->{field} } >= $setup->{minimum}
163 0 0   0   0 },
164 1   33     21 } );
165             }
166              
167             sub _numeric_strictly_greater_than {
168 1     1   2 my( $bucket, $setup ) = @_;
169              
170 1         2 my @caller = $bucket->__caller_chain_as_list();
171              
172             $bucket->add_to_bucket({
173             name => $setup->{name} || $caller[0]{'sub'},
174             description => "The number is greater than $setup->{minimum}",
175             fields => [ $setup->{field} ],
176             code => sub {
177             die {
178             message => "The number in $setup->{field} was $_[0]->{ $setup->{field} }, but should have been strictly greater than $setup->{minimum}",
179             failed_field => $setup->{field},
180             handler => $caller[0]{'sub'},
181 0 0   0   0 } unless $_[0]->{ $setup->{field} } > $setup->{minimum};
182             },
183 1   33     15 } );
184             }
185              
186             sub _numeric_equal_or_less_than {
187 1     1   2 my( $bucket, $setup ) = @_;
188              
189 1         2 my @caller = $bucket->__caller_chain_as_list();
190              
191             $bucket->add_to_bucket({
192             name => $setup->{name} || $caller[0]{'sub'},
193             description => "The number is equal to or less than $setup->{maximum}",
194             fields => [ $setup->{field} ],
195             code => sub {
196             die {
197             message => "The number in $setup->{field} was $_[0]->{ $setup->{field} }, but should have been less than or equal to $setup->{maximum}",
198             failed_field => $setup->{field},
199             handler => $caller[0]{'sub'},
200 0 0   0   0 } unless $_[0]->{ $setup->{field} } <= $setup->{maximum};
201             },
202 1   33     9 } );
203             }
204              
205             sub _numeric_strictly_less_than {
206 1     1   2 my( $bucket, $setup ) = @_;
207              
208 1         2 my @caller = $bucket->__caller_chain_as_list();
209              
210             $bucket->add_to_bucket({
211             name => $setup->{name} || $caller[0]{'sub'},
212             description => "The number is less than $setup->{maximum}",
213             fields => [ $setup->{field} ],
214             code => sub {
215             die {
216             message => "The number in $setup->{field} was $_[0]->{ $setup->{field} }, but should have been strictly less than $setup->{maximum}",
217             failed_field => $setup->{field},
218             handler => $caller[0]{'sub'},
219 0 0   0     } unless $_[0]->{ $setup->{field} } < $setup->{maximum};
220             },
221 1   33     10 } );
222             }
223              
224             =back
225              
226             =head1 TO DO
227              
228             TBA
229              
230             =head1 SEE ALSO
231              
232             TBA
233              
234             =head1 SOURCE AVAILABILITY
235              
236             This source is in Github:
237              
238             https://github.com/briandfoy/brick
239              
240             =head1 AUTHOR
241              
242             brian d foy, C<< >>
243              
244             =head1 COPYRIGHT
245              
246             Copyright © 2007-2026, brian d foy . All rights reserved.
247              
248             You may redistribute this under the terms of the Artistic License 2.0.
249              
250             =cut
251              
252             1;