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   3588 use vars qw($VERSION);
  1         1  
  1         42  
16             $VERSION = '1.29'; # Current version of this package
17             require 5.005; # requires this Perl version or later
18              
19 1     1   4 use Exporter;
  1         0  
  1         48  
20             @ISA = qw(Exporter);
21             @EXPORT_OK = qw(sequence);
22              
23 1     1   206 use Math::String;
  1         2  
  1         3  
24 1     1   33 use Math::String::Charset;
  1         1  
  1         28  
25              
26 1     1   3 use strict;
  1         0  
  1         537  
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 24 my $class = shift;
46 6   33     19 $class = ref($class) || $class;
47              
48 6         5 my $args;
49 6 50       13 if (ref $_[0] eq 'HASH')
50             {
51 0         0 $args = shift;
52             }
53             else
54             {
55 6         8 $args->{first} = shift;
56 6         8 $args->{last} = shift;
57 6         6 $args->{charset} = shift;
58             }
59              
60 6         7 my $self = {};
61 6         7 bless $self, $class;
62 6 50       13 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         6 my $first = $args->{first};
72 6         7 my $last = $args->{last};
73 6         4 my $set = $args->{charset};
74              
75 6 50       20 $first = Math::String->new($first,$set) unless ref $first;
76 6 50       20 $last = Math::String->new($last,$set) unless ref $last;
77              
78 6 50       17 die ("first is NaN") if $first->is_nan();
79 6 50       32 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         22 bless $self, $class;
84 6         10 $self->{_first} = $first;
85 6         5 $self->{_last} = $last;
86 6         9 $self->_initialize();
87 6         12 $self;
88             }
89              
90             #############################################################################
91             # private, initialize self
92              
93             sub _initialize
94             {
95             # init sequence
96 6     6   10 my $self = shift;
97              
98 6         9 $self->_size();
99 6         9 $self->{_set} = $self->{_first}->{_set};
100 6         5 $self;
101             }
102              
103             sub _size
104             {
105             # calculate new size and adjust _rev
106 6     6   4 my $self = shift;
107              
108 6 100       10 $self->{_rev} = $self->{_first} < $self->{_last} ? 0 : 1;
109 6         139 $self->{_size} = $self->{_last} - $self->{_first};
110 6         260 $self->{_size} = $self->{_size}->babs()->as_number();
111 6         19 $self->{_size}++;
112 6         142 $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 1 my $self = shift;
127 1         3 $self->{_size};
128             }
129              
130             sub is_reversed
131             {
132             # return true if the sequence is reversed, or false
133 2     2 1 28 my $self = shift;
134 2         7 $self->{_rev};
135             }
136              
137             sub first
138             {
139 3     3 1 136 my $self = shift;
140 3 50       6 if (defined $_[0])
141             {
142 0         0 $self->{_first} = shift;
143             $self->{_first} = Math::String->new($self->{_first},$self->{_set})
144 0 0       0 unless ref $self->{_first};
145 0         0 $self->_size();
146             }
147 3         10 $self->{_first};
148             }
149              
150             sub last
151             {
152 3     3 1 3 my $self = shift;
153 3 50       4 if (defined $_[0])
154             {
155 0         0 $self->{_last} = shift;
156             $self->{_last} = Math::String->new($self->{_last},$self->{_set})
157 0 0       0 unless ref $self->{_last};
158 0         0 $self->_size();
159             }
160 3         8 $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 10 my $self = shift;
167 11 50       11 my $nr = shift; $nr = 0 if !defined $nr;
  11         14  
168              
169 11 50       33 $nr = Math::BigInt->new($nr) unless ref $nr;
170 11         310 my $n;
171 11 100       19 if ($self->{_rev})
172             {
173 4 100       6 if ($nr < 0)
174             {
175 2         166 $n = $self->{_last}-$nr; $n--;
  2         67  
176             }
177             else
178             {
179 2         190 $n = $self->{_first}-$nr;
180             }
181 4 50 33     69 return if $n > $self->{_first} || $n < $self->{_last};
182             }
183             else
184             {
185 7 100       10 if ($nr < 0)
186             {
187 4         332 $n = $self->{_last}+$nr; $n++;
  4         154  
188             }
189             else
190             {
191 3         294 $n = $self->{_first}+$nr;
192             }
193 7 50 33     99 return if $n > $self->{_last} || $n < $self->{_first};
194             }
195 11         588 $n;
196             }
197              
198             sub error
199             {
200 1     1 0 113 my $self = shift;
201 1         5 $self->{_set}->error();
202             }
203              
204             sub as_array
205             {
206             # return the sequence as array of strings
207 2     2 1 12 my $x = shift;
208              
209 2         3 my @a;
210 2         2 my $f = $x->{_first}; my $l = $x->{_last};
  2         3  
211 2 100       3 if ($x->{_rev})
212             {
213 1         3 while ($f >= $l) { push @a,$f->copy(); $f->bdec(); }
  26         495  
  26         35  
214             }
215             else
216             {
217 1         3 while ($f <= $l) { push @a,$f->copy(); $f->binc(); }
  55         975  
  55         72  
218             }
219 2         66 @a;
220             }
221              
222             __END__