File Coverage

blib/lib/Data/Str2Num.pm
Criterion Covered Total %
statement 25 117 21.3
branch 0 86 0.0
condition 0 30 0.0
subroutine 9 13 69.2
pod 3 5 60.0
total 37 251 14.7


line stmt bran cond sub pod time code
1             #!perl
2             #
3             # The copyright notice and plain old documentation (POD)
4             # are at the end of this file.
5             #
6             package Data::Str2Num;
7            
8 1     1   22292 use strict;
  1         2  
  1         34  
9 1     1   17 use 5.001;
  1         3  
  1         46  
10 1     1   5 use warnings;
  1         10  
  1         38  
11 1     1   6 use warnings::register;
  1         1  
  1         96  
12            
13             #####
14             # Connect up with the event log.
15             #
16 1     1   5 use vars qw( $VERSION $DATE $FILE);
  1         2  
  1         85  
17             $VERSION = '0.08';
18             $DATE = '2004/05/22';
19             $FILE = __FILE__;
20            
21 1     1   4 use vars qw(@ISA @EXPORT_OK);
  1         2  
  1         65  
22             require Exporter;
23             @ISA=('Exporter');
24             @EXPORT_OK = qw(str2float str2int str2integer);
25            
26 1     1   4 use Data::Startup;
  1         3  
  1         36  
27            
28 1     1   5 use vars qw($default_options);
  1         2  
  1         2101  
29             $default_options = new();
30            
31             ######
32             # Provide a way to module wide configure
33             #
34             sub config
35             {
36 0 0   0 0 0 shift if UNIVERSAL::isa($_[0],__PACKAGE__);
37 0 0       0 $default_options = new() unless $default_options;
38 0         0 $default_options->config(@_);
39             }
40            
41            
42             #######
43             # Object used to set default, startup, options values.
44             #
45             sub new
46             {
47 1     1 0 6 Data::Startup->new(
48            
49             ######
50             # Make Test variables visible to tech_config
51             #
52             ascii_float => 0
53             );
54            
55             }
56            
57            
58             ######
59             # Covert a string to floats.
60             #
61             sub str2float
62             {
63 0 0   0 1   shift if UNIVERSAL::isa($_[0],__PACKAGE__);
64 0 0         return '',() unless @_;
65            
66 0 0         $default_options = Data::Str2Num->new() unless ref($default_options);
67 0 0         my $options = $default_options->override(pop @_) if ref($_[-1]);
68            
69             #########
70             # Drop leading empty strings
71             #
72 0           my @strs = @_;
73 0   0       while (@strs && $strs[0] !~ /^\s*\S/) {
74 0           shift @strs;
75             }
76 0 0         @strs = () unless(@strs); # do not shift @strs out of existance
77            
78 0           my @floats = ();
79 0 0         my $early_exit unless wantarray;
80 0           my ($sign,$integer,$fraction,$exponent);
81 0           foreach (@strs) {
82 0 0         next unless defined $_;
83 0           while ( length($_) ) {
84            
85 0           ($sign, $integer,$fraction,$exponent) = ('',undef,undef,undef);
86            
87             #######
88             # Parse the integer part
89             #
90 0 0         if($_ =~ s/^\s*(-?)\s*(0[0-7]+|0?b[0-1]+|0x[0-9A-Fa-f]+)\s*[,;\n]?//) {
    0          
91 0           $integer = 0+oct($1 . $2);
92 0 0         $sign = $1 if $integer =~ s/^\s*-//;
93             }
94             elsif ($_ =~ s/^\s*(-?)\s*([0-9]+)\s*[,;\n]?//) {
95 0           ($sign,$integer) = ($1,$2);
96             }
97            
98             ######
99             # Parse the decimal part
100             #
101 0 0         $fraction = $1 if $_ =~ s/^\.([0-9]+)\s*[,;\n]?// ;
102            
103             ######
104             # Parse the exponent part
105 0 0         $exponent = $1 . $2 if $_ =~ s/^E(-?)([0-9]+)\s*[,;\n]?//;
106            
107 0 0 0       goto LAST unless defined($integer) || defined($fraction) || defined($exponent);
      0        
108            
109 0 0         $integer = '' unless defined($integer);
110 0 0         $fraction = '' unless defined($fraction);
111 0 0         $exponent = 0 unless defined($exponent);
112            
113 0 0         if($options->{ascii_float} ) {
114 0 0         $integer .= '.' . $fraction if( $fraction);
115 0 0         $integer .= 'E' . $exponent if( $exponent);
116 0           push @floats,$sign . $integer;
117             }
118             else {
119             ############
120             # Normalize decimal float so that there is only one digit to the
121             # left of the decimal point.
122             #
123 0   0       while($integer && substr($integer,0,1) == 0) {
124 0           $integer = substr($integer,1);
125             }
126 0 0         if( $integer ) {
127 0           $exponent += length($integer) - 1;
128             }
129             else {
130 0   0       while($fraction && substr($fraction,0,1) == 0) {
131 0           $fraction = substr($fraction,1);
132 0           $exponent--;
133             }
134 0           $exponent--;
135             }
136 0           $integer .= $fraction;
137 0   0       while($integer && substr($integer,0,1) == 0) {
138 0           $integer = substr($integer,1);
139             }
140 0 0         $integer = 0 unless $integer;
141 0           push @floats,[$sign . $integer, $exponent];
142             }
143 0 0         goto LAST if $early_exit;
144             }
145 0 0         last if $early_exit;
146             }
147            
148             LAST:
149             #########
150             # Drop leading empty strings
151             #
152 0   0       while (@strs && $strs[0] !~ /^\s*\S/) {
153 0           shift @strs;
154             }
155 0 0         @strs = () unless(@strs); # do not shift @strs out of existance
156            
157 0 0         return (\@strs, @floats) unless $early_exit;
158 0           ($integer,$fraction,$exponent) = @{$floats[0]};
  0            
159 0           "${integer}${fraction}E${exponent}"
160             }
161            
162            
163            
164             ######
165             # Convert number (oct, bin, hex, decimal) to decimal
166             #
167             sub str2int
168             {
169 0 0   0 1   shift if UNIVERSAL::isa($_[0],__PACKAGE__);
170             ####
171             # do no let the wantarray kink in
172 0           my $num = str2integer(@_);
173 0           $num;
174             }
175            
176            
177            
178             ######
179             # Convert number (oct, bin, hex, decimal) to decimal
180             #
181             sub str2integer
182             {
183 0 0   0 1   shift if UNIVERSAL::isa($_[0],__PACKAGE__);
184 0 0         unless( wantarray ) {
185 0 0         return undef unless(defined($_[0]));
186 0           my $str = $_[0];
187 0 0         return 0+oct($1) if($str =~ /^\s*(-?\s*0[0-7]+|0?b[0-1]+|0x[0-9A-Fa-f]+)\s*[,;\n]?$/);
188 0 0         return 0+$1 if ($str =~ /^\s*(-?\s*[0-9]+)\s*[,;:\n]?$/ );
189 0           return undef;
190             }
191            
192             #######
193             # Pick up input strings
194             #
195 0 0         return [],() unless @_;
196            
197 0 0         $default_options = Data::Str2num->new() unless ref($default_options);
198 0 0         my $options = $default_options->override(pop @_) if ref($_[-1]);
199 0           my @strs = @_;
200            
201             #########
202             # Drop leading empty strings
203             #
204 0   0       while (@strs && $strs[0] !~ /^\s*\S/) {
205 0           shift @strs;
206             }
207 0 0         @strs = () unless(@strs); # do not shift @strs out of existance
208            
209 0           my ($int,$num);
210 0           my @integers = ();
211 0           foreach $_ (@strs) {
212 0 0         next unless defined $_;
213 0           while ( length($_) ) {
214 0 0         if($_ =~ s/^\s*(-?)\s*(0[0-7]+|0?b[0-1]+|0x[0-9A-Fa-f]+)\s*[,;\n]?//) {
    0          
215 0           $int = $1 . $2;
216 0           $num = 0+oct($int);
217             }
218             elsif ($_ =~ s/^\s*(-?)\s*([0-9]+)\s*[,;\n]?// ) {
219 0           $int = $1 . $2;
220 0           $num = 0+$int;
221            
222             }
223             else {
224 0           goto LAST;
225             }
226            
227             #######
228             # If the integer is so large that Perl converted it to a float,
229             # repair the str so that the large integer may be dealt as a string
230             # or converted to a float. The using routine may be using Math::BigInt
231             # instead of using the native Perl floats and this automatic conversion
232             # would cause major damage.
233             #
234 0 0         if($num =~ /\s*[\.E]\d+/) {
    0          
235 0           $_ = $int;
236 0           goto LAST;
237             }
238            
239             #######
240             # If there is a string float instead of an int repair the str to
241             # perserve the float. The using routine may decide to use str2float
242             # to parse out the float.
243             #
244             elsif($_ =~ /^\s*[\.E]\d+/) {
245 0           $_ = $int . $_;
246 0           goto LAST;
247             }
248 0           push @integers,$num;
249             }
250             }
251            
252             LAST:
253             #########
254             # Drop leading empty strings
255             #
256 0   0       while (@strs && (!defined($strs[0]) || $strs[0] !~ /^\s*\S/)) {
      0        
257 0           shift @strs;
258             }
259 0 0         @strs = ('') unless(@strs); # do not shift @strs out of existance
260            
261 0           (\@strs, @integers);
262             }
263            
264             1
265            
266             __END__