File Coverage

blib/lib/Locale/MakePhrase/Numeric.pm
Criterion Covered Total %
statement 51 57 89.4
branch 21 30 70.0
condition 8 18 44.4
subroutine 9 10 90.0
pod 1 5 20.0
total 90 120 75.0


line stmt bran cond sub pod time code
1             package Locale::MakePhrase::Numeric;
2             our $VERSION = 0.1;
3             our $DEBUG = 0;
4              
5             =head1 NAME
6              
7             Locale::MakePhrase::Numeric - Numeric translation/stringification
8              
9             =head1 SYNOPSIS
10              
11             This module provides the functionality to translate and/or stringify
12             a numeric, into something suitable for the string being translated.
13              
14             =head1 API
15              
16             The following class-functions are provided:
17              
18             =cut
19              
20 10     10   7133 use strict;
  10         20  
  10         376  
21 10     10   56 use warnings;
  10         21  
  10         327  
22 10     10   53 use base qw(Exporter);
  10         17  
  10         1046  
23 10     10   2350 use Data::Dumper;
  10         16701  
  10         711  
24 10     10   64 use vars qw(@EXPORT_OK);
  10         21  
  10         8018  
25             @EXPORT_OK = qw( stringify);
26             local $Data::Dumper::Indent = 1 if $DEBUG;
27              
28             # Common formatting types
29 22     22 0 793 sub DOT { return [ '.','' ,'-','' ]; }
30 0     0 0 0 sub COMMA { return [ ',','' ,'-','' ]; }
31 1     1 0 229 sub DOT_COMMA { return [ '.',',','-','' ]; }
32 1     1 0 248 sub COMMA_DOT { return [ ',','.','-','' ]; }
33              
34             #--------------------------------------------------------------------------
35              
36             =head2 $string stringify($number,$options)
37              
38             This class-function implements the stringification of a number to a
39             suitable output format. The $options parameter is used to control
40             the formatting behaviour:
41              
42             =over 2
43              
44             =item C
45              
46             The formatting appled to the number; this must be an array reference
47             containing 4 elements:
48              
49             =over 3
50              
51             =item 1.
52              
53             decimal seperator
54              
55             =item 2.
56              
57             thousand's seperator
58              
59             =item 3.
60              
61             when the value is negative, the symbol shown to the left of the
62             number
63              
64             =item 4.
65              
66             when the value is negative, the symbol shown to the right of the
67             number
68              
69             =back
70              
71             =item C
72              
73             Set the number of characters used in the output.
74              
75             =item C
76              
77             Set the maximum number of decimal places processed.
78              
79             =item C
80              
81             Set this to true to make the output use a fixed number of decimal
82             places, irrespective if the values are all zeros. Use this in
83             conjunction with the C setting.
84              
85             =item C
86              
87             Set this value to true to make the number show exponential notation.
88              
89             =item C
90              
91             Set this to true to make the output display zeros; combine this
92             with the C setting.
93              
94             =back
95              
96             =cut
97              
98             sub stringify {
99 10 50   10 1 116 shift if (@_ == 3);
100 10         20 my ($number,$options) = @_;
101 10         16 my $format = $options->{numeric_format};
102 10 50       27 $format = DOT unless $format;
103 10 50       28 print STDERR "Stringify format: '".join("' '",@$format)."'\n" if $DEBUG > 3;
104 10 100       30 my $negative = $number < 0 ? 1 : 0;
105 10         16 $number = abs($number);
106              
107             # Don't let the %G of sprintf, turn ten million (or bigger) into something like 1E+007
108             # Otherwise, try to apply various formatting options.
109 10 100 33     195 if (!$options->{fixed} and !$options->{scientific} and $number < 10_000_000_000 and $number == int($number)) {
      33        
      66        
110 8         14 $number += 0; # Just use normal integer stringification.
111             } else {
112 2         6 my $mode = "%";
113 2 50       8 $mode .= $options->{width} if (exists $options->{width});
114 2 100       6 if (exists $options->{precision}) {
115 1         4 $mode .= ".".$options->{precision};
116             } else {
117 1         3 $mode .= ".15";
118             }
119 2 50       6 if ($options->{fixed}) {
120 0         0 $mode .= "F";
121             } else {
122 2         3 $mode .= "G";
123             }
124 2         28 $number = CORE::sprintf($mode,$number);
125 2 100 33     42 if(!$options->{fixed} and !$options->{scientific} and $number < 10_000_000_000 and $number == int($number)) {
      33        
      66        
126 1         3 $number += 0; # Just use normal integer stringification.
127             }
128             }
129              
130             # We optionally apply numeric formatting (eg: put comma's into big numbers)
131 10 50       24 if ($format) {
132              
133             # has the format defined a seperator, we add them
134 10 100       33 if ($format->[1]) {
135             # The initial \d+ gobbles as many digits as it can, and then we
136             # backtrack so it un-eats the rightmost three, and then we
137             # insert the comma there.
138 3         32 while( $number =~ s/^(\d+)(\d{3})/$1_$2/s ) {1}
  3         12  
139              
140 3         6 my $t = $format->[0];
141 3 50       7 if ($t eq '_') {
142 0         0 $number =~ s/_/#/g;
143 0         0 $number =~ s/\./_/;
144 0         0 $t = $format->[1];
145 0         0 $number =~ s/#/$t/g;
146             } else {
147 3         6 $number =~ s/\./$t/;
148 3         5 $t = $format->[1];
149 3         12 $number =~ s/_/$t/g;
150             }
151             } else {
152 7         14 my $t = $format->[0];
153 7 50       24 $number =~ s/\./$t/ if ($t ne '.');
154             }
155             }
156              
157             # do we want leading zero's
158 10 50       28 $number = tr< ><0> if ($options->{leading_zeros});
159              
160             # apply negative-formatting
161 10 100       39 $number = $format->[2].$number.$format->[3] if $negative;
162              
163 10         83 return $number;
164             }
165              
166             1;
167             __END__