File Coverage

blib/lib/Text/Sprintf/Zenkaku.pm
Criterion Covered Total %
statement 140 140 100.0
branch 56 56 100.0
condition n/a
subroutine 9 9 100.0
pod 2 2 100.0
total 207 207 100.0


line stmt bran cond sub pod time code
1             package Text::Sprintf::Zenkaku;
2 3     3   28078 use 5.008001;
  3         8  
3 3     3   12 use strict;
  3         3  
  3         49  
4 3     3   14 use warnings;
  3         4  
  3         77  
5 3     3   526 use utf8;
  3         10  
  3         12  
6 3     3   90 use Carp;
  3         4  
  3         195  
7 3     3   1425 use Encode;
  3         21629  
  3         263  
8              
9             our $VERSION = "0.08";
10              
11 3     3   19 use Exporter 'import';
  3         3  
  3         3071  
12             our @EXPORT_OK = qw(sprintf);
13              
14             our $cp932 = Encode::find_encoding("cp932");
15              
16             our $conversions = qr/\A[cduoxefgXEGbBpnaA]\Z/;
17             $conversions = qr/\A[cduoxefgXEGbBpn]\Z/ if $] lt 5.022000;
18             $conversions = qr/\A[cduoxefgXEGbpn]\Z/ if $] lt 5.010000;
19              
20             sub calc_width {
21 114     114 1 111 my ($w, $s) = @_;
22              
23 114         91 my $ofs;
24 114 100       141 if ($w >= 0) {
25 89         352 $ofs = $w - ((length $cp932->encode($s)) - (length $s));
26             } else {
27 25         132 $ofs = (abs $w) - ((length $cp932->encode($s)) - (length $s));
28 25         34 $ofs *= -1;
29             }
30              
31 114         188 return $ofs;
32             }
33              
34             sub sprintf {
35 95     95 1 63097 my @argv = @_;
36 95 100       178 my $fmt = defined $argv[0] ? $argv[0] : "";
37              
38 95         87 my $ofs = 0;
39 95         78 my $state = "IDL";
40              
41 95         63 my $index = 1;
42 95         74 my $tmp = "";
43 95         62 my $fmt_new = "";
44 95         70 my $length = length $fmt;
45 95         98 my $is_uniq = {};
46              
47 95         219 while ($ofs < $length) {
48 869         723 my $s = substr $fmt, $ofs, 1;
49 869 100       1168 if ($state eq "IDL") {
    100          
    100          
50 314 100       308 if ($s eq "%") {
51 187         131 $tmp = $s;
52 187         167 $state = "READ_FORMAT";
53             } else {
54 127         103 $fmt_new .= $s;
55             }
56             } elsif ($state eq "READ_FORMAT") {
57 377 100       1596 if ($s eq "%") {
    100          
    100          
    100          
    100          
    100          
58             # 'a percent sign' literal
59 3         3 $fmt_new .= $tmp . $s;
60 3         3 $tmp = "";
61 3         4 $state = "IDL";
62              
63             } elsif ($s eq "s") {
64             # %s
65 123         102 $tmp .= $s;
66              
67 123 100       678 if ($tmp =~ /^%([1-9][0-9]*)\$( *)\*([1-9][0-9]*)\$s$/) {
    100          
    100          
    100          
    100          
    100          
    100          
68 7         17 my $s_index = int $1;
69 7         10 my $space = $2;
70 7         9 my $w_index = int $3;
71              
72 7         11 my $s = $_[$s_index];
73 7         6 my $w = $_[$w_index];
74              
75 7         15 my $width = calc_width($w, $s);
76 7 100       18 if (not exists $is_uniq->{$w_index}) {
77 6         7 $argv[$w_index] = $width;
78 6         14 $is_uniq->{$w_index}++;
79             } else {
80 1         3 $tmp = '%' . $s_index . '$' . $space . $width . 's';
81             }
82              
83             } elsif ($tmp =~ /^%([1-9][0-9]*)\$( *)\*s$/) {
84 2         7 my $s_index = int $1;
85 2         3 my $space = $2;
86 2         3 my $w_index = $index;
87              
88 2         5 my $s = $_[$s_index];
89 2         5 my $w = $_[$w_index];
90              
91 2         42 my $width = calc_width($w, $s);
92 2 100       9 if (not exists $is_uniq->{$w_index}) {
93 1         2 $argv[$w_index] = $width;
94 1         3 $is_uniq->{$w_index}++;
95             } else {
96 1         3 $tmp = '%' . $s_index . '$' . $space . $width . 's';
97             }
98 2         4 $index++;
99              
100             } elsif ($tmp =~ /^%([1-9][0-9]*)\$( *)(-?[0-9]+)s$/) {
101 2         4 my $s_index = int $1;
102 2         4 my $space = $2;
103              
104 2         2 my $s = $_[$s_index];
105 2         4 my $w = $3;
106              
107 2         3 $w = calc_width($w, $s);
108              
109 2         5 $tmp = '%' . $s_index . '$' . $space . $w . 's';
110 2         3 $index++;
111              
112             } elsif ($tmp =~ /^%([1-9][0-9]*)\$( *)s$/) {
113             # do nothing
114 1         2 $index++;
115              
116             } elsif ($tmp =~ /^%( *)\*([1-9][0-9]*)\$s$/) {
117 9         10 my $s_index = $index;
118 9         18 my $space = $1;
119 9         16 my $w_index = int $2;
120              
121 9         13 my $s = $_[$s_index];
122 9         7 my $w = $_[$w_index];
123              
124 9         15 my $width = calc_width($w, $s);
125 9 100       18 if (not exists $is_uniq->{$w_index}) {
126 8         10 $argv[$w_index] = $width;
127 8         13 $is_uniq->{$w_index}++;
128             } else {
129 1         3 $tmp = '%' . $space . $width . 's';
130             }
131 9         10 $index++;
132              
133             } elsif ($tmp =~ /^%( *)\*s$/) {
134 4         7 my $s_index = $index + 1;
135 4         8 my $space = $1;
136 4         4 my $w_index = $index;
137 4         5 $index++;
138              
139 4         6 my $s = $_[$s_index];
140 4         4 my $w = $_[$w_index];
141              
142 4         7 my $width = calc_width($w, $s);
143              
144 4 100       11 if (not exists $is_uniq->{$w_index}) {
145 2         4 $argv[$w_index] = $width;
146 2         3 $is_uniq->{$w_index}++;
147             } else {
148             #$tmp = '%' . $space . $width . 's';
149 2         1 $argv[$w_index] = $width;
150 2         3 $is_uniq->{$w_index}++;
151             }
152 4         6 $index++;
153              
154             } elsif ($tmp =~ /^%( *)(-?[0-9]+)s$/) {
155 90         149 my $space = $1;
156              
157 90         106 my $s = $_[$index];
158 90         146 my $w = int $2;
159              
160 90         122 $w = calc_width($w, $s);
161              
162 90         122 $tmp = '%' . $space . $w . 's';
163 90         78 $index++;
164              
165             } else {
166             # do nothing
167 8         8 $index++;
168              
169             }
170              
171 123         109 $fmt_new .= $tmp;
172 123         101 $tmp = "";
173 123         91 $state = "IDL";
174             } elsif ($s =~ /$conversions/) {
175             # %c, %d, %u, %o, %x, %e, %f, %g, ...
176 59         63 $fmt_new .= $tmp . $s;
177 59         45 $tmp = "";
178 59         45 $index++;
179 59         49 $state = "IDL";
180             } elsif ($s eq "*") {
181 27         27 $tmp .= $s;
182 27         27 $state = "READ_ARGUMENT_NUMBER";
183             } elsif ($s =~ /\A[0-9]\Z/) {
184 109         114 $tmp .= $s;
185 109         94 $state = "READ_FORMAT_OR_ARGUMENT_NUMBER";
186             } elsif ($s =~ /\A[-+ #\.v]\Z/) {
187 55         51 $tmp .= $s;
188 55 100       104 if ($tmp =~ /\*v/) {
189 2         2 $index++;
190             }
191             } else {
192 1         34 croak "not supported : $fmt";
193             }
194             } elsif ($state eq "READ_ARGUMENT_NUMBER") {
195 46 100       93 if ($s =~ /\A[0-9]\Z/) {
    100          
196 19         26 $tmp .= $s;
197             } elsif ($s eq '$') {
198 19         20 $tmp .= $s;
199 19         19 $state = "READ_FORMAT";
200             } else {
201 8         13 $state = "READ_FORMAT";
202             #$index++;
203 8         13 next;
204             }
205             } else {
206             # $state eq "READ_FORMAT_OR_ARGUMENT_NUMBER"
207 132 100       240 if ($s =~ /\A[0-9]\Z/) {
    100          
208 23         25 $tmp .= $s;
209             } elsif ($s eq '$') {
210 12         11 $tmp .= $s;
211 12         13 $state = "READ_FORMAT";
212             } else {
213 97         67 $state = "READ_FORMAT";
214 97         158 next;
215             }
216             }
217 763         1042 $ofs++;
218             }
219              
220 94         72 $fmt_new .= $tmp;
221              
222 94         80 shift @argv;
223 94         1019 return CORE::sprintf $fmt_new, @argv;
224             }
225              
226             1;
227             __END__