File Coverage

blib/lib/Algorithm/Interval2Prefix.pm
Criterion Covered Total %
statement 31 31 100.0
branch 8 8 100.0
condition 5 5 100.0
subroutine 8 8 100.0
pod 2 2 100.0
total 54 54 100.0


line stmt bran cond sub pod time code
1             package Algorithm::Interval2Prefix;
2 2     2   46979 use strict;
  2         5  
  2         91  
3              
4 2     2   10 use vars qw($VERSION @ISA @EXPORT);
  2         5  
  2         1232  
5              
6             require Exporter;
7              
8             @ISA = qw(Exporter);
9             @EXPORT = qw(interval2prefix interval2regex);
10              
11             $VERSION = '0.02';
12              
13             my %Step; # cache
14              
15             sub _step {
16 487     487   562 my($i, $base) = @_;
17 487 100       2106 return $Step{$base}[$i] if exists $Step{$base}[$i];
18 14         20 $Step{$base}[0] = 1; # n**0 == 1
19 14         71 return $Step{$base}[$i] = $Step{$base}[$i-1] * $base;
20             }
21              
22             sub _i2a {
23 14     14   24 my($lo, $hi, $base, $render) = @_;
24 14         15 my @res;
25 14         44 while ($lo <= $hi) {
26 70         83 my $i = 0;
27 70   100     131 while (($lo % _step($i+1, $base) == 0) and
28             (($lo + _step($i+1, $base) - 1 <= $hi))) {
29 136         251 $i++;
30             }
31 70         142 push @res, $render->($lo, $i, $base);
32 70         131 $lo += _step($i, $base);
33             }
34 14         97 return @res;
35             }
36              
37             sub interval2prefix {
38 8     8 1 5100 my($lo, $hi, $base) = @_;
39             return _i2a($lo, $hi, $base || 10,
40             sub {
41 60     60   73 my($n, $i, $base)= @_;
42 60         103 return $n / _step($i, $base);
43 8   100     72 });
44             }
45              
46             sub interval2regex {
47 6     6 1 16 my($lo, $hi) = @_;
48             my @res = _i2a($lo, $hi, 10,
49             sub {
50 10     10   13 my($n, $i, $base)= @_;
51 10         17 my $p = $n / _step($i, $base);
52 10         51 my $s = length($n) - length($p);
53 10 100       56 return $p . ($s ? '\d' . ($s > 1 ? "{$s}" : '') : '');
    100          
54 6         37 });
55 6 100       82 return unless @res;
56 5         33 return '^(?:' . join('|', @res) . ')$';
57             }
58              
59             1;
60              
61             =head1 NAME
62              
63             Algorithm::Interval2Prefix - Generate prefixes from intervals
64              
65             =head1 SYNOPSIS
66              
67             use Algorithm::Interval2Prefix;
68              
69             my @prefixes = interval2prefix('33400','33599');
70             print join(',', @prefixes); # prints "334,335"
71              
72             my $regex = interval2regex('33400','33599');
73             if ($n =~ /$regex/) { ... }
74              
75             =head1 DESCRIPTION
76              
77             Taking an interval as input, this module will construct the smallest
78             set of prefixes, such that all numbers in the interval will match
79             exactly one of the prefixes, and no prefix will match a number not in
80             the interval.
81              
82             E.g. all numbers in the interval 39967000 to 39980999 would be matched
83             by the following set of prefixes:
84              
85             39967
86             39968
87             39969
88             3997
89             39980
90              
91             This type of conversion is particularly useful when working with
92             telephony switching equipment, which usually determines call routing
93             based on number prefixes rather than ranges.
94              
95             Note that the numbers in the interval must be of the same length
96             for the result to make sense.
97              
98             The algorithm is much dependent on the number base, which defaults to
99             10. Other number bases can be specified explicitly.
100              
101             An additional function is provided, that will generate a regular
102             expression string matching B those numbers in the interval.
103              
104             =head1 FUNCTIONS
105              
106             =over 4
107              
108             =item interval2prefix LO,HI,BASE
109              
110             =item interval2prefix LO,HI
111              
112             Yields an array of prefixes, covering the interval LO to HI,
113             using number base BASE.
114              
115             BASE is optional, and defaults to 10.
116              
117             =item interval2regex LO,HI
118              
119             Yields a regular expression string, which will match B those
120             numbers in the interval.
121              
122             This function assumes base 10.
123              
124             =back
125              
126             =head1 EXPORT
127              
128             Both interval2prefix() and interval2regex() are exported by default.
129              
130             =head1 BUGS/TODO
131              
132             =over 4
133              
134             =item *
135              
136             With interval2prefix(), the endpoints of the interval must be the
137             same length (same number of digits in the particular number base)
138             for the results to make any sense.
139              
140             =item *
141              
142             interval2regex() only does base 10.
143              
144             =back
145              
146             Please report issues via CPAN RT:
147              
148             http://rt.cpan.org/NoAuth/Bugs.html?Dist=Algorithm-Interval2Prefix
149              
150             or by sending mail to
151              
152             bug-Algorithm-Interval2Prefix@rt.cpan.org
153              
154             =head1 AUTHOR
155              
156             Lars Thegler
157              
158             =head1 COPYRIGHT
159              
160             Copyright (c) 2003 Lars Thegler. All rights reserved.
161              
162             This program is free software; you can redistribute it and/or modify
163             it under the same terms as Perl itself.
164              
165             =cut