File Coverage

blib/lib/Mo/utils/Number.pm
Criterion Covered Total %
statement 54 54 100.0
branch 24 24 100.0
condition 9 9 100.0
subroutine 14 14 100.0
pod 6 6 100.0
total 107 107 100.0


line stmt bran cond sub pod time code
1             package Mo::utils::Number;
2              
3 26     26   272056 use base qw(Exporter);
  26         55  
  26         7732  
4 26     26   229 use strict;
  26         77  
  26         819  
5 26     26   119 use warnings;
  26         46  
  26         1822  
6              
7 26     26   4449 use Error::Pure qw(err);
  26         40607  
  26         1450  
8 26     26   14212 use Mo::utils::Number::Utils qw(sub_check_percent);
  26         93  
  26         575  
9 26     26   1722 use Readonly;
  26         100  
  26         1404  
10 26     26   155 use Scalar::Util qw(looks_like_number);
  26         47  
  26         26869  
11              
12             Readonly::Array our @EXPORT_OK => qw(check_int check_natural check_number
13             check_percent check_positive_decimal check_positive_natural);
14              
15             our $VERSION = 0.10;
16              
17             # ... -2, -1, 0, 1, 2, ...
18             sub check_int {
19 48     48 1 338185 my ($self, $key) = @_;
20              
21 48 100       125 _check_key($self, $key) && return;
22              
23 46 100       410 if ($self->{$key} !~ m/^\-?\d+$/ms) {
24             err "Parameter '$key' must be a integer.",
25 12         83 'Value', $self->{$key},
26             ;
27             }
28              
29 34         318 return;
30             }
31              
32             # 0, 1, 2 ...
33             sub check_natural {
34 48     48 1 424677 my ($self, $key) = @_;
35              
36 48 100       120 _check_key($self, $key) && return;
37              
38 46 100       343 if ($self->{$key} !~ m/^\d+$/ms) {
39             err "Parameter '$key' must be a natural number.",
40 18         107 'Value', $self->{$key},
41             ;
42             }
43              
44 28         239 return;
45             }
46              
47             # Common number.
48             sub check_number {
49 18     18 1 324621 my ($self, $key) = @_;
50              
51 18 100       48 _check_key($self, $key) && return;
52              
53 16 100       68 if (! looks_like_number($self->{$key})) {
54             err "Parameter '$key' must be a number.",
55 2         16 'Value', $self->{$key},
56             ;
57             }
58              
59 14         26 return;
60             }
61              
62             sub check_percent {
63 16     16 1 413111 my ($self, $key) = @_;
64              
65 16 100       49 _check_key($self, $key) && return;
66              
67 14         65 sub_check_percent($self->{$key}, $key, 'percent value');
68              
69 7         14 return;
70             }
71              
72             sub check_positive_decimal {
73 26     26 1 323513 my ($self, $key) = @_;
74              
75 26 100       78 _check_key($self, $key) && return;
76              
77 24 100 100     246 if ($self->{$key} !~ m/^\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/ms || $self->{$key} == 0) {
78             err "Parameter '$key' must be a positive decimal number.",
79 10         58 'Value', $self->{$key},
80             ;
81             }
82              
83 14         35 return;
84             }
85              
86             # 1, 2 ...
87             sub check_positive_natural {
88 16     16 1 307473 my ($self, $key) = @_;
89              
90 16 100       45 _check_key($self, $key) && return;
91              
92 14 100 100     122 if ($self->{$key} !~ m/^\d+$/ms || $self->{$key} == 0) {
93             err "Parameter '$key' must be a positive natural number.",
94 7         39 'Value', $self->{$key},
95             ;
96             }
97              
98 7         21 return;
99             }
100              
101             sub _check_key {
102 172     172   386 my ($self, $key) = @_;
103              
104 172 100 100     905 if (! exists $self->{$key} || ! defined $self->{$key}) {
105 12         63 return 1;
106             }
107              
108 160         447 return 0;
109             }
110              
111             1;
112              
113             __END__
114              
115             =pod
116              
117             =encoding utf8
118              
119             =head1 NAME
120              
121             Mo::utils::Number - Mo number utilities.
122              
123             =head1 SYNOPSIS
124              
125             use Mo::utils::Number qw(check_int check_natural check_number check_percent check_positive_decimal check_positive_natural);
126              
127             check_int($self, $key);
128             check_natural($self, $key);
129             check_number($self, $key);
130             check_percent($self, $key);
131             check_positive_decimal($self, $key)
132             check_positive_natural($self, $key);
133              
134             =head1 DESCRIPTION
135              
136             Mo number utilities for checking of data objects.
137              
138             =head1 SUBROUTINES
139              
140             =head2 C<check_int>
141              
142             check_int($self, $key);
143              
144             Check if the parameter defined by C<$key> is an integer (... -2, -1, 0, 1, 2, ...).
145             Value could be undefined or doesn't exist.
146              
147             Put error if check isn't ok.
148              
149             Returns undef.
150              
151             =head2 C<check_natural>
152              
153             check_natural($self, $key);
154              
155             Check if the parameter defined by C<$key> is a natural number (0, 1, 2, ...).
156             Value could be undefined or doesn't exist.
157              
158             Put error if check isn't ok.
159              
160             Returns undef.
161              
162             =head2 C<check_number>
163              
164             check_number($self, $key);
165              
166             I<Since version 0.02.>
167              
168             Check if the parameter defined by C<$key> is a number.
169             Number could be integer, float, exponencial and negative.
170             Implementation is via L<Scalar::Util/looks_like_number>.
171              
172             Put error if check isn't ok.
173              
174             Returns undef.
175              
176             =head2 C<check_percent>
177              
178             check_percent($self, $key);
179              
180             Check if the parameter defined by C<$key> is a percent.
181             Value could be undefined or doesn't exist.
182              
183             Put error if check isn't ok.
184              
185             Returns undef.
186              
187             =head2 C<check_positive_decimal>
188              
189             check_positive_decimal($self, $key)
190              
191             I<Since version 0.05. Described functionality since version 0.08.>
192              
193             Check if the parameter defined by C<$key> is a positive decimal number.
194             Value could be undefined or doesn't exist.
195             Check accepts numbers in scientific notation.
196              
197             Put error if check isn't ok.
198              
199             Returns undef.
200              
201             =head2 C<check_positive_natural>
202              
203             check_positive_natural($self, $key);
204              
205             Check if the parameter defined by C<$key> is a positive natural number (1, 2, ...).
206             Value could be undefined or doesn't exist.
207              
208             Put error if check isn't ok.
209              
210             Returns undef.
211              
212             =head1 ERRORS
213              
214             check_int():
215             Parameter '%s' must be a integer.
216             Value: %s
217             check_natural():
218             Parameter '%s' must be a natural number.
219             Value: %s
220             check_number():
221             Parameter '%s' must be a number.
222             Value: %s
223             check_percent():
224             Parameter '%s' has bad percent value.
225             Value: %s
226             Parameter '%s' has bad percent value (missing %).
227             Value: %s
228             check_positive_decimal():
229             Parameter '%s' must be a positive decimal number.
230             Value: %s
231             check_positive_natural():
232             Parameter '%s' must be a positive natural number.
233             Value: %s
234              
235             =head1 EXAMPLE1
236              
237             =for comment filename=check_int_ok.pl
238              
239             use strict;
240             use warnings;
241              
242             use Mo::utils::Number qw(check_int);
243              
244             my $self = {
245             'key' => -2,
246             };
247             check_int($self, 'key');
248              
249             # Print out.
250             print "ok\n";
251              
252             # Output:
253             # ok
254              
255             =head1 EXAMPLE2
256              
257             =for comment filename=check_int_fail.pl
258              
259             use strict;
260             use warnings;
261              
262             use Error::Pure;
263             use Mo::utils::Number qw(check_int);
264              
265             $Error::Pure::TYPE = 'Error';
266              
267             my $self = {
268             'key' => 1.2,
269             };
270             check_int($self, 'key');
271              
272             # Print out.
273             print "ok\n";
274              
275             # Output like:
276             # #Error [...Number.pm:?] Parameter 'key' must be a integer.
277              
278             =head1 EXAMPLE3
279              
280             =for comment filename=check_natural_ok.pl
281              
282             use strict;
283             use warnings;
284              
285             use Mo::utils::Number qw(check_natural);
286              
287             my $self = {
288             'key' => 0,
289             };
290             check_natural($self, 'key');
291              
292             # Print out.
293             print "ok\n";
294              
295             # Output:
296             # ok
297              
298             =head1 EXAMPLE4
299              
300             =for comment filename=check_natural_fail.pl
301              
302             use strict;
303             use warnings;
304              
305             use Error::Pure;
306             use Mo::utils::Number qw(check_natural);
307              
308             $Error::Pure::TYPE = 'Error';
309              
310             my $self = {
311             'key' => -2,
312             };
313             check_natural($self, 'key');
314              
315             # Print out.
316             print "ok\n";
317              
318             # Output like:
319             # #Error [...Number.pm:?] Parameter 'key' must be a natural number.
320              
321             =head1 EXAMPLE5
322              
323             =for comment filename=check_number_ok.pl
324              
325             use strict;
326             use warnings;
327              
328             use Mo::utils::Number qw(check_number);
329              
330             my $self = {
331             'key' => '10',
332             };
333             check_number($self, 'key');
334              
335             # Print out.
336             print "ok\n";
337              
338             # Output:
339             # ok
340              
341             =head1 EXAMPLE6
342              
343             =for comment filename=check_number_fail.pl
344              
345             use strict;
346             use warnings;
347              
348             $Error::Pure::TYPE = 'Error';
349              
350             use Mo::utils::Number qw(check_number);
351              
352             my $self = {
353             'key' => 'foo',
354             };
355             check_number($self, 'key');
356              
357             # Print out.
358             print "ok\n";
359              
360             # Output like:
361             # #Error [...Number.pm:?] Parameter 'key' must be a number.
362              
363             =head1 EXAMPLE7
364              
365             =for comment filename=check_percent_ok.pl
366              
367             use strict;
368             use warnings;
369              
370             use Mo::utils::Number qw(check_percent);
371              
372             my $self = {
373             'key' => '10%',
374             };
375             check_percent($self, 'key');
376              
377             # Print out.
378             print "ok\n";
379              
380             # Output:
381             # ok
382              
383             =head1 EXAMPLE8
384              
385             =for comment filename=check_percent_fail.pl
386              
387             use strict;
388             use warnings;
389              
390             $Error::Pure::TYPE = 'Error';
391              
392             use Mo::utils::Number qw(check_percent);
393              
394             my $self = {
395             'key' => 'foo',
396             };
397             check_percent($self, 'key');
398              
399             # Print out.
400             print "ok\n";
401              
402             # Output like:
403             # #Error [...Number.pm:?] Parameter 'key' has bad percent value.
404              
405             =head1 EXAMPLE9
406              
407             =for comment filename=check_positive_decimal_ok.pl
408              
409             use strict;
410             use warnings;
411              
412             use Mo::utils::Number qw(check_positive_decimal);
413              
414             my $self = {
415             'key' => 3.2,
416             };
417             check_positive_decimal($self, 'key');
418              
419             # Print out.
420             print "ok\n";
421              
422             # Output:
423             # ok
424              
425             =head1 EXAMPLE10
426              
427             =for comment filename=check_positive_decimal_fail.pl
428              
429             use strict;
430             use warnings;
431              
432             $Error::Pure::TYPE = 'Error';
433              
434             use Mo::utils::Number qw(check_positive_decimal);
435              
436             my $self = {
437             'key' => -1.2,
438             };
439             check_positive_decimal($self, 'key');
440              
441             # Print out.
442             print "ok\n";
443              
444             # Output like:
445             # #Error [...Number.pm:?] Parameter 'key' must be a positive decimal number.
446              
447             =head1 EXAMPLE11
448              
449             =for comment filename=check_positive_natural_ok.pl
450              
451             use strict;
452             use warnings;
453              
454             use Mo::utils::Number qw(check_positive_natural);
455              
456             my $self = {
457             'key' => '3',
458             };
459             check_positive_natural($self, 'key');
460              
461             # Print out.
462             print "ok\n";
463              
464             # Output:
465             # ok
466              
467             =head1 EXAMPLE12
468              
469             =for comment filename=check_positive_natural_fail.pl
470              
471             use strict;
472             use warnings;
473              
474             $Error::Pure::TYPE = 'Error';
475              
476             use Mo::utils::Number qw(check_positive_natural);
477              
478             my $self = {
479             'key' => -1,
480             };
481             check_positive_natural($self, 'key');
482              
483             # Print out.
484             print "ok\n";
485              
486             # Output like:
487             # #Error [...Number.pm:?] Parameter 'key' must be a positive natural number.
488              
489             =head1 DEPENDENCIES
490              
491             L<Error::Pure>,
492             L<Exporter>,
493             L<Readonly>,
494             L<Scalar::Util>.
495              
496             =head1 SEE ALSO
497              
498             =over
499              
500             =item L<Mo::utils::Number::Range>
501              
502             Mo number utilities for ranges.
503              
504             =item L<Mo>
505              
506             Micro Objects. Mo is less.
507              
508             =item L<Mo::utils>
509              
510             Mo utilities.
511              
512             =item L<Wikibase::Datatype::Utils>
513              
514             Wikibase datatype utilities.
515              
516             =back
517              
518             =head1 REPOSITORY
519              
520             L<https://github.com/michal-josef-spacek/Mo-utils-Number>
521              
522             =head1 AUTHOR
523              
524             Michal Josef Špaček L<mailto:skim@cpan.org>
525              
526             L<http://skim.cz>
527              
528             =head1 LICENSE AND COPYRIGHT
529              
530             © 2024-2026 Michal Josef Špaček
531              
532             BSD 2-Clause License
533              
534             =head1 VERSION
535              
536             0.10
537              
538             =cut