File Coverage

blib/lib/Data/Validate/Chemistry.pm
Criterion Covered Total %
statement 25 26 96.1
branch 4 6 66.6
condition 1 6 16.6
subroutine 6 6 100.0
pod 0 2 0.0
total 36 46 78.2


line stmt bran cond sub pod time code
1             package Data::Validate::Chemistry;
2              
3 3     3   1414 use strict;
  3         18  
  3         81  
4 3     3   18 use warnings;
  3         5  
  3         116  
5              
6             # ABSTRACT: Validate common chemical identifiers
7             our $VERSION = '0.1.0'; # VERSION
8              
9 3     3   25 use Exporter 'import';
  3         7  
  3         1140  
10             our @EXPORT_OK = qw(
11             is_CAS_number
12             is_European_Community_number
13             );
14              
15             sub is_CAS_number
16             {
17 6     6 0 168 my( $CAS_number ) = shift;
18              
19 6 100       42 return unless $CAS_number =~ /^[0-9]{2,7}-[0-9]{2}-[0-9]$/;
20              
21 4         25 my @digits = $CAS_number =~ /([0-9])/g;
22 4         10 my $checksum = pop @digits;
23              
24 4         11 return $checksum == _ISBN_like_checksum( 10, reverse @digits );
25             }
26              
27             sub is_European_Community_number
28             {
29 1     1 0 78 my( $EC_number ) = shift;
30              
31 1 50       8 return unless $EC_number =~ /^([0-9]{3}-){2}[0-9]$/;
32              
33 1         9 my @digits = $EC_number =~ /([0-9])/g;
34 1         3 my $checksum = pop @digits;
35              
36 1 50 33     6 if( $digits[0] == 4 && $checksum == 1 ) {
37             # There are 181 ELINCS numbers starting with 4 having checksum
38             # of 10 and with a checksum digit of 1, as given in
39             # https://en.wikipedia.org/w/index.php?title=European_Community_number&oldid=910557632
40 0   0     0 return _ISBN_like_checksum( 11, @digits ) == $checksum ||
41             _ISBN_like_checksum( 11, @digits ) == 10;
42             } else {
43 1         4 return _ISBN_like_checksum( 11, @digits ) == $checksum;
44             }
45             }
46              
47             sub _ISBN_like_checksum
48             {
49 5     5   11 my $modulo = shift;
50              
51 5         8 my $checksum = 0;
52 5         19 for (0..$#_) {
53 26         57 $checksum = ($checksum + $_[$_] * ($_ + 1)) % $modulo;
54             }
55 5         27 return $checksum;
56             }
57              
58             1;
59              
60             __END__