File Coverage

lib/Math/String/Sequence.pm
Criterion Covered Total %
statement 88 101 87.1
branch 22 38 57.8
condition 3 9 33.3
subroutine 15 17 88.2
pod 8 10 80.0
total 136 175 77.7


line stmt bran cond sub pod time code
1             #############################################################################
2             # Math/String/Sequence.pm -- defines a sequence or range of strings.
3             #
4             # Copyright (C) 2001 - 2005 by Tels.
5             #############################################################################
6              
7             # the following hash values are used
8             # _first : first string
9             # _last : last string
10             # _set : charset for first/last
11             # _size : last-first
12             # _rev : 1 if reversed sequence
13              
14             package Math::String::Sequence;
15 1     1   7761 use vars qw($VERSION);
  1         2  
  1         72  
16             $VERSION = '1.06'; # Current version of this package
17             require 5.005; # requires this Perl version or later
18              
19 1     1   6 use Exporter;
  1         1  
  1         63  
20             @ISA = qw(Exporter);
21             @EXPORT_OK = qw(sequence);
22              
23 1     1   2355 use Math::String;
  1         3  
  1         8  
24 1     1   265 use Math::String::Charset;
  1         3  
  1         86  
25              
26 1     1   5 use strict;
  1         2  
  1         2348  
27             my $class = "Math::String::Sequence";
28              
29             # some shortcuts for easier life
30             sub sequence
31             {
32             # exportable version of new
33 0     0 0 0 $class->new(@_);
34             }
35              
36             ###############################################################################
37             # constructor
38              
39             sub new
40             {
41             # takes the following arguments:
42             # first, last: Math:Strings or scalars
43             # charset: optional, if you pass a scalar as first or last
44              
45 6     6 1 200 my $class = shift;
46 6   33     34 $class = ref($class) || $class;
47              
48 6         11 my $args;
49 6 50       17 if (ref $_[0] eq 'HASH')
50             {
51 0         0 $args = shift;
52             }
53             else
54             {
55 6         20 $args->{first} = shift;
56 6         11 $args->{last} = shift;
57 6         13 $args->{charset} = shift;
58             }
59              
60 6         11 my $self = {};
61 6         16 bless $self, $class;
62 6 50       19 if (ref $args eq $class)
63             {
64             # make copy
65 0         0 for (qw/_first _last/)
66             {
67 0         0 $self->{$_} = Math::String->new($args->{$_});
68             }
69 0         0 return $self;
70             }
71 6         11 my $first = $args->{first};
72 6         7 my $last = $args->{last};
73 6         8 my $set = $args->{charset};
74              
75 6 50       35 $first = Math::String->new($first,$set) unless ref $first;
76 6 50       33 $last = Math::String->new($last,$set) unless ref $last;
77            
78 6 50       32 die ("first is NaN") if $first->is_nan();
79 6 50       47 die ("last is NaN") if $last->is_nan();
80             #die ("$first is not smaller than $last") if
81             # adjustment by $self->_size(): $self->{_rev} = $first > $last ? 1 : 0;
82              
83 6         38 bless $self, $class;
84 6         32 $self->{_first} = $first;
85 6         10 $self->{_last} = $last;
86 6         16 $self->_initialize();
87 6         21 $self;
88             }
89              
90             #############################################################################
91             # private, initialize self
92              
93             sub _initialize
94             {
95             # init sequence
96 6     6   7 my $self = shift;
97              
98 6         16 $self->_size();
99 6         12 $self->{_set} = $self->{_first}->{_set};
100 6         9 $self;
101             }
102              
103             sub _size
104             {
105             # calculate new size and adjust _rev
106 6     6   9 my $self = shift;
107              
108 6 100       20 $self->{_rev} = $self->{_first} < $self->{_last} ? 0 : 1;
109 6         194 $self->{_size} = $self->{_last} - $self->{_first};
110 6         428 $self->{_size} = $self->{_size}->babs()->as_number();
111 6         41 $self->{_size}++;
112 6         213 $self;
113             }
114              
115             #############################################################################
116             # public
117              
118             sub charset
119             {
120 0     0 1 0 my $self = shift;
121 0         0 $self->{_first}->{_set};
122             }
123              
124             sub length
125             {
126 1     1 1 4 my $self = shift;
127 1         6 $self->{_size};
128             }
129              
130             sub is_reversed
131             {
132             # return true if the sequence is reversed, or false
133 2     2 1 51 my $self = shift;
134 2         9 $self->{_rev};
135             }
136              
137             sub first
138             {
139 3     3 1 735 my $self = shift;
140 3 50       8 if (defined $_[0])
141             {
142 0         0 $self->{_first} = shift;
143 0 0       0 $self->{_first} = Math::String->new($self->{_first},$self->{_set})
144             unless ref $self->{_first};
145 0         0 $self->_size();
146             }
147 3         12 $self->{_first};
148             }
149              
150             sub last
151             {
152 3     3 1 6 my $self = shift;
153 3 50       8 if (defined $_[0])
154             {
155 0         0 $self->{_last} = shift;
156 0 0       0 $self->{_last} = Math::String->new($self->{_last},$self->{_set})
157             unless ref $self->{_last};
158 0         0 $self->_size();
159             }
160 3         12 $self->{_last};
161             }
162              
163             sub string
164             {
165             # return the Nth string in sequence or undef for out-of-range
166 11     11 1 21 my $self = shift;
167 11 50       14 my $nr = shift; $nr = 0 if !defined $nr;
  11         46  
168              
169 11 50       46 $nr = Math::BigInt->new($nr) unless ref $nr;
170 11         429 my $n;
171 11 100       31 if ($self->{_rev})
172             {
173 4 100       11 if ($nr < 0)
174             {
175 2         198 $n = $self->{_last}-$nr; $n--;
  2         3307  
176             }
177             else
178             {
179 2         245 $n = $self->{_first}-$nr;
180             }
181 4 50 33     122 return if $n > $self->{_first} || $n < $self->{_last};
182             }
183             else
184             {
185 7 100       20 if ($nr < 0)
186             {
187 4         451 $n = $self->{_last}+$nr; $n++;
  4         277  
188             }
189             else
190             {
191 3         339 $n = $self->{_first}+$nr;
192             }
193 7 50 33     178 return if $n > $self->{_last} || $n < $self->{_first};
194             }
195 11         959 $n;
196             }
197              
198             sub error
199             {
200 1     1 0 153 my $self = shift;
201 1         7 $self->{_set}->error();
202             }
203              
204             sub as_array
205             {
206             # return the sequence as array of strings
207 2     2 1 45 my $x = shift;
208              
209 2         4 my @a;
210 2         5 my $f = $x->{_first}; my $l = $x->{_last};
  2         3  
211 2 100       6 if ($x->{_rev})
212             {
213 1         6 while ($f >= $l) { push @a,$f->copy(); $f->bdec(); }
  26         760  
  26         64  
214             }
215             else
216             {
217 1         4 while ($f <= $l) { push @a,$f->copy(); $f->binc(); }
  55         1297  
  55         142  
218             }
219 2         122 @a;
220             }
221              
222             __END__