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