1 /* Test c8rtomb.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <errno.h>
20 #include <limits.h>
21 #include <locale.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <uchar.h>
26 #include <wchar.h>
27 #include <support/check.h>
28 #include <support/support.h>
29
30 static int
test_truncated_code_unit_sequence(void)31 test_truncated_code_unit_sequence (void)
32 {
33 /* Missing trailing code unit for a two code byte unit sequence. */
34 {
35 const char8_t *u8s = (const char8_t*) u8"\xC2";
36 char buf[MB_LEN_MAX] = { 0 };
37 mbstate_t s = { 0 };
38
39 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
40 errno = 0;
41 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
42 TEST_COMPARE (errno, EILSEQ);
43 }
44
45 /* Missing first trailing code unit for a three byte code unit sequence. */
46 {
47 const char8_t *u8s = (const char8_t*) u8"\xE0";
48 char buf[MB_LEN_MAX] = { 0 };
49 mbstate_t s = { 0 };
50
51 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
52 errno = 0;
53 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
54 TEST_COMPARE (errno, EILSEQ);
55 }
56
57 /* Missing second trailing code unit for a three byte code unit sequence. */
58 {
59 const char8_t *u8s = (const char8_t*) u8"\xE0\xA0";
60 char buf[MB_LEN_MAX] = { 0 };
61 mbstate_t s = { 0 };
62
63 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
64 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
65 errno = 0;
66 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) -1);
67 TEST_COMPARE (errno, EILSEQ);
68 }
69
70 /* Missing first trailing code unit for a four byte code unit sequence. */
71 {
72 const char8_t *u8s = (const char8_t*) u8"\xF0";
73 char buf[MB_LEN_MAX] = { 0 };
74 mbstate_t s = { 0 };
75
76 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
77 errno = 0;
78 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
79 TEST_COMPARE (errno, EILSEQ);
80 }
81
82 /* Missing second trailing code unit for a four byte code unit sequence. */
83 {
84 const char8_t *u8s = (const char8_t*) u8"\xF0\x90";
85 char buf[MB_LEN_MAX] = { 0 };
86 mbstate_t s = { 0 };
87
88 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
89 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
90 errno = 0;
91 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) -1);
92 TEST_COMPARE (errno, EILSEQ);
93 }
94
95 /* Missing third trailing code unit for a four byte code unit sequence. */
96 {
97 const char8_t *u8s = (const char8_t*) u8"\xF0\x90\x80";
98 char buf[MB_LEN_MAX] = { 0 };
99 mbstate_t s = { 0 };
100
101 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
102 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
103 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
104 errno = 0;
105 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) -1);
106 TEST_COMPARE (errno, EILSEQ);
107 }
108
109 return 0;
110 }
111
112 static int
test_invalid_trailing_code_unit_sequence(void)113 test_invalid_trailing_code_unit_sequence (void)
114 {
115 /* Invalid trailing code unit for a two code byte unit sequence. */
116 {
117 const char8_t *u8s = (const char8_t*) u8"\xC2\xC0";
118 char buf[MB_LEN_MAX] = { 0 };
119 mbstate_t s = { 0 };
120
121 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
122 errno = 0;
123 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
124 TEST_COMPARE (errno, EILSEQ);
125 }
126
127 /* Invalid first trailing code unit for a three byte code unit sequence. */
128 {
129 const char8_t *u8s = (const char8_t*) u8"\xE0\xC0";
130 char buf[MB_LEN_MAX] = { 0 };
131 mbstate_t s = { 0 };
132
133 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
134 errno = 0;
135 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
136 TEST_COMPARE (errno, EILSEQ);
137 }
138
139 /* Invalid second trailing code unit for a three byte code unit sequence. */
140 {
141 const char8_t *u8s = (const char8_t*) u8"\xE0\xA0\xC0";
142 char buf[MB_LEN_MAX] = { 0 };
143 mbstate_t s = { 0 };
144
145 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
146 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
147 errno = 0;
148 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) -1);
149 TEST_COMPARE (errno, EILSEQ);
150 }
151
152 /* Invalid first trailing code unit for a four byte code unit sequence. */
153 {
154 const char8_t *u8s = (const char8_t*) u8"\xF0\xC0";
155 char buf[MB_LEN_MAX] = { 0 };
156 mbstate_t s = { 0 };
157
158 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
159 errno = 0;
160 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
161 TEST_COMPARE (errno, EILSEQ);
162 }
163
164 /* Invalid second trailing code unit for a four byte code unit sequence. */
165 {
166 const char8_t *u8s = (const char8_t*) u8"\xF0\x90\xC0";
167 char buf[MB_LEN_MAX] = { 0 };
168 mbstate_t s = { 0 };
169
170 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
171 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
172 errno = 0;
173 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) -1);
174 TEST_COMPARE (errno, EILSEQ);
175 }
176
177 /* Invalid third trailing code unit for a four byte code unit sequence. */
178 {
179 const char8_t *u8s = (const char8_t*) u8"\xF0\x90\x80\xC0";
180 char buf[MB_LEN_MAX] = { 0 };
181 mbstate_t s = { 0 };
182
183 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
184 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
185 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
186 errno = 0;
187 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) -1);
188 TEST_COMPARE (errno, EILSEQ);
189 }
190
191 return 0;
192 }
193
194 static int
test_lone_trailing_code_units(void)195 test_lone_trailing_code_units (void)
196 {
197 /* Lone trailing code unit. */
198 const char8_t *u8s = (const char8_t*) u8"\x80";
199 char buf[MB_LEN_MAX] = { 0 };
200 mbstate_t s = { 0 };
201
202 errno = 0;
203 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) -1);
204 TEST_COMPARE (errno, EILSEQ);
205
206 return 0;
207 }
208
209 static int
test_overlong_encoding(void)210 test_overlong_encoding (void)
211 {
212 /* Two byte overlong encoding. */
213 {
214 const char8_t *u8s = (const char8_t*) u8"\xC0\x80";
215 char buf[MB_LEN_MAX] = { 0 };
216 mbstate_t s = { 0 };
217
218 errno = 0;
219 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) -1);
220 TEST_COMPARE (errno, EILSEQ);
221 }
222
223 /* Two byte overlong encoding. */
224 {
225 const char8_t *u8s = (const char8_t*) u8"\xC1\x80";
226 char buf[MB_LEN_MAX] = { 0 };
227 mbstate_t s = { 0 };
228
229 errno = 0;
230 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) -1);
231 TEST_COMPARE (errno, EILSEQ);
232 }
233
234 /* Three byte overlong encoding. */
235 {
236 const char8_t *u8s = (const char8_t*) u8"\xE0\x9F\xBF";
237 char buf[MB_LEN_MAX] = { 0 };
238 mbstate_t s = { 0 };
239
240 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
241 errno = 0;
242 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
243 TEST_COMPARE (errno, EILSEQ);
244 }
245
246 /* Four byte overlong encoding. */
247 {
248 const char8_t *u8s = (const char8_t*) u8"\xF0\x8F\xBF\xBF";
249 char buf[MB_LEN_MAX] = { 0 };
250 mbstate_t s = { 0 };
251
252 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
253 errno = 0;
254 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
255 TEST_COMPARE (errno, EILSEQ);
256 }
257
258 return 0;
259 }
260
261 static int
test_surrogate_range(void)262 test_surrogate_range (void)
263 {
264 /* Would encode U+D800. */
265 {
266 const char8_t *u8s = (const char8_t*) u8"\xED\xA0\x80";
267 char buf[MB_LEN_MAX] = { 0 };
268 mbstate_t s = { 0 };
269
270 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
271 errno = 0;
272 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
273 TEST_COMPARE (errno, EILSEQ);
274 }
275
276 /* Would encode U+DFFF. */
277 {
278 const char8_t *u8s = (const char8_t*) u8"\xED\xBF\xBF";
279 char buf[MB_LEN_MAX] = { 0 };
280 mbstate_t s = { 0 };
281
282 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
283 errno = 0;
284 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
285 TEST_COMPARE (errno, EILSEQ);
286 }
287
288 return 0;
289 }
290
291 static int
test_out_of_range_encoding(void)292 test_out_of_range_encoding (void)
293 {
294 /* Would encode U+00110000. */
295 {
296 const char8_t *u8s = (const char8_t*) u8"\xF4\x90\x80\x80";
297 char buf[MB_LEN_MAX] = { 0 };
298 mbstate_t s = { 0 };
299
300 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
301 errno = 0;
302 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) -1);
303 TEST_COMPARE (errno, EILSEQ);
304 }
305
306 /* Would encode U+00140000. */
307 {
308 const char8_t *u8s = (const char8_t*) u8"\xF5\x90\x80\x80";
309 char buf[MB_LEN_MAX] = { 0 };
310 mbstate_t s = { 0 };
311
312 errno = 0;
313 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) -1);
314 TEST_COMPARE (errno, EILSEQ);
315 }
316
317 return 0;
318 }
319
320 static int
test_null_output_buffer(void)321 test_null_output_buffer (void)
322 {
323 /* Null character with an initial state. */
324 {
325 mbstate_t s = { 0 };
326
327 TEST_COMPARE (c8rtomb (NULL, u8"X"[0], &s), (size_t) 1);
328 /* Assert the state is now an initial state. */
329 TEST_VERIFY (mbsinit (&s));
330 }
331
332 /* Null buffer with a state corresponding to an incompletely read code
333 unit sequence. In this case, an error occurs since insufficient
334 information is available to complete the already started code unit
335 sequence and return to the initial state. */
336 {
337 char buf[MB_LEN_MAX] = { 0 };
338 mbstate_t s = { 0 };
339
340 TEST_COMPARE (c8rtomb (buf, u8"\xC2"[0], &s), (size_t) 0);
341 errno = 0;
342 TEST_COMPARE (c8rtomb (NULL, u8"\x80"[0], &s), (size_t) -1);
343 TEST_COMPARE (errno, EILSEQ);
344 }
345
346 return 0;
347 }
348
349 static int
test_utf8(void)350 test_utf8 (void)
351 {
352 xsetlocale (LC_ALL, "de_DE.UTF-8");
353
354 /* Null character. */
355 {
356 /* U+0000 => 0x00 */
357 const char8_t *u8s = (const char8_t*) u8"\x00";
358 char buf[MB_LEN_MAX] = { 0 };
359 mbstate_t s = { 0 };
360
361 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 1);
362 TEST_COMPARE (buf[0], (char) 0x00);
363 TEST_VERIFY (mbsinit (&s));
364 }
365
366 /* First non-null character in the code point range that maps to a single
367 code unit. */
368 {
369 /* U+0001 => 0x01 */
370 const char8_t *u8s = (const char8_t*) u8"\x01";
371 char buf[MB_LEN_MAX] = { 0 };
372 mbstate_t s = { 0 };
373
374 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 1);
375 TEST_COMPARE (buf[0], (char) 0x01);
376 TEST_VERIFY (mbsinit (&s));
377 }
378
379 /* Last character in the code point range that maps to a single code unit. */
380 {
381 /* U+007F => 0x7F */
382 const char8_t *u8s = (const char8_t*) u8"\x7F";
383 char buf[MB_LEN_MAX] = { 0 };
384 mbstate_t s = { 0 };
385
386 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 1);
387 TEST_COMPARE (buf[0], (char) 0x7F);
388 TEST_VERIFY (mbsinit (&s));
389 }
390
391 /* First character in the code point range that maps to two code units. */
392 {
393 /* U+0080 => 0xC2 0x80 */
394 const char8_t *u8s = (const char8_t*) u8"\xC2\x80";
395 char buf[MB_LEN_MAX] = { 0 };
396 mbstate_t s = { 0 };
397
398 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
399 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 2);
400 TEST_COMPARE (buf[0], (char) 0xC2);
401 TEST_COMPARE (buf[1], (char) 0x80);
402 TEST_VERIFY (mbsinit (&s));
403 }
404
405 /* Last character in the code point range that maps to two code units. */
406 {
407 /* U+07FF => 0xDF 0xBF */
408 const char8_t *u8s = (const char8_t*) u8"\u07FF";
409 char buf[MB_LEN_MAX] = { 0 };
410 mbstate_t s = { 0 };
411
412 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
413 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 2);
414 TEST_COMPARE (buf[0], (char) 0xDF);
415 TEST_COMPARE (buf[1], (char) 0xBF);
416 TEST_VERIFY (mbsinit (&s));
417 }
418
419 /* First character in the code point range that maps to three code units. */
420 {
421 /* U+0800 => 0xE0 0xA0 0x80 */
422 const char8_t *u8s = (const char8_t*) u8"\u0800";
423 char buf[MB_LEN_MAX] = { 0 };
424 mbstate_t s = { 0 };
425
426 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
427 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
428 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
429 TEST_COMPARE (buf[0], (char) 0xE0);
430 TEST_COMPARE (buf[1], (char) 0xA0);
431 TEST_COMPARE (buf[2], (char) 0x80);
432 TEST_VERIFY (mbsinit (&s));
433 }
434
435 /* Last character in the code point range that maps to three code units
436 before the surrogate code point range. */
437 {
438 /* U+D7FF => 0xED 0x9F 0xBF */
439 const char8_t *u8s = (const char8_t*) u8"\uD7FF";
440 char buf[MB_LEN_MAX] = { 0 };
441 mbstate_t s = { 0 };
442
443 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
444 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
445 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
446 TEST_COMPARE (buf[0], (char) 0xED);
447 TEST_COMPARE (buf[1], (char) 0x9F);
448 TEST_COMPARE (buf[2], (char) 0xBF);
449 TEST_VERIFY (mbsinit (&s));
450 }
451
452 /* First character in the code point range that maps to three code units
453 after the surrogate code point range. */
454 {
455 /* U+E000 => 0xEE 0x80 0x80 */
456 const char8_t *u8s = (const char8_t*) u8"\uE000";
457 char buf[MB_LEN_MAX] = { 0 };
458 mbstate_t s = { 0 };
459
460 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
461 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
462 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
463 TEST_COMPARE (buf[0], (char) 0xEE);
464 TEST_COMPARE (buf[1], (char) 0x80);
465 TEST_COMPARE (buf[2], (char) 0x80);
466 TEST_VERIFY (mbsinit (&s));
467 }
468
469 /* Not a BOM. */
470 {
471 /* U+FEFF => 0xEF 0xBB 0xBF */
472 const char8_t *u8s = (const char8_t*) u8"\uFEFF";
473 char buf[MB_LEN_MAX] = { 0 };
474 mbstate_t s = { 0 };
475
476 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
477 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
478 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
479 TEST_COMPARE (buf[0], (char) 0xEF);
480 TEST_COMPARE (buf[1], (char) 0xBB);
481 TEST_COMPARE (buf[2], (char) 0xBF);
482 TEST_VERIFY (mbsinit (&s));
483 }
484
485 /* Replacement character. */
486 {
487 /* U+FFFD => 0xEF 0xBF 0xBD */
488 const char8_t *u8s = (const char8_t*) u8"\uFFFD";
489 char buf[MB_LEN_MAX] = { 0 };
490 mbstate_t s = { 0 };
491
492 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
493 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
494 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
495 TEST_COMPARE (buf[0], (char) 0xEF);
496 TEST_COMPARE (buf[1], (char) 0xBF);
497 TEST_COMPARE (buf[2], (char) 0xBD);
498 TEST_VERIFY (mbsinit (&s));
499 }
500
501 /* Last character in the code point range that maps to three code units. */
502 {
503 /* U+FFFF => 0xEF 0xBF 0xBF */
504 const char8_t *u8s = (const char8_t*) u8"\uFFFF";
505 char buf[MB_LEN_MAX] = { 0 };
506 mbstate_t s = { 0 };
507
508 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
509 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
510 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 3);
511 TEST_COMPARE (buf[0], (char) 0xEF);
512 TEST_COMPARE (buf[1], (char) 0xBF);
513 TEST_COMPARE (buf[2], (char) 0xBF);
514 TEST_VERIFY (mbsinit (&s));
515 }
516
517 /* First character in the code point range that maps to four code units. */
518 {
519 /* U+10000 => 0xF0 0x90 0x80 0x80 */
520 const char8_t *u8s = (const char8_t*) u8"\U00010000";
521 char buf[MB_LEN_MAX] = { 0 };
522 mbstate_t s = { 0 };
523
524 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
525 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
526 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
527 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) 4);
528 TEST_COMPARE (buf[0], (char) 0xF0);
529 TEST_COMPARE (buf[1], (char) 0x90);
530 TEST_COMPARE (buf[2], (char) 0x80);
531 TEST_COMPARE (buf[3], (char) 0x80);
532 TEST_VERIFY (mbsinit (&s));
533 }
534
535 /* Last character in the code point range that maps to four code units. */
536 {
537 /* U+10FFFF => 0xF4 0x8F 0xBF 0xBF */
538 const char8_t *u8s = (const char8_t*) u8"\U0010FFFF";
539 char buf[MB_LEN_MAX] = { 0 };
540 mbstate_t s = { 0 };
541
542 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
543 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
544 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
545 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) 4);
546 TEST_COMPARE (buf[0], (char) 0xF4);
547 TEST_COMPARE (buf[1], (char) 0x8F);
548 TEST_COMPARE (buf[2], (char) 0xBF);
549 TEST_COMPARE (buf[3], (char) 0xBF);
550 TEST_VERIFY (mbsinit (&s));
551 }
552
553 return 0;
554 }
555
556 static int
test_big5_hkscs(void)557 test_big5_hkscs (void)
558 {
559 xsetlocale (LC_ALL, "zh_HK.BIG5-HKSCS");
560
561 /* A pair of two byte UTF-8 code unit sequences that map a Unicode code
562 point and combining character to a single double byte character. */
563 {
564 /* U+00CA U+0304 => 0x88 0x62 */
565 const char8_t *u8s = (const char8_t*) u8"\u00CA\u0304";
566 char buf[MB_LEN_MAX] = { 0 };
567 mbstate_t s = { 0 };
568
569 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
570 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
571 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
572 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) 2);
573 TEST_COMPARE (buf[0], (char) 0x88);
574 TEST_COMPARE (buf[1], (char) 0x62);
575 TEST_VERIFY (mbsinit (&s));
576 }
577
578 /* Another pair of two byte UTF-8 code unit sequences that map a Unicode code
579 point and combining character to a single double byte character. */
580 {
581 /* U+00EA U+030C => 0x88 0xA5 */
582 const char8_t *u8s = (const char8_t*) u8"\u00EA\u030C";
583 char buf[MB_LEN_MAX] = { 0 };
584 mbstate_t s = { 0 };
585
586 TEST_COMPARE (c8rtomb (buf, u8s[0], &s), (size_t) 0);
587 TEST_COMPARE (c8rtomb (buf, u8s[1], &s), (size_t) 0);
588 TEST_COMPARE (c8rtomb (buf, u8s[2], &s), (size_t) 0);
589 TEST_COMPARE (c8rtomb (buf, u8s[3], &s), (size_t) 2);
590 TEST_COMPARE (buf[0], (char) 0x88);
591 TEST_COMPARE (buf[1], (char) 0xA5);
592 TEST_VERIFY (mbsinit (&s));
593 }
594
595 return 0;
596 }
597
598 static int
do_test(void)599 do_test (void)
600 {
601 test_truncated_code_unit_sequence ();
602 test_invalid_trailing_code_unit_sequence ();
603 test_lone_trailing_code_units ();
604 test_overlong_encoding ();
605 test_surrogate_range ();
606 test_out_of_range_encoding ();
607 test_null_output_buffer ();
608 test_utf8 ();
609 test_big5_hkscs ();
610 return 0;
611 }
612
613 #include <support/test-driver.c>
614