File Coverage

sjis_imode2.c
Criterion Covered Total %
statement 72 209 34.4
branch 65 430 15.1
condition n/a
subroutine n/a
pod n/a
total 137 639 21.4


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