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