Branch data Line data Source code
1 : : /*
2 : : * _codecs_cn.c: Codecs collection for Mainland Chinese encodings
3 : : *
4 : : * Written by Hye-Shik Chang <perky@FreeBSD.org>
5 : : */
6 : :
7 : : #include "cjkcodecs.h"
8 : : #include "mappings_cn.h"
9 : :
10 : : /**
11 : : * hz is predefined as 100 on AIX. So we undefine it to avoid
12 : : * conflict against hz codec's.
13 : : */
14 : : #ifdef _AIX
15 : : #undef hz
16 : : #endif
17 : :
18 : : /* GBK and GB2312 map differently in few code points that are listed below:
19 : : *
20 : : * gb2312 gbk
21 : : * A1A4 U+30FB KATAKANA MIDDLE DOT U+00B7 MIDDLE DOT
22 : : * A1AA U+2015 HORIZONTAL BAR U+2014 EM DASH
23 : : * A844 undefined U+2015 HORIZONTAL BAR
24 : : */
25 : :
26 : : #define GBK_DECODE(dc1, dc2, writer) \
27 : : if ((dc1) == 0xa1 && (dc2) == 0xaa) { \
28 : : OUTCHAR(0x2014); \
29 : : } \
30 : : else if ((dc1) == 0xa8 && (dc2) == 0x44) { \
31 : : OUTCHAR(0x2015); \
32 : : } \
33 : : else if ((dc1) == 0xa1 && (dc2) == 0xa4) { \
34 : : OUTCHAR(0x00b7); \
35 : : } \
36 : : else if (TRYMAP_DEC(gb2312, decoded, dc1 ^ 0x80, dc2 ^ 0x80)) { \
37 : : OUTCHAR(decoded); \
38 : : } \
39 : : else if (TRYMAP_DEC(gbkext, decoded, dc1, dc2)) { \
40 : : OUTCHAR(decoded); \
41 : : }
42 : :
43 : : #define GBK_ENCODE(code, assi) \
44 : : if ((code) == 0x2014) { \
45 : : (assi) = 0xa1aa; \
46 : : } else if ((code) == 0x2015) { \
47 : : (assi) = 0xa844; \
48 : : } else if ((code) == 0x00b7) { \
49 : : (assi) = 0xa1a4; \
50 : : } else if ((code) != 0x30fb && TRYMAP_ENC(gbcommon, assi, code)) { \
51 : : ; \
52 : : }
53 : :
54 : : /*
55 : : * codecs in this file use the first byte of MultibyteCodec_State.c[8]
56 : : * to store a 0 or 1 state value
57 : : */
58 : : #define CN_STATE_OFFSET 0
59 : :
60 : : /*
61 : : * GB2312 codec
62 : : */
63 : :
64 : 10243 : ENCODER(gb2312)
65 : : {
66 [ + + ]: 45077 : while (*inpos < inlen) {
67 : 34962 : Py_UCS4 c = INCHAR1;
68 : : DBCHAR code;
69 : :
70 [ + + ]: 34962 : if (c < 0x80) {
71 [ + + ]: 3522 : WRITEBYTE1((unsigned char)c);
72 : 3521 : NEXT(1, 1);
73 : 3521 : continue;
74 : : }
75 : :
76 [ - + ]: 31440 : if (c > 0xFFFF)
77 : 0 : return 1;
78 : :
79 [ - + ]: 31440 : REQUIRE_OUTBUF(2);
80 [ + + + - : 31440 : if (TRYMAP_ENC(gbcommon, code, c))
+ + + + ]
81 : : ;
82 : : else
83 : 127 : return 1;
84 : :
85 [ - + ]: 31313 : if (code & 0x8000) /* MSB set: GBK */
86 : 0 : return 1;
87 : :
88 : 31313 : OUTBYTE1((code >> 8) | 0x80);
89 : 31313 : OUTBYTE2((code & 0xFF) | 0x80);
90 : 31313 : NEXT(1, 2);
91 : : }
92 : :
93 : 10115 : return 0;
94 : : }
95 : :
96 : 13237 : DECODER(gb2312)
97 : : {
98 [ + + ]: 53643 : while (inleft > 0) {
99 : 42645 : unsigned char c = **inbuf;
100 : : Py_UCS4 decoded;
101 : :
102 [ + + ]: 42645 : if (c < 0x80) {
103 [ - + ]: 8377 : OUTCHAR(c);
104 : 8377 : NEXT_IN(1);
105 : 8377 : continue;
106 : : }
107 : :
108 [ + + ]: 34268 : REQUIRE_INBUF(2);
109 [ + + + - : 32127 : if (TRYMAP_DEC(gb2312, decoded, c ^ 0x80, INBYTE2 ^ 0x80)) {
+ + + - ]
110 [ - + ]: 32029 : OUTCHAR(decoded);
111 : 32029 : NEXT_IN(2);
112 : : }
113 : : else
114 : 98 : return 1;
115 : : }
116 : :
117 : 10998 : return 0;
118 : : }
119 : :
120 : :
121 : : /*
122 : : * GBK codec
123 : : */
124 : :
125 : 28732 : ENCODER(gbk)
126 : : {
127 [ + + ]: 124072 : while (*inpos < inlen) {
128 : 95469 : Py_UCS4 c = INCHAR1;
129 : : DBCHAR code;
130 : :
131 [ + + ]: 95469 : if (c < 0x80) {
132 [ + + ]: 29480 : WRITEBYTE1((unsigned char)c);
133 : 29479 : NEXT(1, 1);
134 : 29479 : continue;
135 : : }
136 : :
137 [ - + ]: 65989 : if (c > 0xFFFF)
138 : 0 : return 1;
139 : :
140 [ - + ]: 65989 : REQUIRE_OUTBUF(2);
141 : :
142 [ + + + + : 65989 : GBK_ENCODE(c, code)
+ + + + +
+ + - + +
+ + ]
143 : : else
144 : 128 : return 1;
145 : :
146 : 65861 : OUTBYTE1((code >> 8) | 0x80);
147 [ + + ]: 65861 : if (code & 0x8000)
148 : 19862 : OUTBYTE2((code & 0xFF)); /* MSB set: GBK */
149 : : else
150 : 45999 : OUTBYTE2((code & 0xFF) | 0x80); /* MSB unset: GB2312 */
151 : 65861 : NEXT(1, 2);
152 : : }
153 : :
154 : 28603 : return 0;
155 : : }
156 : :
157 : 34731 : DECODER(gbk)
158 : : {
159 [ + + ]: 137602 : while (inleft > 0) {
160 : 107111 : unsigned char c = INBYTE1;
161 : : Py_UCS4 decoded;
162 : :
163 [ + + ]: 107111 : if (c < 0x80) {
164 [ - + ]: 35729 : OUTCHAR(c);
165 : 35729 : NEXT_IN(1);
166 : 35729 : continue;
167 : : }
168 : :
169 [ + + ]: 71382 : REQUIRE_INBUF(2);
170 : :
171 [ + + + + : 67176 : GBK_DECODE(c, INBYTE2, writer)
- + + + +
+ - + + +
+ + - + +
+ + + + +
+ + - + +
+ + + + +
+ - - + ]
172 : : else
173 : 34 : return 1;
174 : :
175 : 67142 : NEXT_IN(2);
176 : : }
177 : :
178 : 30491 : return 0;
179 : : }
180 : :
181 : :
182 : : /*
183 : : * GB18030 codec
184 : : */
185 : :
186 : 38258 : ENCODER(gb18030)
187 : : {
188 [ + + ]: 147271 : while (*inpos < inlen) {
189 : 109259 : Py_UCS4 c = INCHAR1;
190 : : DBCHAR code;
191 : :
192 [ + + ]: 109259 : if (c < 0x80) {
193 [ + + ]: 30398 : WRITEBYTE1(c);
194 : 30387 : NEXT(1, 1);
195 : 30387 : continue;
196 : : }
197 : :
198 [ + + ]: 78861 : if (c >= 0x10000) {
199 : 1 : Py_UCS4 tc = c - 0x10000;
200 : : assert (c <= 0x10FFFF);
201 : :
202 [ - + ]: 1 : REQUIRE_OUTBUF(4);
203 : :
204 : 1 : OUTBYTE4((unsigned char)(tc % 10) + 0x30);
205 : 1 : tc /= 10;
206 : 1 : OUTBYTE3((unsigned char)(tc % 126) + 0x81);
207 : 1 : tc /= 126;
208 : 1 : OUTBYTE2((unsigned char)(tc % 10) + 0x30);
209 : 1 : tc /= 10;
210 : 1 : OUTBYTE1((unsigned char)(tc + 0x90));
211 : :
212 : 1 : NEXT(1, 4);
213 : 1 : continue;
214 : : }
215 : :
216 [ + + ]: 78860 : REQUIRE_OUTBUF(2);
217 : :
218 [ + + + + : 78837 : GBK_ENCODE(c, code)
+ + + + +
+ + + + +
+ + ]
219 [ + + + + : 12982 : else if (TRYMAP_ENC(gb18030ext, code, c))
+ + + + ]
220 : : ;
221 : 10621 : else {
222 : : const struct _gb18030_to_unibmp_ranges *utrrange;
223 : :
224 [ + + ]: 10833 : REQUIRE_OUTBUF(4);
225 : :
226 : 10739 : for (utrrange = gb18030_to_unibmp_ranges;
227 [ + + ]: 1499535 : utrrange->first != 0;
228 : 1488796 : utrrange++)
229 [ + + ]: 1499417 : if (utrrange->first <= c &&
230 [ + + ]: 1495523 : c <= utrrange->last) {
231 : : Py_UCS4 tc;
232 : :
233 : 10621 : tc = c - utrrange->first +
234 : 10621 : utrrange->base;
235 : :
236 : 10621 : OUTBYTE4((unsigned char)(tc % 10) + 0x30);
237 : 10621 : tc /= 10;
238 : 10621 : OUTBYTE3((unsigned char)(tc % 126) + 0x81);
239 : 10621 : tc /= 126;
240 : 10621 : OUTBYTE2((unsigned char)(tc % 10) + 0x30);
241 : 10621 : tc /= 10;
242 : 10621 : OUTBYTE1((unsigned char)tc + 0x81);
243 : :
244 : 10621 : NEXT(1, 4);
245 : 10621 : break;
246 : : }
247 : :
248 [ + + ]: 10739 : if (utrrange->first == 0)
249 : 118 : return 1;
250 : 10621 : continue;
251 : : }
252 : :
253 : 68004 : OUTBYTE1((code >> 8) | 0x80);
254 [ + + ]: 68004 : if (code & 0x8000)
255 : 22005 : OUTBYTE2((code & 0xFF)); /* MSB set: GBK or GB18030ext */
256 : : else
257 : 45999 : OUTBYTE2((code & 0xFF) | 0x80); /* MSB unset: GB2312 */
258 : :
259 : 68004 : NEXT(1, 2);
260 : : }
261 : :
262 : 38012 : return 0;
263 : : }
264 : :
265 : 45538 : DECODER(gb18030)
266 : : {
267 [ + + ]: 161598 : while (inleft > 0) {
268 : 121498 : unsigned char c = INBYTE1, c2;
269 : : Py_UCS4 decoded;
270 : :
271 [ + + ]: 121498 : if (c < 0x80) {
272 [ - + ]: 36053 : OUTCHAR(c);
273 : 36053 : NEXT_IN(1);
274 : 36053 : continue;
275 : : }
276 : :
277 [ + + ]: 85445 : REQUIRE_INBUF(2);
278 : :
279 : 80851 : c2 = INBYTE2;
280 [ + - + + ]: 80851 : if (c2 >= 0x30 && c2 <= 0x39) { /* 4 bytes seq */
281 : : const struct _gb18030_to_unibmp_ranges *utr;
282 : : unsigned char c3, c4;
283 : : Py_UCS4 lseq;
284 : :
285 [ + + ]: 11552 : REQUIRE_INBUF(4);
286 : 10732 : c3 = INBYTE3;
287 : 10732 : c4 = INBYTE4;
288 [ + - + + : 10732 : if (c < 0x81 || c > 0xFE ||
+ + ]
289 [ + + + - ]: 10726 : c3 < 0x81 || c3 > 0xFE ||
290 [ + + ]: 10722 : c4 < 0x30 || c4 > 0x39)
291 : 11 : return 1;
292 : 10721 : c -= 0x81; c2 -= 0x30;
293 : 10721 : c3 -= 0x81; c4 -= 0x30;
294 : :
295 [ + + ]: 10721 : if (c < 4) { /* U+0080 - U+FFFF */
296 : 10720 : lseq = ((Py_UCS4)c * 10 + c2) * 1260 +
297 : 10720 : (Py_UCS4)c3 * 10 + c4;
298 [ + + ]: 10720 : if (lseq < 39420) {
299 : 10719 : for (utr = gb18030_to_unibmp_ranges;
300 [ + + ]: 1492112 : lseq >= (utr + 1)->base;
301 : 1481393 : utr++) ;
302 [ - + ]: 10719 : OUTCHAR(utr->first - utr->base + lseq);
303 : 10719 : NEXT_IN(4);
304 : 10719 : continue;
305 : : }
306 : : }
307 [ - + ]: 1 : else if (c >= 15) { /* U+10000 - U+10FFFF */
308 : 0 : lseq = 0x10000 + (((Py_UCS4)c-15) * 10 + c2)
309 : 0 : * 1260 + (Py_UCS4)c3 * 10 + c4;
310 [ # # ]: 0 : if (lseq <= 0x10FFFF) {
311 [ # # ]: 0 : OUTCHAR(lseq);
312 : 0 : NEXT_IN(4);
313 : 0 : continue;
314 : : }
315 : : }
316 : 2 : return 1;
317 : : }
318 : :
319 [ + + + + : 69299 : GBK_DECODE(c, c2, writer)
- + + + +
+ - + + +
+ + - + +
+ + + + +
+ + - + +
+ + + + +
+ + - + ]
320 [ + + + - : 2172 : else if (TRYMAP_DEC(gb18030ext, decoded, c, c2))
+ - + - ]
321 [ - + ]: 2161 : OUTCHAR(decoded);
322 : : else
323 : 11 : return 1;
324 : :
325 : 69288 : NEXT_IN(2);
326 : : }
327 : :
328 : 40100 : return 0;
329 : : }
330 : :
331 : :
332 : : /*
333 : : * HZ codec
334 : : */
335 : :
336 : 204 : ENCODER_INIT(hz)
337 : : {
338 : 204 : state->c[CN_STATE_OFFSET] = 0;
339 : 204 : return 0;
340 : : }
341 : :
342 : 38 : ENCODER_RESET(hz)
343 : : {
344 [ + + ]: 38 : if (state->c[CN_STATE_OFFSET] != 0) {
345 [ - + ]: 3 : WRITEBYTE2('~', '}');
346 : 3 : state->c[CN_STATE_OFFSET] = 0;
347 : 3 : NEXT_OUT(2);
348 : : }
349 : 38 : return 0;
350 : : }
351 : :
352 : 1210 : ENCODER(hz)
353 : : {
354 [ + + ]: 13327 : while (*inpos < inlen) {
355 : 12245 : Py_UCS4 c = INCHAR1;
356 : : DBCHAR code;
357 : :
358 [ + + ]: 12245 : if (c < 0x80) {
359 [ + + ]: 10582 : if (state->c[CN_STATE_OFFSET]) {
360 [ - + ]: 153 : WRITEBYTE2('~', '}');
361 : 153 : NEXT_OUT(2);
362 : 153 : state->c[CN_STATE_OFFSET] = 0;
363 : : }
364 [ + + ]: 10582 : WRITEBYTE1((unsigned char)c);
365 : 10581 : NEXT(1, 1);
366 [ + + ]: 10581 : if (c == '~') {
367 [ - + ]: 1 : WRITEBYTE1('~');
368 : 1 : NEXT_OUT(1);
369 : : }
370 : 10581 : continue;
371 : : }
372 : :
373 [ - + ]: 1663 : if (c > 0xFFFF)
374 : 0 : return 1;
375 : :
376 [ + + + - : 1663 : if (TRYMAP_ENC(gbcommon, code, c))
+ + + + ]
377 : : ;
378 : : else
379 : 127 : return 1;
380 : :
381 [ - + ]: 1536 : if (code & 0x8000) /* MSB set: GBK */
382 : 0 : return 1;
383 : :
384 [ + + ]: 1536 : if (state->c[CN_STATE_OFFSET] == 0) {
385 [ - + ]: 156 : WRITEBYTE4('~', '{', code >> 8, code & 0xff);
386 : 156 : NEXT(1, 4);
387 : 156 : state->c[CN_STATE_OFFSET] = 1;
388 : : }
389 : : else {
390 [ - + ]: 1380 : WRITEBYTE2(code >> 8, code & 0xff);
391 : 1380 : NEXT(1, 2);
392 : : }
393 : : }
394 : :
395 : 1082 : return 0;
396 : : }
397 : :
398 : 193 : DECODER_INIT(hz)
399 : : {
400 : 193 : state->c[CN_STATE_OFFSET] = 0;
401 : 193 : return 0;
402 : : }
403 : :
404 : 5 : DECODER_RESET(hz)
405 : : {
406 : 5 : state->c[CN_STATE_OFFSET] = 0;
407 : 5 : return 0;
408 : : }
409 : :
410 : 1786 : DECODER(hz)
411 : : {
412 [ + + ]: 19461 : while (inleft > 0) {
413 : 18093 : unsigned char c = INBYTE1;
414 : : Py_UCS4 decoded;
415 : :
416 [ + + ]: 18093 : if (c == '~') {
417 : 364 : unsigned char c2 = INBYTE2;
418 : :
419 [ + + ]: 364 : REQUIRE_INBUF(2);
420 [ + + - + ]: 336 : if (c2 == '~' && state->c[CN_STATE_OFFSET] == 0)
421 [ # # ]: 0 : OUTCHAR('~');
422 [ + + + - ]: 336 : else if (c2 == '{' && state->c[CN_STATE_OFFSET] == 0)
423 : 165 : state->c[CN_STATE_OFFSET] = 1; /* set GB */
424 [ + + + + ]: 171 : else if (c2 == '\n' && state->c[CN_STATE_OFFSET] == 0)
425 : : ; /* line-continuation */
426 [ + + + - ]: 168 : else if (c2 == '}' && state->c[CN_STATE_OFFSET] == 1)
427 : 163 : state->c[CN_STATE_OFFSET] = 0; /* set ASCII */
428 : : else
429 : 5 : return 1;
430 : 331 : NEXT_IN(2);
431 : 331 : continue;
432 : : }
433 : :
434 [ + + ]: 17729 : if (c & 0x80)
435 : 259 : return 1;
436 : :
437 [ + + ]: 17470 : if (state->c[CN_STATE_OFFSET] == 0) { /* ASCII mode */
438 [ - + ]: 15749 : OUTCHAR(c);
439 : 15749 : NEXT_IN(1);
440 : : }
441 : : else { /* GB mode */
442 [ + + ]: 1721 : REQUIRE_INBUF(2);
443 [ + + + - : 1597 : if (TRYMAP_DEC(gb2312, decoded, c, INBYTE2)) {
+ - + - ]
444 [ - + ]: 1595 : OUTCHAR(decoded);
445 : 1595 : NEXT_IN(2);
446 : : }
447 : : else
448 : 2 : return 1;
449 : : }
450 : : }
451 : :
452 : 1368 : return 0;
453 : : }
454 : :
455 : :
456 : : BEGIN_MAPPINGS_LIST
457 : : MAPPING_DECONLY(gb2312)
458 : : MAPPING_DECONLY(gbkext)
459 : : MAPPING_ENCONLY(gbcommon)
460 : : MAPPING_ENCDEC(gb18030ext)
461 : : END_MAPPINGS_LIST
462 : :
463 : : BEGIN_CODECS_LIST
464 : : CODEC_STATELESS(gb2312)
465 : : CODEC_STATELESS(gbk)
466 : : CODEC_STATELESS(gb18030)
467 : : CODEC_STATEFUL(hz)
468 : : END_CODECS_LIST
469 : :
470 : 13 : I_AM_A_MODULE_FOR(cn)
|