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