File Coverage

blib/lib/Persistent/DataType/Number.pm
Criterion Covered Total %
statement 67 81 82.7
branch 28 56 50.0
condition 10 18 55.5
subroutine 9 10 90.0
pod 4 5 80.0
total 118 170 69.4


line stmt bran cond sub pod time code
1             ########################################################################
2             # File: Number.pm
3             # Author: David Winters
4             # RCS: $Id: Number.pm,v 1.6 2000/02/08 02:36:40 winters Exp winters $
5             #
6             # A floating point and integer class.
7             #
8             # This file contains POD documentation that may be viewed with the
9             # perldoc, pod2man, or pod2html utilities.
10             #
11             # Copyright (c) 1998-2000 David Winters. All rights reserved.
12             # This program is free software; you can redistribute it
13             # and/or modify it under the same terms as Perl itself.
14             ########################################################################
15              
16             package Persistent::DataType::Number;
17             require 5.004;
18              
19 5     5   25 use strict;
  5         7  
  5         199  
20 5     5   24 use vars qw($VERSION $REVISION @ISA);
  5         8  
  5         320  
21              
22             ### we are a subclass of the all-powerful Persistent::DataType::Base class ###
23 5     5   27 use Persistent::DataType::Base;
  5         8  
  5         151  
24             @ISA = qw(Persistent::DataType::Base);
25              
26 5     5   22 use Carp;
  5         18  
  5         6033  
27              
28             ### copy version number from superclass ###
29             $VERSION = $Persistent::DataType::Base::VERSION;
30             $REVISION = (qw$Revision: 1.6 $)[1];
31              
32             =head1 NAME
33              
34             Persistent::DataType::Number - A Floating Point and Integer Class
35              
36             =head1 SYNOPSIS
37              
38             use Persistent::DataType::Number;
39             use English;
40              
41             eval { ### in case an exception is thrown ###
42              
43             ### allocate a number ###
44             my $number = new Persistent::DataType::Number($value,
45             $precision,
46             $scale);
47              
48             ### get/set value of number ###
49             $value = $number->value($new_value);
50              
51             ### get/set precision of the number ###
52             $precision = $number->precision($new_precision);
53              
54             ### get/set scale of number ###
55             $scale = $number->scale($new_scale);
56              
57             ### returns '<=>' for numbers ###
58             my $cmp_op = $number->get_compare_op();
59             };
60              
61             if ($EVAL_ERROR) { ### catch those exceptions! ###
62             print "An error occurred: $EVAL_ERROR\n";
63             }
64              
65             =head1 ABSTRACT
66              
67             This is a floating point and integer class used by the Persistent
68             framework of classes to implement the attributes of objects. This
69             class provides methods for accessing the value, precision, scale, and
70             comparison operator of a number.
71              
72             This class is usually not invoked directly, at least not when used
73             with the Persistent framework of classes. However, the constructor
74             arguments of this class are usually of interest when defining the
75             attributes of a Persistent object since the I method of
76             the Persistent classes instantiates this class directly. Also, the
77             arguments to the I method are of interest when dealing with the
78             accessor methods of the Persistent classes since the accessor methods
79             pass their arguments to the I method and return the string
80             value from the I method.
81              
82             This class is part of the Persistent base package which is available
83             from:
84              
85             http://www.bigsnow.org/persistent
86             ftp://ftp.bigsnow.org/pub/persistent
87              
88             =head1 DESCRIPTION
89              
90             Before we get started describing the methods in detail, it should be
91             noted that all error handling in this class is done with exceptions.
92             So you should wrap an eval block around all of your code. Please see
93             the L documentation for more information on exception
94             handling in Perl.
95              
96             =head1 METHODS
97              
98             =cut
99              
100             ########################################################################
101             #
102             # --------------------------------------------------------------------
103             # PUBLIC ABSTRACT METHODS OVERRIDDEN (REDEFINED) FROM THE PARENT CLASS
104             # --------------------------------------------------------------------
105             #
106             ########################################################################
107              
108             ########################################################################
109             # initialize
110             ########################################################################
111              
112             =head2 Constructor -- Creates the Number Object
113              
114             eval {
115             my $number = new Persistent::DataType::Number($value,
116             $precision,
117             $scale);
118             };
119             croak "Exception caught: $@" if $@;
120              
121             Initializes a number object. This method throws Perl execeptions so
122             use it with an eval block.
123              
124             Parameters:
125              
126             =over 4
127              
128             =item I<$value>
129              
130             Actual value of the number; this may be a floating point or integer.
131             This argument is optional and may be set to undef.
132              
133             =item I<$precision>
134              
135             The number of digits in the number not including the decimal point or
136             the sign. This argument is optional and will be initialized to the
137             precision of the I<$value> argument as a default.
138              
139             =item I<$scale>
140              
141             The number of digits after the decimal point. This argument is
142             optional and will be initialized to the scale of the I<$value>
143             argument as a default.
144              
145             =back
146              
147             =cut
148              
149             sub initialize {
150 11     11 0 22 my($this, $value, $precision, $scale) = @_;
151              
152 11         32 $this->_trace();
153              
154             ### parse out the digits before and after the decimal point ###
155 11         27 my($before, $after) = _parse_number($value);
156              
157             ### set the attributes ###
158 11 50       35 $precision = length($before) + length($after) if !defined($precision);
159 11         31 $this->precision($precision);
160 11 50       34 $scale = length($after) if !defined($scale);
161 11         28 $this->scale($scale);
162 11         28 $this->value($value);
163             }
164              
165             ########################################################################
166             # value
167             ########################################################################
168              
169             =head2 value -- Accesses the Value of the Number
170              
171             eval {
172             ### set the value ###
173             $number->value($value);
174              
175             ### get the value ###
176             $value = $number->value();
177             };
178             croak "Exception caught: $@" if $@;
179              
180             Sets the value of the number and/or returns the value. This method
181             throws Perl execeptions so use it with an eval block.
182              
183             Parameters:
184              
185             =over 4
186              
187             =item I<$value>
188              
189             Actual value of the number; this may be a floating point or integer.
190             This argument is optional and may be set to undef.
191              
192             =back
193              
194             =cut
195              
196             sub value {
197 67 50 66 67 1 260 (@_ == 1 || @_ == 2) or croak 'Usage: $obj->value([$value])';
198 67         75 my $this = shift;
199 67 50       149 ref($this) or croak "$this is not an object";
200              
201 67         304 $this->_trace();
202              
203             ### set the value ###
204 67 100       141 if (@_) {
205 30         41 my $value = shift;
206 30 50 66     127 $value = undef if defined $value && $value eq '';
207              
208             ### parse out the digits before and after the decimal point ###
209 30         54 my($before, $after) = _parse_number($value);
210              
211             ### get the precision and scale of the object ###
212 30         208 my $precision = $this->precision();
213 30         69 my $scale = $this->scale();
214              
215             ### check the length ###
216 30 50       106 if (length($before) + length($after) > $precision) {
    50          
217 0         0 croak "'$value' is longer than $precision digit(s) of precision";
218             } elsif (length($after) > $scale) {
219 0         0 croak "'$value' is longer than $scale digit(s) of scale";
220             } else {
221 30 100       95 $value = $value + 0 if defined $value; ### force numeric context ###
222 30         70 $this->{Data}->{Value} = $value;
223             }
224             }
225              
226             ### return the value ###
227 67         215 $this->{Data}->{Value};
228             }
229              
230             ########################################################################
231             # get_compare_op
232             ########################################################################
233              
234             =head2 get_compare_op -- Returns the Comparison Operator
235              
236             $cmp_op = $number->get_compare_op();
237              
238             Returns the comparison operator for the Number class which is '<=>'.
239             This method does not throw execeptions.
240              
241             Parameters:
242              
243             =over 4
244              
245             =item None
246              
247             =back
248              
249             =cut
250              
251             sub get_compare_op {
252 0 0   0 1 0 (@_ == 1) or croak 'Usage: $obj->get_compare_op()';
253 0         0 my $this = shift;
254 0 0       0 ref($this) or croak "$this is not an object";
255              
256 0         0 $this->_trace();
257              
258 0         0 '<=>'; ### number comparison operator ###
259             }
260              
261             ########################################################################
262             #
263             # --------------
264             # PUBLIC METHODS
265             # --------------
266             #
267             ########################################################################
268              
269             ########################################################################
270             # precision
271             ########################################################################
272              
273             =head2 precision -- Accesses the Precision of the Number
274              
275             eval {
276             ### set the precision ###
277             $number->precision($new_precision);
278              
279             ### get the precision ###
280             $precision = $number->precision();
281             };
282             croak "Exception caught: $@" if $@;
283              
284             Sets the precision of the number and/or returns it. This method
285             throws Perl execeptions so use it with an eval block.
286              
287             Parameters:
288              
289             =over 4
290              
291             =item I<$precision>
292              
293             The number of digits in the number not including the decimal point or
294             the sign. The precision must be >= 0. If it is undef or the empty
295             string (''), then it is set to 0.
296              
297             =back
298              
299             =cut
300              
301             sub precision {
302 41 50 66 41 1 145 (@_ == 1 || @_ == 2) or croak 'Usage: $obj->precision([$precision])';
303 41         46 my $this = shift;
304 41 50       83 ref($this) or croak "$this is not an object";
305              
306 41         106 $this->_trace();
307              
308             ### set the precision ###
309 41 100       90 if (@_) {
310 11         15 my $precision = shift;
311 11 50 33     66 $precision = 0 if !defined($precision) || $precision eq '';
312 11 50       29 croak "precision ($precision) must be >= 0" if $precision < 0;
313 11         33 $this->{Data}->{Precision} = $precision;
314              
315             ### check that the value is not too long ###
316 11         36 my $value = $this->value();
317 11 50       36 if (defined $value) {
318 0         0 $value =~ s/[\-\.]//g;
319 0 0       0 if (length($value) > $precision) {
320 0         0 croak(sprint("'%s' is longer than $precision digit(s) of precision",
321             $this->value()));
322             }
323             }
324             }
325              
326             ### return the precision ###
327 41         100 $this->{Data}->{Precision};
328             }
329              
330             ########################################################################
331             # scale
332             ########################################################################
333              
334             =head2 scale -- Accesses the Scale of the Number
335              
336             eval {
337             ### set the scale ###
338             $number->scale($new_scale);
339              
340             ### get the scale ###
341             $scale = $number->scale();
342             };
343             croak "Exception caught: $@" if $@;
344              
345             Sets the scale of the number and/or returns it. This method throws
346             Perl execeptions so use it with an eval block.
347              
348             Parameters:
349              
350             =over 4
351              
352             =item I<$scale>
353              
354             The number of digits after the decimal point. The scale must be >= 0.
355             If it is undef or the empty string (''), then it is set to 0.
356              
357             =back
358              
359             =cut
360              
361             sub scale {
362 41 50 66 41 1 145 (@_ == 1 || @_ == 2) or croak 'Usage: $obj->scale([$scale])';
363 41         45 my $this = shift;
364 41 50       92 ref($this) or croak "$this is not an object";
365              
366 41         103 $this->_trace();
367              
368             ### set the scale ###
369 41 100       82 if (@_) {
370 11         17 my $scale = shift;
371 11 50 33     64 $scale = 0 if !defined($scale) || $scale eq '';
372 11 50       25 croak "scale ($scale) must be >= 0" if $scale < 0;
373 11         46 $this->{Data}->{Scale} = $scale;
374              
375             ### check that the value is not too long ###
376 11         36 my $value = $this->value();
377 11 50       45 if (defined $value) {
378 0 0       0 if ($value =~ /^\d*\.(\d*)$/) {
379 0 0       0 if (length($1) > $scale) {
380 0         0 croak(sprint("'%s' is longer than $scale digit(s) of scale",
381             $this->value()));
382             }
383             }
384             }
385             }
386              
387             ### return the scale ###
388 41         89 $this->{Data}->{Scale};
389             }
390              
391             ########################################################################
392             #
393             # ---------------
394             # PRIVATE METHODS
395             # ---------------
396             #
397             # NOTE: These methods do not need to be overridden in the subclasses.
398             # However, you may certainly override these methods if you see
399             # the need to.
400             #
401             ########################################################################
402              
403             ########################################################################
404             # Function: _parse_number
405             # Description: Parses the number into digits before and after the
406             # decimal point. Insignificant trailing zeroes will be
407             # truncated.
408             # Parameters: None
409             # Returns: None
410             ########################################################################
411             sub _parse_number {
412 41     41   60 my $value = shift;
413              
414 41         51 my $before = '';
415 41         45 my $after = '';
416              
417 41 100       89 if (defined $value) {
418 19 50       110 if ($value =~ /^[+-]?(\d*)\.?(\d*)$/) {
419 19         53 $before = $1; $after = $2;
  19         40  
420 19         30 $after =~ s/0+$//; ### remove trailing zeroes ###
421             } else {
422 0         0 croak "'$value' is not a number";
423             }
424             }
425              
426 41         136 ($before, $after);
427             }
428              
429             ### end of library ###
430             1;
431             __END__