File Coverage

sjis_jsky1.c
Criterion Covered Total %
statement 96 237 40.5
branch 89 506 17.5
condition n/a
subroutine n/a
pod n/a
total 185 743 24.9


line stmt bran cond sub pod time code
1              
2             /* $Id: sjis_jsky1.c 4692 2007-09-07 10:10:20Z 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_jsky1_utf8(SV* sv_sjis)
27             * convert sjis(jsky1) into utf8.
28             * ------------------------------------------------------------------------- */
29             EXTERN_C
30             SV*
31 7           xs_sjis_jsky1_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 7 50         if( sv_str==&PL_sv_undef )
40             {
41 0           return newSVsv(&PL_sv_undef);
42             }
43 7 50         if( SvGMAGICAL(sv_str) )
44             {
45 0           mg_get(sv_str);
46             }
47 7 50         if( !SvOK(sv_str) )
48             {
49 0           return newSVsv(&PL_sv_undef);
50             }
51            
52 7           src = (UJ_UINT8*)SvPV(sv_str, len);
53             #if DISP_S2U
54             fprintf(stderr,"Unicode::Japanese::(xs)sjis_utf8_jsky1, len=%d\n",len);
55             bin_dump("in ",src,len);
56             #endif
57 7 50         SV_Buf_init(&result,len*3/2+4);
    50          
58 7           src_end = src+len;
59              
60 14 100         while( src
61             {
62             const UJ_UINT8* ptr;
63 7 100         if( src[0]<0x80 )
64 5           { /* ASCII */
65             UJ_UINT8* begin;
66             int j1;
67             ECHO_U2S((stderr,"ascii: %02x\n",src[0]));
68            
69 5 50         if( src[0]!='\x1b' || src+2>=src_end || src[1]!='$' )
    50          
    50          
70             { /* not emoji. */
71 0 0         SV_Buf_append_ch(&result,*src);
    0          
    0          
72 0           ++src;
73 0           continue;
74             }
75             /*fprint(stderr,"detect j-sky emoji-start escape\n"); */
76             /* E_JSKY_1 */
77 5 50         if( src[2]=='E' || src[2]=='F' || src[2]=='G' )
    100          
    50          
78             {
79 5           j1 = (src[2]-'E')<<8;
80             ECHO_U2S((stderr,"src[2]: %02x '%c' j1:%04x\n",src[2],src[2],j1));
81             }else
82             {
83             /*fprintf(stderr,"first char is invalid"); */
84 0 0         SV_Buf_append_ch(&result,*src);
    0          
    0          
85 0           ++src;
86 0           continue;
87             }
88            
89 5           begin = src;
90 5           src += 3;
91             /* E_JSKY_2 */
92 10 100         while( src
93             {
94 8 100         if( '!'<=src[0] && src[0]<='z' )
    50          
95             {
96 5           ++src;
97 5           continue;
98             }
99 3           break;
100             }
101 5 100         if( src
    50          
102             {
103             /* accept, normally. */
104 2 50         }else if( src==src_end )
105             {
106             /* accept, without terminator. */
107             }else
108             {
109             /* invalid, rollback. */
110 0 0         SV_Buf_append_ch(&result, '\x1b');
    0          
    0          
111 0           src = begin+1;
112 0           continue;
113             }
114 10 100         for( ptr = begin+3; ptr
115             {
116             /*fprintf(stderr," <%c%c:%04x>\n",begin[2],*ptr,j1+*ptr); */
117             /*fprintf(stderr," => %04x\n",g_ej2u1_table[j1+*ptr]); */
118 5           const UJ_UINT8* str = (UJ_UINT8*)&g_ej2u1_table[j1+*ptr];
119             /*fprintf(stderr," len: %d\n",str[3]?4:strlen((char*)str)); */
120 5 50         SV_Buf_append_mem(&result,str,str[3]?4:strlen((char*)str));
    50          
    0          
    0          
    0          
    50          
    50          
121             }
122             /*fprintf(stderr,"j-sky string done.\n"); */
123            
124             /* '\x0f' をスキップ. */
125             /* src==src_end の時はバッファを超えるけど, */
126             /* その時はこれ以上はアクセスしないので気にしない. */
127 5           ++src;
128 5           continue;
129 2 50         }else if( 0xa1<=src[0] && src[0]<=0xdf )
    0          
130             { /* half-width katakana (ja:半角カナ) */
131             ECHO_U2S((stderr,"kana: %02x\n",src[0]));
132 0           ptr = (UJ_UINT8*)&g_s2u_table[(src[0]-0xa1)*3];
133 0           ++src;
134 2 50         }else if( src+1
    50          
    50          
135 2           { /* a double-byte letter (ja:2バイト文字) */
136 2           const UJ_UINT16 sjis = (src[0]<<8)+src[1]; /* ntohs */
137             ECHO_U2S((stderr,"sjis.dbcs#1: %04x\n",sjis));
138 2           ptr = (UJ_UINT8*)&g_s2u_table[(sjis - 0x8100 + 0x3f)*3];
139 2           src += 2;
140 0 0         }else if( src+1
    0          
    0          
141 0           { /* a double-byte letter (ja:2バイト文字) */
142 0           const UJ_UINT16 sjis = (src[0]<<8)+src[1]; /* ntohs */
143             ECHO_U2S((stderr,"sjis.dbcs#2: %04x\n",sjis));
144 0           ptr = (UJ_UINT8*)&g_s2u_table[(sjis- 0xe000 + 0x1f3f)*3];
145 0           src += 2;
146             }else
147             { /* unknown */
148             /*fprintf(stderr,"unknown: %02x\n",src[0]); */
149 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
150 0           ++src;
151 0           continue;
152             }
153              
154             ECHO_U2S((stderr,"offset: 0x%04x\n",ptr-g_s2u_table));
155             ECHO_U2S((stderr,"utf8-char : %02x %02x %02x\n",ptr[0],ptr[1],ptr[2]));
156 2 50         if( ptr[2] )
157             {
158             /*fprintf(stderr,"utf8-len: [%d]\n",3); */
159 2 50         SV_Buf_append_mem(&result, ptr, 3);
    0          
    0          
160 0 0         }else if( ptr[1] )
161             {
162             /*fprintf(stderr,"utf8-len: [%d]\n",2); */
163 0 0         SV_Buf_append_mem(&result, ptr, 2);
    0          
    0          
164 0 0         }else if( ptr[0] )
165             {
166             /*fprintf(stderr,"utf8-len: [%d]\n",1); */
167 0 0         SV_Buf_append_ch(&result,*ptr);
    0          
    0          
168             }else
169             {
170 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
171             }
172             }
173             ON_S2U( bin_dump("out",SV_Buf_getBegin(&result),SV_Buf_getLength(&result)) );
174 7           SV_Buf_setLength(&result);
175              
176 7           return SV_Buf_getSv(&result);
177             }
178              
179             /* ---------------------------------------------------------------------------
180             * utf8 ==> jsky1
181             * ------------------------------------------------------------------------- */
182             EXTERN_C
183             SV*
184 29           xs_utf8_sjis_jsky1(SV* sv_str)
185             {
186             UJ_UINT8* src;
187             STRLEN len;
188             SV_Buf result;
189             const UJ_UINT8* src_end;
190              
191 29 50         if( sv_str==&PL_sv_undef )
192             {
193 0           return newSVsv(&PL_sv_undef);
194             }
195 29 50         if( SvGMAGICAL(sv_str) )
196             {
197 0           mg_get(sv_str);
198             }
199 29 50         if( !SvOK(sv_str) )
200             {
201 0           return newSVsv(&PL_sv_undef);
202             }
203 29           src = (UJ_UINT8*)SvPV(sv_str, len);
204              
205             ECHO_U2S((stderr,"Unicode::Japanese::(xs)utf8_sjis_jsky1\n"));
206             ON_U2S( bin_dump("in ",src,len) );
207              
208 29 50         SV_Buf_init(&result,len+4);
    50          
209 29           src_end = src+len;
210              
211 58 100         while( src
212             {
213             UJ_UINT32 ucs;
214             const UJ_UINT8* sjis_ptr;
215            
216 29 50         if( *src<=0x7f )
217 0           {
218             /* ascii chars sequence (ja:ASCIIはまとめて追加〜) */
219 0           int len = 1;
220 0 0         while( src+len
    0          
221             {
222 0           ++len;
223             }
224 0 0         SV_Buf_append_mem(&result,src,len);
    0          
    0          
225 0           src+=len;
226 0           continue;
227             }
228            
229             /* non-ascii */
230 29 50         if( 0xe0<=*src && *src<=0xef )
    100          
231 2           { /* 3byte range. mostly enter here. */
232 2           const int utf8_len = 3;
233 2           const UJ_UINT32 ucs_min = 0x800;
234 2           const UJ_UINT32 ucs_max = 0xffff;
235             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
236             /* check length */
237 2 50         if( src+utf8_len<=src_end )
238             { /* noop */
239             }else
240             { /* no enough sequence */
241 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
242 0           ++src;
243 0           continue;
244             }
245             /* check follow sequences */
246 2 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf )
    50          
    50          
    50          
247             { /* noop */
248             }else
249             {
250 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
251 0           ++src;
252 0           continue;
253             }
254            
255             /* compute code point */
256 2           ucs = ((src[0] & 0x0F)<<12)|((src[1] & 0x3F)<<6)|(src[2] & 0x3F);
257 2           src += utf8_len;
258 2 50         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
259             { /* noop */
260             }else
261             { /* illegal sequence */
262 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
263 0           continue;
264             }
265             /* ok. */
266 27 50         }else if( 0xf0<=*src && *src<=0xf7 )
    50          
267 0           {
268 27           const int utf8_len = 4;
269 27           const UJ_UINT32 ucs_min = 0x010000;
270 27           const UJ_UINT32 ucs_max = 0x10ffff;
271             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
272             /* check length */
273 27 50         if( src+utf8_len<=src_end )
274             { /* noop */
275             }else
276             { /* no enough sequence */
277 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
278 0           ++src;
279 0           continue;
280             }
281             /* check follow sequences */
282 27 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
283 27 50         && 0x80<=src[3] && src[3]<=0xbf )
    50          
284             { /* noop */
285             }else
286             {
287 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
288 0           ++src;
289 0           continue;
290             }
291            
292             /* compute code point */
293 27           ucs = ((src[0] & 0x07)<<18)|((src[1] & 0x3F)<<12)|
294 27           ((src[2] & 0x3f) << 6)|(src[3] & 0x3F);
295 27           src += utf8_len;
296 27 50         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
297             { /* noop */
298             }else
299             { /* illegal sequence */
300 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
301 0           continue;
302             }
303             /* private area: block emoji */
304 27 50         if( 0x0f0000<=ucs && ucs<=0x0fffff )
    50          
305 27           {
306             const UJ_UINT8* sjis;
307 27 50         if( ucs<0x0fe000 )
308             { /* unknown area. */
309 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
310 0           continue;
311             }
312             /* j-sky1 emoji */
313 27           sjis = &g_eu2j1_table[(ucs - 0x0fe000)*5];
314             /*fprintf(stderr," emoji: %02x %02x %02x %02x %02x\n", */
315             /* sjis[0],sjis[1],sjis[2],sjis[3],sjis[4]); */
316 27 100         if( sjis[4]!=0 )
317             { /* 5 bytes */
318 24 50         SV_Buf_append_ch5(&result,sjis);
    0          
    0          
319 3 50         }else if( sjis[3]!=0 )
320             { /* 4 bytes. */
321             assert("not reach here" && 0);
322 0 0         SV_Buf_append_mem(&result, sjis, 4);
    0          
    0          
323 3 50         }else if( sjis[2]!=0 )
324             { /* 3 bytes. */
325             assert("not reach here" && 0);
326 0 0         SV_Buf_append_mem(&result, sjis, 3);
    0          
    0          
327 3 50         }else if( sjis[1]!=0 )
328             { /* 2 bytes. */
329 0 0         SV_Buf_append_mem(&result,sjis, 2);
    0          
    0          
330 3 50         }else if( sjis[0]!=0 )
331             { /* 1 byte. */
332 3 50         SV_Buf_append_ch(&result,*sjis);
    0          
    0          
333             }else
334             { /* no mapping */
335 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
336             }
337 27           continue;
338             }
339            
340             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
341 0 0         if( ucs>0x10FFFF )
342             {
343 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
344 0           continue;
345             }
346 0 0         }else if( 0xc0<=*src && *src<=0xdf )
    0          
347 0           {
348 0           const int utf8_len = 2;
349 0           const UJ_UINT32 ucs_min = 0x80;
350 0           const UJ_UINT32 ucs_max = 0x7ff;
351             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
352             /* check length */
353 0 0         if( src+utf8_len<=src_end )
354             { /* noop */
355             }else
356             { /* no enough sequence */
357 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
358 0           ++src;
359 0           continue;
360             }
361             /* check follow sequences */
362 0 0         if( 0x80<=src[1] && src[1]<=0xbf )
    0          
363             { /* noop */
364             }else
365             {
366 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
367 0           ++src;
368 0           continue;
369             }
370            
371             /* compute code point */
372 0           ucs = ((src[0] & 0x1F)<<6)|(src[1] & 0x3F);
373 0           src += utf8_len;
374 0 0         if( ucs_min<=ucs && ucs<=ucs_max )
    0          
375             { /* noop */
376             }else
377             { /* illegal sequence */
378 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
379 0           continue;
380             }
381            
382             /* ok. */
383 0 0         }else if( 0xf8<=*src && *src<=0xfb )
    0          
384 0           {
385 0           const int utf8_len = 5;
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             { /* noop */
400             }else
401             {
402 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
403 0           ++src;
404 0           continue;
405             }
406            
407             /* compute code point */
408             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
409 0           src += utf8_len;
410 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
411 0           continue;
412 0 0         }else if( 0xfc<=*src && *src<=0xfd )
    0          
413 0           {
414 0           const int utf8_len = 6;
415             ECHO_U2S((stderr,"utf8-len: [%d]\n",utf8_len));
416             /* check length */
417 0 0         if( src+utf8_len<=src_end )
418             { /* noop */
419             }else
420             { /* no enough sequence */
421 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
422 0           ++src;
423 0           continue;
424             }
425             /* check follow sequences */
426 0 0         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    0          
    0          
    0          
427 0 0         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf
    0          
    0          
    0          
428 0 0         && 0x80<=src[5] && src[5]<=0xbf )
    0          
429             { /* noop */
430             }else
431             {
432 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
433 0           ++src;
434 0           continue;
435             }
436            
437             /* compute code point */
438             /* > U+10FFFF not supported by UTF-8 (RFC 3629). */
439 0           src += utf8_len;
440 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
441 0           continue;
442             }else
443             {
444 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
445 0           ++src;
446 0           continue;
447             }
448            
449             /* ucs => sjis */
450             ECHO_U2S((stderr,"ucs [%04x]\n",ucs));
451 2 50         if( ucs<=0x9FFF )
452             {
453 2           sjis_ptr = g_u2s_table + ucs*2;
454 0 0         }else if( 0xF900<=ucs && ucs<=0xFFFF )
    0          
455             {
456 0           sjis_ptr = g_u2s_table + (ucs - 0xF900 + 0xA000)*2;
457 0 0         }else if( 0x0FE000<=ucs && ucs<=0x0FFFFF )
    0          
458             {
459 0           sjis_ptr = (UJ_UINT8*)"?"; /* exactly 2byte: "?\0" */
460             }else
461             {
462 0           sjis_ptr = (UJ_UINT8*)"\0"; /* exactly 2byte: "\0\0" */
463             }
464 2 50         if( sjis_ptr[0]!=0 || sjis_ptr[1]!=0 )
    0          
465             { /* mapping dest exists. */
466 2 50         if( sjis_ptr[1]!=0 )
467             {
468 2 50         SV_Buf_append_mem(&result, sjis_ptr, 2);
    0          
    0          
469             }else
470             {
471 0 0         SV_Buf_append_ch(&result,sjis_ptr[0]);
    0          
    0          
472             }
473 0 0         }else if( ucs<=0x7F )
474             {
475 0 0         SV_Buf_append_ch(&result,(UJ_UINT8)ucs);
    0          
    0          
476             }else
477             {
478 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
479             }
480             } /* while */
481              
482             ON_U2S( bin_dump("out",SV_Buf_getBegin(&result),SV_Buf_getLength(&result)) );
483 29           SV_Buf_setLength(&result);
484              
485 29           sv_2mortal(SV_Buf_getSv(&result));
486             {
487             /* packing J-SKY emoji escapes */
488             SV_Buf pack;
489             UJ_UINT8* ptr;
490 29           UJ_UINT8 tmpl[5] = { '\x1b','$',0,0,'\x0f',};
491            
492 29 50         SV_Buf_init(&pack,SV_Buf_getLength(&result));
    50          
493 29           src = SV_Buf_getBegin(&result);
494 29           src_end = src + SV_Buf_getLength(&result);
495 29           ptr = src;
496 29 50         for( ; src+5*2-1
497             {
498             UJ_UINT8 ch1;
499             /* E_JSKY_START "\x1b\$", */
500 0 0         if( src[0]!='\x1b' ) continue;
501 0 0         if( src[1]!='$' ) continue;
502             /* E_JSKY1 '[EFG]', */
503             /*fprintf(stderr," found emoji-start\n"); */
504 0 0         if( src[2]!='E' && src[2]!='F' && src[2]!='G' )
    0          
    0          
505             {
506             /*fprintf(stderr," invalid ch1 [%x:%02x]\n",src[2],src[2]); */
507 0           continue;
508             }
509 0           ch1 = src[2];
510             /* E_JSKY2 '[\!-\;\=-z\xbc]', */
511 0 0         if( src[3]<'!' || 'z'
    0          
512             {
513             /*fprintf(stderr," invalid ch2 [%02x]\n",src[3]); */
514 0           continue;
515             }
516             /* E_JSKY_END "\x0f", */
517 0 0         if( src[4]!='\x0f' ) continue;
518              
519             /*fprintf(stderr," found first emoji [%02x:%c]\n",ch1,ch1); */
520 0           src += 5;
521 0 0         SV_Buf_append_mem(&pack,ptr,(src-1)-ptr);
    0          
    0          
522 0           tmpl[2] = ch1;
523 0 0         for( ; src_end-src>=5; src+= 5 )
524             {
525 0           tmpl[3] = src[3];
526 0 0         if( memcmp(src,tmpl,5)!=0 ) break;
527             /*fprintf(stderr," packing...[%02x]\n",src[3]); */
528 0 0         SV_Buf_append_ch(&pack,src[3]);
    0          
    0          
529             }
530             /*fprintf(stderr," pack done.\n"); */
531 0 0         SV_Buf_append_ch(&pack,'\x0f');
    0          
    0          
532 0           ptr = src;
533             }
534             /*fprintf(stderr," pack complete.\n"); */
535             /*fprintf(stderr," append len %0d\n",src_end-ptr); */
536 29 50         if( ptr!=src_end )
537             {
538 29 50         SV_Buf_append_mem(&pack,ptr,src_end-ptr);
    50          
    100          
539             }
540              
541             ON_U2S( bin_dump("out",SV_Buf_getBegin(&pack),SV_Buf_getLength(&pack)) );
542 29           SV_Buf_setLength(&pack);
543              
544 29           return SV_Buf_getSv(&pack);
545             }
546             }
547              
548             /* ----------------------------------------------------------------------------
549             * End of File.
550             * ------------------------------------------------------------------------- */