File Coverage

blib/lib/Sort/strverscmp.pm
Criterion Covered Total %
statement 40 40 100.0
branch 14 16 87.5
condition 9 12 75.0
subroutine 10 10 100.0
pod 3 3 100.0
total 76 81 93.8


line stmt bran cond sub pod time code
1             package Sort::strverscmp;
2              
3             require Sort::strverscmp::StringIterator;
4              
5 3     3   29564 use Exporter 'import';
  3         5  
  3         105  
6 3     3   74 use 5.010;
  3         9  
7              
8 3     3   20 use strict;
  3         2  
  3         61  
9 3     3   10 use warnings;
  3         8  
  3         1575  
10              
11             our $VERSION = "0.013_02";
12             our @EXPORT = qw(strverscmp);
13             our @EXPORT_OK = qw(strverssort versionsort);
14              
15             # strnum_cmp from bam_sort.c
16             sub strverscmp($$) {
17 39     39 1 4308 my $ai = Sort::strverscmp::StringIterator->new($_[0]);
18 39         62 my $bi = Sort::strverscmp::StringIterator->new($_[1]);
19              
20 39   66     31 do {
21 123 100 66     168 if (_isdigit($ai->head) && _isdigit($bi->head)) {
22 48         68 my $an = (($ai->head . $ai->tail) =~ /^(\d*)/)[0];
23 48         98 my $bn = (($bi->head . $bi->tail) =~ /^(\d*)/)[0];
24 48 100 100     158 if ($an =~ /^0\d/ || $bn =~ /^0\d/) {
25 7         12 return _fcmp($an, $bn);
26             } else {
27 41 100       74 if ($an <=> $bn) {
28 26         70 return ($an <=> $bn);
29             }
30             }
31             } else {
32 75 100       108 if ($ai->head cmp $bi->head) {
33 5         9 return ($ai->head cmp $bi->head);
34             }
35             }
36 85         157 $ai->advance();
37 85         123 $bi->advance();
38             } while (defined($ai->head) && defined($bi->head));
39              
40 1 50       6 return $ai->head ? 1 : $bi->head ? -1 : 0;
    50          
41             }
42              
43 1     1 1 11 sub versionsort { &strverssort }
44             sub strverssort {
45 1     1 1 5 return sort { strverscmp($a, $b) } @_;
  2         4  
46             }
47              
48             sub _isdigit {
49 171     171   121 my $c = shift;
50 171   66     750 return (defined($c) && $c =~ /^\d+$/);
51             }
52              
53             sub _fcmp {
54 7     7   9 my ($l, $r) = @_;
55              
56 7         5 my ($lz, $ln, $rz, $rn);
57 7         8 ($lz, $ln) = _decompose_fractional($l);
58 7         9 ($rz, $rn) = _decompose_fractional($r);
59              
60 7 100       12 if (length($lz) == length($rz)) {
61 1         5 return $ln <=> $rn;
62             } else {
63 6 100       35 return (length($lz) > length($rz) ? -1 : 1);
64             }
65             }
66              
67             sub _decompose_fractional {
68 14     14   29 my ($zeroes, $number) = shift =~ /^(0*)(\d+)$/;
69 14         24 return ($zeroes, $number);
70             }
71              
72             1;
73             __END__