File Coverage

sjis_imode1.c
Criterion Covered Total %
statement 76 209 36.3
branch 67 430 15.5
condition n/a
subroutine n/a
pod n/a
total 143 639 22.3


line stmt bran cond sub pod time code
1              
2             /* $Id: sjis_imode1.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_imode1_utf8(SV* sv_sjis)
34             * convert sjis(imode1) into utf8.
35             * ------------------------------------------------------------------------- */
36             EXTERN_C
37             SV*
38 257           xs_sjis_imode1_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 257 50         if( sv_str==&PL_sv_undef )
47             {
48 0           return newSVsv(&PL_sv_undef);
49             }
50 257 50         if( SvGMAGICAL(sv_str) )
51             {
52 0           mg_get(sv_str);
53             }
54 257 50         if( !SvOK(sv_str) )
55             {
56 0           return newSVsv(&PL_sv_undef);
57             }
58            
59 257           src = (UJ_UINT8*)SvPV(sv_str, len);
60             #if DISP_S2U
61             fprintf(stderr,"Unicode::Japanese::(xs)sjis_utf8_imode1\n",len);
62             bin_dump("in ",src,len);
63             #endif
64 257 50         SV_Buf_init(&result,len*3/2+4);
    50          
65 257           src_end = src+len;
66              
67 514 100         while( src
68             {
69             const UJ_UINT8* ptr;
70 257 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_UINT32* emoji32 = &g_ei2u1_table[num&0x1ff];
87 0 0         if( ((char*)emoji32)[3]!=0 )
88             {
89             /*fprintf(stderr,"utf8-len: [%d]\n",4); */
90 0 0         SV_Buf_append_ch4(&result, *emoji32);
    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 257 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 = &g_s2u_table[(src[0]-0xa1)*3];
103 0           ++src;
104 257 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 = &g_s2u_table[(sjis - 0x8100 + 0x3f)*3];
109 1           src += 2;
110 256 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 256           ptr32 = &g_ei2u1_table[((src[0]&1)<<8)|src[1]];
115 256 100         if( ((char*)ptr32)[3]!=0 )
116             {
117 179 50         SV_Buf_append_ch4(&result, *ptr32);
    0          
    0          
118 179           src += 2;
119 179           continue;
120 77 50         }else if( *ptr32 )
121             {
122 77 50         SV_Buf_append_mem(&result, ptr32, strlen((char*)ptr32));
    0          
    0          
123 77           src += 2;
124 77           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 257           SV_Buf_setLength(&result);
169              
170 257           return SV_Buf_getSv(&result);
171             }
172              
173             /* ---------------------------------------------------------------------------
174             * utf8 ==> imode1
175             * ------------------------------------------------------------------------- */
176             EXTERN_C
177             SV*
178 28           xs_utf8_sjis_imode1(SV* sv_str)
179             {
180             UJ_UINT8* src;
181             STRLEN len;
182             SV_Buf result;
183             const UJ_UINT8* src_end;
184              
185 28 50         if( sv_str==&PL_sv_undef )
186             {
187 0           return newSVsv(&PL_sv_undef);
188             }
189 28 50         if( SvGMAGICAL(sv_str) )
190             {
191 0           mg_get(sv_str);
192             }
193 28 50         if( !SvOK(sv_str) )
194             {
195 0           return newSVsv(&PL_sv_undef);
196             }
197 28           src = (UJ_UINT8*)SvPV(sv_str, len);
198              
199             ECHO_U2S((stderr,"Unicode::Japanese::(xs)utf8_sjis_imode1\n"));
200             ON_U2S( bin_dump("in ",src,len) );
201              
202 28 50         SV_Buf_init(&result,len+4);
    50          
203 28           src_end = src+len;
204              
205 56 100         while( src
206             {
207             UJ_UINT32 ucs;
208             const UJ_UINT8* sjis_ptr;
209            
210 28 50         if( *src<=0x7f )
211 0           {
212             /* ascii chars sequence (ja:ASCIIはまとめて追加〜) */
213 0           int len = 1;
214 0 0         while( src+len
    0          
215             {
216 0           ++len;
217             }
218 0 0         SV_Buf_append_mem(&result,src,len);
    0          
    0          
219 0           src+=len;
220 0           continue;
221             }
222            
223             /* non-ascii */
224 28 50         if( 0xe0<=*src && *src<=0xef )
    100          
225 1           { /* 3byte range. mostly enter here. */
226 1           const int utf8_len = 3;
227 1           const UJ_UINT32 ucs_min = 0x800;
228 1           const UJ_UINT32 ucs_max = 0xffff;
229             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
230             /* check length */
231 1 50         if( src+utf8_len<=src_end )
232             { /* noop */
233             }else
234             { /* no enough sequence */
235 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
236 0           ++src;
237 0           continue;
238             }
239             /* check follow sequences */
240 1 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf )
    50          
    50          
    50          
241             { /* noop */
242             }else
243             {
244 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
245 0           ++src;
246 0           continue;
247             }
248            
249             /* compute code point */
250 1           ucs = ((src[0] & 0x0F)<<12)|((src[1] & 0x3F)<<6)|(src[2] & 0x3F);
251 1           src += utf8_len;
252 1 50         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
253             { /* noop */
254             }else
255             { /* illegal sequence */
256 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
257 0           continue;
258             }
259             /* ok. */
260 27 50         }else if( 0xf0<=*src && *src<=0xf7 )
    50          
261 0           {
262 27           const int utf8_len = 4;
263 27           const UJ_UINT32 ucs_min = 0x010000;
264 27           const UJ_UINT32 ucs_max = 0x10ffff;
265             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
266             /* check length */
267 27 50         if( src+utf8_len<=src_end )
268             { /* noop */
269             }else
270             { /* no enough sequence */
271 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
272 0           ++src;
273 0           continue;
274             }
275             /* check follow sequences */
276 27 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
277 27 50         && 0x80<=src[3] && src[3]<=0xbf )
    50          
278             { /* noop */
279             }else
280             {
281 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
282 0           ++src;
283 0           continue;
284             }
285            
286             /* compute code point */
287 27           ucs = ((src[0] & 0x07)<<18)|((src[1] & 0x3F)<<12)|
288 27           ((src[2] & 0x3f) << 6)|(src[3] & 0x3F);
289 27           src += utf8_len;
290 27 50         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
291             { /* noop */
292             }else
293             { /* illegal sequence */
294 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
295 0           continue;
296             }
297             /* private area: block emoji */
298 27 50         if( 0x0f0000<=ucs && ucs<=0x0fffff )
    50          
299 27           {
300             const UJ_UINT16* sjis16;
301             const UJ_UINT8* sjis8;
302 27 50         if( ucs<0x0fe000 )
303             { /* unknown area. */
304 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
305 0           continue;
306             }
307             /* imode */
308 27           sjis16 = &g_eu2i1_table[ucs - 0x0fe000];
309 27           sjis8 = (UJ_UINT8*)sjis16;
310 27 100         if( sjis8[1]!=0 )
311             { /* double-byte char */
312 24 50         SV_Buf_append_ch2(&result, *sjis16);
    0          
    0          
313 3 50         }else if( sjis8[0]!=0 )
314             { /* single-byte char, is it exists?? */
315 3 50         SV_Buf_append_ch(&result, *sjis8);
    0          
    0          
316             }else
317             { /* no mapping */
318 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
319             }
320 27           continue;
321             }
322            
323             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
324 0 0         if( ucs>0x10FFFF )
325             {
326 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
327 0           continue;
328             }
329 0 0         }else if( 0xc0<=*src && *src<=0xdf )
    0          
330 0           {
331 0           const int utf8_len = 2;
332 0           const UJ_UINT32 ucs_min = 0x80;
333 0           const UJ_UINT32 ucs_max = 0x7ff;
334             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
335             /* check length */
336 0 0         if( src+utf8_len<=src_end )
337             { /* noop */
338             }else
339             { /* no enough sequence */
340 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
341 0           ++src;
342 0           continue;
343             }
344             /* check follow sequences */
345 0 0         if( 0x80<=src[1] && src[1]<=0xbf )
    0          
346             { /* noop */
347             }else
348             {
349 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
350 0           ++src;
351 0           continue;
352             }
353            
354             /* compute code point */
355 0           ucs = ((src[0] & 0x1F)<<6)|(src[1] & 0x3F);
356 0           src += utf8_len;
357 0 0         if( ucs_min<=ucs && ucs<=ucs_max )
    0          
358             { /* noop */
359             }else
360             { /* illegal sequence */
361 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
362 0           continue;
363             }
364            
365             /* ok. */
366 0 0         }else if( 0xf8<=*src && *src<=0xfb )
    0          
367 0           {
368 0           const int utf8_len = 5;
369             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
370             /* check length */
371 0 0         if( src+utf8_len<=src_end )
372             { /* noop */
373             }else
374             { /* no enough sequence */
375 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
376 0           ++src;
377 0           continue;
378             }
379             /* check follow sequences */
380 0 0         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    0          
    0          
    0          
381 0 0         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf )
    0          
    0          
    0          
382             { /* noop */
383             }else
384             {
385 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
386 0           ++src;
387 0           continue;
388             }
389            
390             /* compute code point */
391             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
392 0           src += utf8_len;
393 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
394 0           continue;
395 0 0         }else if( 0xfc<=*src && *src<=0xfd )
    0          
396 0           {
397 0           const int utf8_len = 6;
398             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
399             /* check length */
400 0 0         if( src+utf8_len<=src_end )
401             { /* noop */
402             }else
403             { /* no enough sequence */
404 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
405 0           ++src;
406 0           continue;
407             }
408             /* check follow sequences */
409 0 0         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    0          
    0          
    0          
410 0 0         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf
    0          
    0          
    0          
411 0 0         && 0x80<=src[5] && src[5]<=0xbf )
    0          
412             { /* noop */
413             }else
414             {
415 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
416 0           ++src;
417 0           continue;
418             }
419            
420             /* compute code point */
421             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
422 0           src += utf8_len;
423 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
424 0           continue;
425             }else
426             {
427 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
428 0           ++src;
429 0           continue;
430             }
431            
432             /* ucs => sjis */
433             ECHO_U2S((stderr,"ucs [%04x]\n",ucs));
434 1 50         if( ucs<=0x9FFF )
435             {
436 1           sjis_ptr = g_u2s_table + ucs*2;
437 0 0         }else if( 0xF900<=ucs && ucs<=0xFFFF )
    0          
438             {
439 0           sjis_ptr = g_u2s_table + (ucs - 0xF900 + 0xA000)*2;
440 0 0         }else if( 0x0FE000<=ucs && ucs<=0x0FFFFF )
    0          
441             {
442 0           sjis_ptr = (UJ_UINT8*)"?"; /* exactly 2byte: "?\0" */
443             }else
444             {
445 0           sjis_ptr = (UJ_UINT8*)"\0"; /* exactly 2byte: "\0\0" */
446             }
447 1 50         if( sjis_ptr[0]!=0 || sjis_ptr[1]!=0 )
    0          
448             { /* mapping dest exists. */
449 1 50         if( sjis_ptr[1]!=0 )
450             {
451 1 50         SV_Buf_append_mem(&result, sjis_ptr, 2);
    0          
    0          
452             }else
453             {
454 0 0         SV_Buf_append_ch(&result,sjis_ptr[0]);
    0          
    0          
455             }
456 0 0         }else if( ucs<=0x7F )
457             {
458 0 0         SV_Buf_append_ch(&result,(UJ_UINT8)ucs);
    0          
    0          
459             }else
460             {
461 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
462             }
463             } /* while */
464              
465             ON_U2S( bin_dump("out",SV_Buf_getBegin(&result),SV_Buf_getLength(&result)) );
466 28           SV_Buf_setLength(&result);
467              
468 28           return SV_Buf_getSv(&result);
469             }
470              
471             /* ----------------------------------------------------------------------------
472             * End of File.
473             * ------------------------------------------------------------------------- */
474