File Coverage

sjis_doti.c
Criterion Covered Total %
statement 74 205 36.1
branch 67 422 15.8
condition n/a
subroutine n/a
pod n/a
total 141 627 22.4


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