File Coverage

blib/lib/ShiftJIS/Regexp.pm
Criterion Covered Total %
statement 198 243 81.4
branch 126 162 77.7
condition 35 45 77.7
subroutine 13 14 92.8
pod 6 8 75.0
total 378 472 80.0


line stmt bran cond sub pod time code
1             package ShiftJIS::Regexp;
2 6     6   8586 use strict;
  6         11  
  6         219  
3 6     6   31 use Carp;
  6         16  
  6         638  
4              
5 6     6   31 use vars qw($VERSION $PACKAGE @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  6         13  
  6         882  
6              
7             $VERSION = '1.03';
8             $PACKAGE = 'ShiftJIS::Regexp'; #__PACKAGE__
9              
10 6     6   177 use vars qw(%Err %Re $Char $PadA $PadG $PadGA);
  6         10  
  6         505  
11 6     6   4145 use ShiftJIS::Regexp::Class;
  6         16  
  6         643  
12 6     6   38 use ShiftJIS::Regexp::Const qw(%Err %Re $Char $PadA $PadG $PadGA);
  6         13  
  6         33099  
13              
14             require Exporter;
15             @ISA = qw(Exporter);
16              
17             %EXPORT_TAGS = (
18             're' => [qw(re mkclass rechar)],
19             'op' => [qw(match replace)],
20             'split' => [qw(jsplit splitchar splitspace)],
21             );
22             $EXPORT_TAGS{all} = [ map @$_, values %EXPORT_TAGS ];
23             @EXPORT_OK = @{ $EXPORT_TAGS{all} };
24             @EXPORT = ();
25              
26             my(%Cache);
27              
28 0 0   0 0 0 sub getReCache { wantarray ? %Cache : \%Cache }
29              
30             sub re ($;$) {
31 1353     1353 1 4366944 my($flag);
32 1353         3082 my $pat = shift;
33 1353   100     7693 my $mod = shift || '';
34 1353 100       5759 if ($pat =~ s/^ (\^|\\[AG]|) \(\? ([a-zA-Z]+) \) /$1/x) {
35 51         142 $mod .= $2;
36             }
37              
38 1353         2971 my $s = $mod =~ /s/;
39 1353         2125 my $m = $mod =~ /m/;
40 1353         2466 my $x = $mod =~ /x/;
41 1353         2169 my $h = $mod =~ /h/;
42              
43 1353 100 100     4170 if ($mod =~ /o/ && defined $Cache{$pat}{$mod}) {
44 19         128 return $Cache{$pat}{$mod};
45             }
46              
47 1334 100 66     6540 my $res = $m && $s ? '(?ms)' : $m ? '(?m)' : $s ? '(?s)' : '';
    100          
    50          
48 1334         2309 my $tmppat = $pat;
49              
50 1334         2642 for ($tmppat) {
51 1334         4099 while (length) {
52 2378 50       6224 if (s/^(\(\?[p?]?\{)//) { # (?{}), (??{}) and (?p{})
53 0         0 $res .= $1;
54 0         0 my $count = 1;
55 0   0     0 while ($count && length) {
56 0 0       0 if (s/^(\x5C[\x00-\xFC])//) {
57 0         0 $res .= $1;
58 0         0 next;
59             }
60 0 0       0 if (s/^([^\{\}\\]+)//) {
61 0         0 $res .= $1;
62 0         0 next;
63             }
64 0 0       0 if (s/^\{//) {
65 0         0 ++$count;
66 0         0 $res .= '{';
67 0         0 next;
68             }
69 0 0       0 if (s/^\}//) {
70 0         0 --$count;
71 0         0 $res .= '}';
72 0         0 next;
73             }
74 0         0 croak $Err{Code};
75             }
76 0 0       0 if (s/^\)//) {
77 0         0 $res .= ')';
78 0         0 next;
79             }
80 0         0 croak $Err{Code};
81             }
82              
83 2378 100       19428 if (s/^\x5B(\^?)//) {
84 874         2354 my $not = $1;
85 874         3505 my $class = parse_class(\$_, $mod);
86 874 100       4303 $res .= $not ? "(?:(?!$class)$Char)" : $class;
87 874         3957 next;
88             }
89              
90 1504 100       3699 if (s/^\\([.*+?^$|\\()\[\]\{\}])//) { # backslashed meta chars
91 4         9 $res .= '\\'.$1;
92 4         13 next;
93             }
94 1500 50       5206 if (s|^\\?(['"/])||) { # <'>, <">, should be backslashed.
95 0         0 $res .= '\\'.$1;
96 0         0 next;
97             }
98 1500 100 100     6262 if ($x && s/^\s+//) { # skip whitespace
99 11         30 next;
100             }
101 1489 100       3576 if (s/^\.//) { # dot
102 5 50       22 $res .= $s ? $Re{'\j'} : $Re{'\J'};
103 5         15 next;
104             }
105 1484 100       5300 if (s/^\^//) { # begin
106 598         1379 $res .= '(?:^)';
107 598         2002 next;
108             }
109 886 100       1956 if (s/^\$//) { # end
110 37         57 $res .= '(?:$)';
111 37         118 next;
112             }
113 849 100       1814 if (s/^\\z//) { # \z (Perl 5.003 doesn't have this)
114 8         14 $res .= '(?!\n)\Z';
115 8         25 next;
116             }
117 841 100       2214 if (s/^\\([dDwWsSCjJ])//) { # class
118 46         168 $res .= $Re{ "\\$1" };
119 46         140 next;
120             }
121 795 100       2324 if (s/^\\([pP])//) { # prop
122 227         7683 my $key = parse_prop($1, \$_);
123 227 50       920 if (defined $Re{$key}) {
124 227         787 $res .= $Re{$key};
125             } else {
126 0         0 croak sprintf($Err{Undef}, $key);
127             }
128 227         995 next;
129             }
130 568 100       1012 if (s/^\\([R])//) { # regex
131 1         11 my $key = parse_regex($1, \$_);
132 1 50       9 if (defined $Re{$key}) {
133 1         6 $res .= $Re{$key};
134             } else {
135 0         0 croak sprintf($Err{Undef}, $key);
136             }
137 1         6 next;
138             }
139 567 100       1155 if (s/^\\([0-7][0-7][0-7]?)//) {
140 1         7 $res .= rechar(chr oct $1, $mod);
141 1         4 next;
142             }
143 566 100       1001 if (s/^\\0//) {
144 3         5 $res .='\\x00';
145 3         10 next;
146             }
147 563 100       1131 if (s/^\\c([\x00-\x7F])//) {
148 72         283 $res .= rechar(chr(ord(uc $1) ^ 64), $mod);
149 72         246 next;
150             }
151 491 100       858 if (s/^\\x([0-9A-Fa-f][0-9A-Fa-f])//) {
152 1         6 $res .= rechar(chr hex $1, $mod);
153 1         4 next;
154             }
155 490 100       853 if (s/^\\x\{([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])\}//) {
156 2         13 $res .= rechar(chr(hex $1).chr(hex $2), $mod);
157 2         7 next;
158             }
159 488 100       917 if (s/^\\([A-Za-z])//) {
160 9         18 $res .= '\\'. $1;
161 9         23 next;
162             }
163 479 100       1162 if (s/^(\(\?[a-z\-\s]+)//) {
164 2         3 $res .= $1;
165 2         5 next;
166             }
167 477 100       835 if (s/^\\([1-9])//) {
168 1 50       6 $res .= $h ? '\\'. ($1+1) : '\\'. $1;
169 1         4 next;
170             }
171 476 100       1505 if (s/^([\x21-\x40\x5B\x5D-\x60\x7B-\x7E])//) {
172 306         532 $res .= $1;
173 306         795 next;
174             }
175 170 50       296 if ($_ eq '\\') {
176 0         0 croak $Err{backtips};
177             }
178 170 50       706 if (s/^\\?($Char)//o) {
179 170         416 $res .= rechar($1, $mod);
180 170         491 next;
181             }
182 0         0 croak sprintf($Err{oddTrail}, ord);
183             }
184             }
185 1334 100       5467 return $mod =~ /o/ ? ($Cache{$pat}{$mod} = $res) : $res;
186             }
187              
188              
189              
190             sub dst ($) {
191 48     48 0 65 my $str = shift;
192 48         62 my $res = '';
193 48         87 for ($str) {
194 48         130 while (length) {
195 76 100       161 if (s/^\\\\//) {
196 1         2 $res .= '\\\\';
197 1         3 next;
198             }
199 75 50       168 if (s/^\\?\///) {
200 0         0 $res .= '\\/';
201 0         0 next;
202             }
203 75 100       198 if (s/^\$([1-8])//) {
204 24         79 $res .= '${' . ($1 + 1) . '}';
205 24         71 next;
206             }
207 51 100       110 if (s/^\$\{([1-8])\}//) {
208 4         12 $res .= '${' . ($1 + 1) . '}';
209 4         11 next;
210             }
211 47 50       92 if (s/^\\([0-7][0-7][0-7])//) {
212 0         0 $res .= "\\$1";
213 0         0 next;
214             }
215 47 50       102 if (s/^\\([0-7][0-7])//) {
216 0         0 $res .= "\\0$1";
217 0         0 next;
218             }
219 47 50       88 if (s/^\\x([0-9A-Fa-f][0-9A-Fa-f])//) {
220 0         0 $res .= "\\x$1";
221 0         0 next;
222             }
223 47 100       94 if (s/^\\x\{([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])\}//) {
224 2         6 $res .= '\\x' . $1 . '\\x' . $2;
225 2         9 next;
226             }
227 45 50       81 if (s/^\\0//) {
228 0         0 $res .='\\x00';
229 0         0 next;
230             }
231 45 100       88 if (s/^\\([A-Za-z])//) {
232 1         4 $res .= '\\'. $1;
233 1         4 next;
234             }
235 44 100       115 if (s/^\\?([\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])//) {
236 15         32 $res .= quotemeta($1);
237 15         38 next;
238             }
239 29 50       118 if (s/^\\?([\x00-\x7F\xA1-\xDF])//) {
240 29         51 $res .= $1;
241 29         100 next;
242             }
243 0         0 croak sprintf($Err{oddTrail}, ord);
244             }
245             }
246 48         114 return $res;
247             }
248              
249             sub match ($$;$) {
250 98     98 1 4735 my $str = $_[0];
251 98   100     344 my $mod = $_[2] || '';
252 98         199 my $pat = re($_[1], $mod);
253 98 50       183 if ($mod =~ /g/) {
254 0 0 0     0 my $fore = $mod =~ /z/ || '' =~ /$pat/ ? $PadGA : $PadG;
255 0         0 $str =~ /$fore(?:$pat)/g;
256             } else {
257 98         4196 $str =~ /$PadA(?:$pat)/;
258             }
259             }
260              
261              
262             sub replace ($$$;$) {
263 48     48 1 1692 my $str = $_[0];
264 48         107 my $dst = dst($_[2]);
265 48   100     136 my $mod = $_[3] || '';
266 48         130 my $pat = re($_[1], 'h'.$mod);
267 48 100       141 if ($mod =~ /g/) {
268 32 100 100     745 my $fore = $mod =~ /z/ || '' =~ /$pat/ ? $PadGA : $PadG;
269 32 50       79 if (ref $str) {
270 0         0 eval "\$\$str =~ s/($fore)(?:$pat)/\${1}$dst/g";
271             } else {
272 32         4558 eval "\$str =~ s/($fore)(?:$pat)/\${1}$dst/g";
273 32         183 $str;
274             }
275             } else {
276 16 100       40 if (ref $str) {
277 12         1720 eval "\$\$str =~ s/($PadA)(?:$pat)/\${1}$dst/";
278             } else {
279 4         471 eval "\$str =~ s/($PadA)(?:$pat)/\${1}$dst/";
280 4         18 $str;
281             }
282             }
283             }
284              
285              
286             #
287             # splitchar(STRING; LIMIT)
288             #
289             sub splitchar ($;$) {
290 176     176 1 420 my $str = shift;
291 176   100     439 my $lim = shift || 0;
292              
293 176 100       529 return wantarray ? () : 0 if $str eq '';
    100          
294 88 100       155 return wantarray ? ($str) : 1 if $lim == 1;
    100          
295              
296 84         85 my(@ret);
297 84 100       209 if ($lim > 1) {
298 76         419 while ($str =~ s/($Char)//o) {
299 760         1665 push @ret, $1;
300 760 100       3390 last if @ret >= $lim - 1;
301             }
302 76         112 push @ret, $str;
303             } else {
304 8         177 @ret = $str =~ /$Char/go;
305 8 100       31 push @ret, '' if $lim < 0;
306             }
307 84         534 return @ret;
308             }
309              
310             #
311             # splitspace(STRING; LIMIT)
312             #
313             sub splitspace ($;$) {
314 47     47 1 640 my $str = shift;
315 47   100     109 my $lim = shift || 0;
316 47 50       121 return wantarray ? () : 0 if $str eq '';
    100          
317              
318 33         93 my @ret;
319 33 100       63 if (0 < $lim) {
320 20         85 $str =~ s/^(?:[ \n\r\t\f]|\x81\x40)+//;
321 20         50 @ret = jsplit('(?o)[ \n\r\t\f\x{8140}]+', $str, $lim)
322             } else {
323 13         299 $str =~ s/\G($Char*?)\x81\x40/$1 /go;
324 13         74 @ret = split(' ', $str, $lim);
325             }
326 33         149 return @ret;
327             }
328              
329             #
330             # jsplit(PATTERN, STRING; LIMIT)
331             #
332             sub jsplit ($$;$) {
333 168     168 1 11963 my $thing = shift;
334 168         212 my $str = shift;
335 168   100     476 my $lim = shift || 0;
336              
337 168 100       406 return splitspace($str, $lim) if !defined $thing;
338              
339 145 100       483 my $pat = 'ARRAY' eq ref $thing
340             ? re($$thing[0], $$thing[1])
341             : re($thing);
342              
343 145 100       383 return splitchar($str, $lim) if $pat eq '';
344 57 50       125 return wantarray ? () : 0 if $str eq '';
    100          
345 50 50       122 return wantarray ? ($str) : 1 if $lim == 1;
    100          
346              
347 43         49 my $cnt = 0;
348 43         48 my(@mat, @ret);
349 43         1175 while (@mat = $str =~ /^($Char*?)($pat)/) {
350 136 50 66     484 if ($mat[0] eq '' && $mat[1] eq '') {
351 0         0 @mat = $str =~ /^($Char)($pat)/;
352 0         0 $str =~ s/^$Char$pat//;
353             } else {
354 136         1445 $str =~ s/^$Char*?$pat//;
355             }
356 136 50       350 if (@mat) {
357 136         213 push @ret, shift @mat;
358 136         150 shift @mat; # $mat[1] eq $2 is to be removed.
359 136         278 push @ret, @mat;
360             }
361 136         233 $cnt++;
362 136 100       346 last if ! CORE::length $str;
363 130 100 100     1453 last if $lim > 1 && $cnt >= $lim - 1;
364             }
365 43 100 100     256 push @ret, $str if $str ne '' || $lim < 0 || $cnt < $lim;
      66        
366 43 100       92 if ($lim == 0) {
367 10   66     69 pop @ret while defined $ret[-1] && $ret[-1] eq '';
368             }
369 43         227 return @ret;
370             }
371              
372             1;
373             __END__