File Coverage

conv.c
Criterion Covered Total %
statement 113 171 66.0
branch 123 364 33.7
condition n/a
subroutine n/a
pod n/a
total 236 535 44.1


line stmt bran cond sub pod time code
1             /* ----------------------------------------------------------------------------
2             * conv.c
3             * convert sjis <=> utf8
4             * ----------------------------------------------------------------------------
5             * Mastering programed by YAMASHINA Hio
6             * ----------------------------------------------------------------------------
7             * $Id: conv.c 4697 2007-09-14 06:17:00Z pho $
8             * ------------------------------------------------------------------------- */
9              
10             #ifdef _MSC_VER
11             #include "EXTERN.h"
12             #include "perl.h"
13             #include "XSUB.h"
14             #include
15             #include
16             #define snprintf _snprintf
17             #endif
18              
19             #include "Japanese.h"
20             #include
21              
22             #define DISP_S2U 0
23             #define DISP_U2S 0
24              
25             #if DISP_U2S
26             #define ECHO_U2S(arg) fprintf arg
27             #define ON_U2S(cmd) cmd
28             #else
29             #define ECHO_U2S(arg)
30             #define ON_U2S(cmd)
31             #endif
32              
33             /* ----------------------------------------------------------------------------
34             * SV* sv_utf8 = xs_sjis_utf8(SV* sv_sjis)
35             * convert string from sjis to utf8.
36             * ------------------------------------------------------------------------- */
37             EXTERN_C
38             SV*
39 24           xs_sjis_utf8(SV* sv_str)
40             {
41             UJ_UINT8* src;
42             STRLEN len;
43            
44             SV_Buf result;
45             const UJ_UINT8* src_end;
46            
47 24 50         if( sv_str==&PL_sv_undef )
48             {
49 0           return newSVsv(&PL_sv_undef);
50             }
51 24 50         if( SvGMAGICAL(sv_str) )
52             {
53 0           mg_get(sv_str);
54             }
55 24 50         if( !SvOK(sv_str) )
56             {
57 0           return newSVsv(&PL_sv_undef);
58             }
59            
60 24           src = (UJ_UINT8*)SvPV(sv_str, len);
61             #if DISP_S2U
62             fprintf(stderr,"Unicode::Japanese::(xs)sjis_utf8\n");
63             bin_dump("in ",src,len);
64             #endif
65 24 50         SV_Buf_init(&result,len*3/2+4);
    100          
66 24           src_end = src+len;
67              
68 144 100         while( src
69             {
70             const UJ_UINT8* ptr;
71 120 100         if( src[0]<0x80 )
72             { /* ASCII */
73             ECHO_U2S((stderr,"ascii: %02x\n",src[0]));
74 92 50         SV_Buf_append_ch(&result,*src);
    0          
    0          
75 92           ++src;
76 92           continue;
77 28 100         }else if( 0xa1<=src[0] && src[0]<=0xdf )
    50          
78             { /* half-width katakana (ja:半角カナ) */
79             ECHO_U2S((stderr,"kana: %02x\n",src[0]));
80 12           ptr = (UJ_UINT8*)&g_s2u_table[(src[0]-0xa1)*3];
81 12           ++src;
82 16 50         }else if( src+1
    50          
    50          
83 16           { /* a two-bytes letter (ja:2バイト文字) */
84 16           const UJ_UINT16 sjis = (src[0]<<8)+src[1]; /* ntohs */
85             ECHO_U2S((stderr,"sjis.dbcs#1: %04x\n",sjis));
86 16           ptr = (UJ_UINT8*)&g_s2u_table[(sjis - 0x8100 + 0x3f)*3];
87 16           src += 2;
88 0 0         }else if( src+1
    0          
    0          
89 0           { /* a two-bytes letter (ja:2バイト文字) */
90 0           const UJ_UINT16 sjis = (src[0]<<8)+src[1]; /* ntohs */
91             ECHO_U2S((stderr,"sjis.dbcs#2: %04x\n",sjis));
92 0           ptr = (UJ_UINT8*)&g_s2u_table[(sjis- 0xe000 + 0x1f3f)*3];
93 0           src += 2;
94             }else
95             { /* unknown */
96             /*fprintf(stderr,"unknown: %02x\n",src[0]); */
97 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
98 0           ++src;
99 0           continue;
100             }
101              
102             ECHO_U2S((stderr,"offset: 0x%04x\n",(int)(ptr-g_s2u_table)));
103             ECHO_U2S((stderr,"utf8-char : %02x %02x %02x\n",ptr[0],ptr[1],ptr[2]));
104 28 50         if( ptr[2] )
105             {
106             /*fprintf(stderr,"utf8-len: [%d]\n",3); */
107 28 100         SV_Buf_append_mem(&result, ptr, 3);
    50          
    50          
108 0 0         }else if( ptr[1] )
109             {
110             /*fprintf(stderr,"utf8-len: [%d]\n",2); */
111 0 0         SV_Buf_append_mem(&result, ptr, 2);
    0          
    0          
112 0 0         }else if( ptr[0] )
113             {
114             /*fprintf(stderr,"utf8-len: [%d]\n",1); */
115 0 0         SV_Buf_append_ch(&result,*ptr);
    0          
    0          
116             }else
117             {
118 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
119             }
120             }
121             #if DISP_S2U
122             bin_dump("out",SV_Buf_getBegin(&result),SV_Buf_getLength(&result));
123             #endif
124 24           SV_Buf_setLength(&result);
125              
126 24           return SV_Buf_getSv(&result);
127             }
128              
129             /* ----------------------------------------------------------------------------
130             * SV* sv_sjis = xs_utf8_sjis(SV* sv_utf8)
131             * convert from utf8 to sjis.
132             * ------------------------------------------------------------------------- */
133             EXTERN_C
134             SV*
135 117           xs_utf8_sjis(SV* sv_str)
136             {
137             const UJ_UINT8* src;
138             STRLEN len;
139             SV_Buf result;
140             const UJ_UINT8* src_end;
141             static const UJ_UINT8 char_null[2] = { '\0', '\0' };
142             static const UJ_UINT8 char_unknown[2] = { '?', '\0' };
143            
144 117 100         if( sv_str==&PL_sv_undef )
145             {
146 1           return newSVsv(&PL_sv_undef);
147             }
148 116 100         if( SvGMAGICAL(sv_str) )
149             {
150 2           mg_get(sv_str);
151             }
152 116 50         if( !SvOK(sv_str) )
153             {
154 0           return newSVsv(&PL_sv_undef);
155             }
156            
157 116           src = (UJ_UINT8*)SvPV(sv_str, len);
158              
159              
160             ECHO_U2S((stderr,"Unicode::Japanese::(xs)utf8_sjis (%p:%ld)\n",src,len));
161             ON_U2S( bin_dump("in ",src,len) );
162              
163 116 50         SV_Buf_init(&result,len+4);
    100          
164 116           src_end = src+len;
165              
166 240 100         while( src
167             {
168             UJ_UINT32 ucs;
169             const UJ_UINT8* sjis_ptr;
170            
171 124 100         if( *src<=0x7f )
172 60           {
173             /* append the block of contiguous ascii chars (ja:ASCIIはまとめて追加〜) */
174 60           int len = 1;
175 832 100         while( src+len
    50          
176             {
177 772           ++len;
178             }
179 60 50         SV_Buf_append_mem(&result,src,len);
    0          
    0          
180 60           src+=len;
181 60           continue;
182             }
183            
184             /* non-ascii */
185 64 100         if( 0xe0<=*src && *src<=0xef )
    100          
186 30           { /* 3-bytes letters. most letters are 3-bytes. */
187 31           const int utf8_len = 3;
188 31           const UJ_UINT32 ucs_min = 0x800;
189 31           const UJ_UINT32 ucs_max = 0xffff;
190             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
191             /* check the length */
192 31 50         if( src+utf8_len<=src_end )
193             { /* noop */
194             }else
195             { /* no enough space in the buffer */
196 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
197 0           ++src;
198 0           continue;
199             }
200             /* check successive bytes */
201 31 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf )
    50          
    50          
    50          
202             { /* noop */
203             }else
204             {
205 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
206 0           ++src;
207 0           continue;
208             }
209            
210             /* compute the code point */
211 31           ucs = ((src[0] & 0x0F)<<12)|((src[1] & 0x3F)<<6)|(src[2] & 0x3F);
212 31           src += utf8_len;
213 31 100         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
214             { /* noop */
215             }else
216             { /* illegal sequence */
217 1 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
218 1           continue;
219             }
220             /* ok. */
221 33 100         }else if( 0xf0<=*src && *src<=0xf7 )
    100          
222 0           {
223 26           const int utf8_len = 4;
224 26           const UJ_UINT32 ucs_min = 0x010000;
225 26           const UJ_UINT32 ucs_max = 0x10ffff;
226             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
227             /* check the length */
228 26 50         if( src+utf8_len<=src_end )
229             { /* noop */
230             }else
231             { /* no enough space in the buffer */
232 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
233 0           ++src;
234 0           continue;
235             }
236             /* check successive bytes */
237 26 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
238 26 50         && 0x80<=src[3] && src[3]<=0xbf )
    50          
239             { /* noop */
240             }else
241             {
242 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
243 0           ++src;
244 0           continue;
245             }
246            
247             /* compute the code point */
248 26           ucs = ((src[0] & 0x07)<<18)|((src[1] & 0x3F)<<12)|
249 26           ((src[2] & 0x3f) << 6)|(src[3] & 0x3F);
250 26           src += utf8_len;
251 26 100         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
252             { /* noop */
253             }else
254             { /* illegal sequence */
255 1 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
256 1           continue;
257             }
258             /* private area (emoji) */
259 25 50         if( 0x0f0000<=ucs && ucs<=0x0fffff )
    50          
260             {
261 25 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
262 25           continue;
263             }
264            
265             /* > U+10FFFF isn't representable in UTF-8 (RFC 3629). */
266 0 0         if( ucs>0x10FFFF )
267             {
268 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
269 0           continue;
270             }
271 7 50         }else if( 0xc0<=*src && *src<=0xdf )
    100          
272 4           {
273 5           const int utf8_len = 2;
274 5           const UJ_UINT32 ucs_min = 0x80;
275 5           const UJ_UINT32 ucs_max = 0x7ff;
276             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
277             /* check the length */
278 5 50         if( src+utf8_len<=src_end )
279             { /* noop */
280             }else
281             { /* no enough space in the buffer */
282 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
283 0           ++src;
284 0           continue;
285             }
286             /* check follow sequences */
287 5 50         if( 0x80<=src[1] && src[1]<=0xbf )
    50          
288             { /* noop */
289             }else
290             {
291 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
292 0           ++src;
293 0           continue;
294             }
295            
296             /* compute the code point */
297 5           ucs = ((src[0] & 0x1F)<<6)|(src[1] & 0x3F);
298 5           src += utf8_len;
299 5 100         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
300             { /* noop */
301             }else
302             { /* illegal sequence */
303 1 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
304 1           continue;
305             }
306            
307             /* ok. */
308 2 50         }else if( 0xf8<=*src && *src<=0xfb )
    100          
309 1           {
310 1           const int utf8_len = 5;
311             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
312             /* check the length */
313 1 50         if( src+utf8_len<=src_end )
314             { /* noop */
315             }else
316             { /* no enough space in the buffer */
317 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
318 0           ++src;
319 0           continue;
320             }
321             /* check successive bytes */
322 1 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
323 1 50         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf )
    50          
    50          
    50          
324             { /* noop */
325             }else
326             {
327 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
328 0           ++src;
329 0           continue;
330             }
331            
332             /* compute the code point */
333             /* > U+10FFFF isn't representable in UTF-8 (RFC 3629). */
334 1           src += utf8_len;
335 1 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
336 1           continue;
337 1 50         }else if( 0xfc<=*src && *src<=0xfd )
    50          
338 1           {
339 1           const int utf8_len = 6;
340             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
341             /* check the length */
342 1 50         if( src+utf8_len<=src_end )
343             { /* noop */
344             }else
345             { /* no enough space in the buffer */
346 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
347 0           ++src;
348 0           continue;
349             }
350             /* check successive bytes */
351 1 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
352 1 50         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf
    50          
    50          
    50          
353 1 50         && 0x80<=src[5] && src[5]<=0xbf )
    50          
354             { /* noop */
355             }else
356             {
357 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
358 0           ++src;
359 0           continue;
360             }
361            
362             /* compute the code point */
363             /* > U+10FFFF isn't representable in UTF-8 (RFC 3629). */
364 1           src += utf8_len;
365 1 50         SV_Buf_append_ch(&result,'?');
    0          
    0          
366 1           continue;
367             }else
368             {
369 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
370 0           ++src;
371 0           continue;
372             }
373            
374             /* ucs => sjis */
375             ECHO_U2S((stderr,"ucs [%04x]\n",ucs));
376 34 100         if( ucs<=0x9FFF )
377             {
378 28           sjis_ptr = g_u2s_table + ucs*2;
379 6 50         }else if( 0xF900<=ucs && ucs<=0xFFFF )
    50          
380             {
381 6           sjis_ptr = g_u2s_table + (ucs - 0xF900 + 0xA000)*2;
382 0 0         }else if( 0x0FE000<=ucs && ucs<=0x0FFFFF )
    0          
383             { /* emoji. */
384 0           sjis_ptr = char_unknown; /* "?\0" */
385             }else
386             {
387 0           sjis_ptr = char_null; /* "\0\0" */
388             }
389 34 100         if( sjis_ptr[0]!=0 || sjis_ptr[1]!=0 )
    50          
390             { /* this letter can actually be mapped. */
391 31 100         if( sjis_ptr[1]!=0 )
392             {
393 23 50         SV_Buf_append_mem(&result, sjis_ptr, 2);
    0          
    0          
394             }else
395             {
396 8 50         SV_Buf_append_ch(&result, *sjis_ptr);
    0          
    0          
397             }
398 3 50         }else if( ucs<=0x7F )
399             {
400 0 0         SV_Buf_append_ch(&result,(UJ_UINT8)ucs);
    0          
    0          
401             }else
402             {
403 3 50         SV_Buf_append_entityref(&result,ucs);
    50          
    50          
    50          
    50          
    0          
    0          
    0          
404             }
405             } /* while */
406              
407             ON_U2S( bin_dump("out",SV_Buf_getBegin(&result),SV_Buf_getLength(&result)) );
408 116           SV_Buf_setLength(&result);
409              
410 116           return SV_Buf_getSv(&result);
411             }
412              
413             /* ----------------------------------------------------------------------------
414             * End Of File.
415             * ------------------------------------------------------------------------- */