File Coverage

ucs4.c
Criterion Covered Total %
statement 94 139 67.6
branch 86 268 32.0
condition n/a
subroutine n/a
pod n/a
total 180 407 44.2


line stmt bran cond sub pod time code
1             /* ----------------------------------------------------------------------------
2             * ucs4.c
3             * ----------------------------------------------------------------------------
4             * Mastering programed by YAMASHINA Hio
5             * ----------------------------------------------------------------------------
6             * $Id: ucs4.c 41492 2008-02-15 08:26:18Z hio $
7             * ------------------------------------------------------------------------- */
8              
9              
10             #include "Japanese.h"
11              
12             /* ----------------------------------------------------------------------------
13             * convert ucs4 into utf-8
14             * ------------------------------------------------------------------------- */
15             EXTERN_C
16             SV*
17 4           xs_ucs4_utf8(SV* sv_str)
18             {
19             UJ_UINT8* src;
20             STRLEN len;
21             SV_Buf result;
22             const UJ_UINT8* src_end;
23             UJ_UINT8 buf[4];
24              
25 4 50         if( sv_str==&PL_sv_undef )
26             {
27 0           return newSVpvn("",0);
28             }
29 4 50         if( SvGMAGICAL(sv_str) )
30             {
31 0           mg_get(sv_str);
32             }
33 4 50         if( !SvOK(sv_str) )
34             {
35 0           return newSVpvn("",0);
36             }
37            
38 4           src = (UJ_UINT8*)SvPV(sv_str, len);
39 4           src_end = src+(len&~1);
40             /*fprintf(stderr,"Unicode::Japanese::(xs)ucs4_utf8\n",len);*/
41             /*bin_dump("in ",src,len);*/
42 4 50         SV_Buf_init(&result,len*3/2+4);
    50          
43              
44 4 50         if( len&3 )
45             {
46 0           Perl_croak(aTHX_ "Unicode::Japanese::ucs4_utf8, invalid length (not 4*n)");
47             }
48              
49 8 100         for(; src
50             {
51 4           const UJ_UINT32 ucs4 = (src[0]<<24)+(src[1]<<16)+(src[2]<<8)+src[3]; /* ntohs */
52 4 50         if( ucs4<0x80 )
53             {
54 0 0         SV_Buf_append_ch(&result,(UJ_UINT8)ucs4);
    0          
    0          
55 4 50         }else if( ucs4<0x800 )
56             {
57 0           buf[0] = 0xC0 | (ucs4 >> 6);
58 0           buf[1] = 0x80 | (ucs4 & 0x3F);
59 0 0         SV_Buf_append_mem(&result, buf, 2);
    0          
    0          
60 4 50         }else if( ucs4 < 0x10000 )
61             {
62 0           buf[0] = 0xE0 | (ucs4 >> 12);
63 0           buf[1] = 0x80 | ((ucs4 >> 6) & 0x3F);
64 0           buf[2] = 0x80 | (ucs4 & 0x3F);
65 0 0         SV_Buf_append_mem(&result, buf, 3);
    0          
    0          
66 4 50         }else if( ucs4 <= 0x0010FFFF )
67             {
68 4           buf[0] = 0xF0 | (ucs4 >> 18);
69 4           buf[1] = 0x80 | ((ucs4 >> 12) & 0x3F);
70 4           buf[2] = 0x80 | ((ucs4 >> 6) & 0x3F);
71 4           buf[3] = 0x80 | ( ucs4 & 0x3F);
72 4 50         SV_Buf_append_mem(&result, buf, 4);
    0          
    0          
73             }else
74             {
75 0 0         SV_Buf_append_ch(&result,'?');
    0          
    0          
76             }
77             }
78              
79             /*bin_dump("out",result.getBegin(),result.getLength()); */
80 4           SV_Buf_setLength(&result);
81              
82 4           return SV_Buf_getSv(&result);
83             }
84              
85             /* ----------------------------------------------------------------------------
86             * convert utf-8 into ucs4
87             * ------------------------------------------------------------------------- */
88             EXTERN_C
89             SV*
90 41           xs_utf8_ucs4(SV* sv_str)
91             {
92             UJ_UINT8* src;
93             STRLEN len;
94             SV_Buf result;
95             const UJ_UINT8* src_end;
96 41           const char* buf_failed = "\0\0\0?";
97              
98 41 50         if( sv_str==&PL_sv_undef )
99             {
100 0           return newSVpvn("",0);
101             }
102 41 50         if( SvGMAGICAL(sv_str) )
103             {
104 0           mg_get(sv_str);
105             }
106 41 50         if( !SvOK(sv_str) )
107             {
108 0           return newSVpvn("",0);
109             }
110            
111 41           src = (UJ_UINT8*)SvPV(sv_str, len);
112 41           src_end = src+len;
113             /*fprintf(stderr,"Unicode::Japanese::(xs)utf8_ucs4\n",len); */
114             /*bin_dump("in ",src,len); */
115 41 50         SV_Buf_init(&result,len*4);
    100          
116            
117 82 100         while( src
118             {
119             UJ_UINT32 ucs;
120 41 100         if( *src<=0x7f )
121             { /* ascii. */
122 1 50         SV_Buf_append_ch4(&result,htonl(*src));
    50          
    50          
123 1           ++src;
124 1           continue;
125             }
126 40 50         if( 0xc0<=*src && *src<=0xdf )
    100          
127 0           { /* length [2] */
128 1           const int utf8_len = 2;
129 1           const UJ_UINT32 ucs_min = 0x80;
130 1           const UJ_UINT32 ucs_max = 0x7ff;
131 1 50         if( src+1>=src_end ||
132 1 50         src[1]<0x80 || 0xbf
    50          
133             {
134 0 0         SV_Buf_append_ch4(&result,htonl(*src));
    0          
    0          
135 0           ++src;
136 0           continue;
137             }
138            
139             /* compute code point */
140 1           ucs = ((src[0] & 0x1F)<<6)|(src[1] & 0x3F);
141 1           src += utf8_len;
142 1 50         if( ucs_min<=ucs && ucs<=ucs_max )
    0          
143             { /* noop */
144             }else
145             { /* illegal sequence */
146 1 50         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
147 1           continue;
148             }
149            
150             /* ok. */
151 39 50         }else if( 0xe0<=*src && *src<=0xef )
    100          
152 0           { /* length [3] */
153 1           const int utf8_len = 3;
154 1           const UJ_UINT32 ucs_min = 0x800;
155 1           const UJ_UINT32 ucs_max = 0xffff;
156 1 50         if( src+2>=src_end ||
157 1 50         src[1]<0x80 || 0xbf
    50          
158 1 50         src[2]<0x80 || 0xbf
    50          
159             {
160 0 0         SV_Buf_append_ch4(&result,htonl(*src));
    0          
    0          
161 0           ++src;
162 0           continue;
163             }
164            
165             /* compute code point */
166 1           ucs = ((src[0] & 0x0F)<<12)|((src[1] & 0x3F)<<6)|(src[2] & 0x3F);
167 1           src += utf8_len;
168 1 50         if( ucs_min<=ucs && ucs<=ucs_max )
    0          
169             { /* noop */
170             }else
171             { /* illegal sequence */
172 1 50         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
173 1           continue;
174             }
175            
176 0 0         if( ucs<0xD800 || ucs>0xDBFF )
    0          
177             { /* normal char, noop */
178             }else
179             { /* delete surrogate pair range */
180 0 0         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
181 0           continue;
182             }
183            
184             /* ok. */
185 38 50         }else if( 0xf0<=*src && *src<=0xf7 )
    100          
186 35           { /* length [4] */
187 36           const int utf8_len = 4;
188 36           const UJ_UINT32 ucs_min = 0x010000;
189 36           const UJ_UINT32 ucs_max = 0x10ffff;
190 36 50         if( src+3>=src_end ||
191 36 50         src[1]<0x80 || 0xbf
    50          
192 36 50         src[2]<0x80 || 0xbf
    50          
193 36 50         src[3]<0x80 || 0xbf
    50          
194             {
195 0 0         SV_Buf_append_ch4(&result,htonl(*src));
    0          
    0          
196 0           ++src;
197 0           continue;
198             }
199            
200             /* compute code point */
201 36           ucs = ((src[0] & 0x07)<<18)|((src[1] & 0x3F)<<12)|
202 36           ((src[2] & 0x3f) << 6)|(src[3] & 0x3F);
203 36           src += utf8_len;
204 36 100         if( ucs_min<=ucs && ucs<=ucs_max )
    50          
205             { /* noop */
206             }else
207             { /* illegal sequence */
208 1 50         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
209 1           continue;
210             }
211            
212             /* ok. */
213 2 50         }else if( 0xf8<=*src && *src<=0xfb )
    100          
214 1           {
215 1           const int utf8_len = 5;
216 1 50         if( src+utf8_len<=src_end )
217             { /* noop */
218             }else
219             { /* no enough sequence */
220 0 0         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
221 0           ++src;
222 0           continue;
223             }
224             /* check follow sequences */
225 1 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
226 1 50         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf )
    50          
    50          
    50          
227             { /* noop */
228             }else
229             {
230 0 0         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
231 0           ++src;
232 0           continue;
233             }
234            
235             /* compute code point */
236 1           src += utf8_len;
237 1 50         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
238 1           continue;
239 1 50         }else if( 0xfc<=*src && *src<=0xfd )
    50          
240 1           {
241 1           const int utf8_len = 6;
242 1 50         if( src+utf8_len<=src_end )
243             { /* noop */
244             }else
245             { /* no enough sequence */
246 0 0         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
247 0           ++src;
248 0           continue;
249             }
250             /* check follow sequences */
251 1 50         if( 0x80<=src[1] && src[1]<=0xbf && 0x80<=src[2] && src[2]<=0xbf
    50          
    50          
    50          
252 1 50         && 0x80<=src[3] && src[3]<=0xbf && 0x80<=src[4] && src[4]<=0xbf
    50          
    50          
    50          
253 1 50         && 0x80<=src[5] && src[5]<=0xbf )
    50          
254             { /* noop */
255             }else
256             {
257 0 0         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
258 0           ++src;
259 0           continue;
260             }
261            
262             /* compute code point */
263 1           src += utf8_len;
264 1 50         SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed);
    0          
    0          
265 1           continue;
266             }else
267             { /* invalid */
268 0 0         SV_Buf_append_ch4(&result,htonl(*src));
    0          
    0          
269 0           ++src;
270 0           continue;
271             }
272              
273 35 50         SV_Buf_append_ch4(&result,htonl(ucs));
    0          
    0          
274             /*bin_dump("now",dst_begin,dst-dst_begin); */
275             }
276              
277             /*bin_dump("out",result.getBegin(),result.getLength()); */
278 41           SV_Buf_setLength(&result);
279              
280 41           return SV_Buf_getSv(&result);
281             }
282              
283             /* ----------------------------------------------------------------------------
284             * End Of File.
285             * ------------------------------------------------------------------------- */