File Coverage

ucs2_utf8.c
Criterion Covered Total %
statement 97 139 69.7
branch 93 284 32.7
condition n/a
subroutine n/a
pod n/a
total 190 423 44.9


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