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