1 /* Tests wide character conversion functions.
2 test: wcharnorestart, wcharstringnorestart, wcharrestart, char16restart, char32restart
11 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L
14 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
15 #if defined(__APPLE__) || defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
16 // Work around Apple's missing uchar.h
18 typedef int_least16_t char16_t
;
19 typedef int_least32_t char32_t
;
21 #include <uchar.h> // For char16_t, char32_t
25 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
27 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
29 _Static_assert(!WCHAR_MIN
, "nonzero WCHAR_MIN");
30 _Static_assert(WEOF
<= WINT_MAX
, "WEOF out of wint_t range");
37 #ifdef TEST_wcharnorestart
41 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L && !defined(__SDCC_pdk14) // Not enough memory
42 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
47 ASSERT(mbtowc(&w
, c
, 1) == 1);
48 ASSERT(wctomb(c
, w
) == 1);
50 ASSERT(wctob(btowc('C')) == 'C');
51 ASSERT(btowc(EOF
) == WEOF
);
52 ASSERT(wctob(WEOF
) == EOF
);
54 ASSERT(wctomb(c
, L
'W') == 1);
56 #ifdef __STDC_ISO_10646__
57 ASSERT(wctomb(c
, 0x110000) == -1); // Invalid: Out of 21-bit Unicode range.
58 ASSERT(wctomb(c
, 0xd800) == -1); // Invalid: Unpaired UTF-16 surrogate.
59 ASSERT(wctomb(c
, 0xdfff) == -1); // Invalid: Unpaired UTF-16 surrogate.
66 #ifdef TEST_wcharstringnorestart
68 wcharstringnorestart(void)
70 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L && !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Not enough memory
71 wchar_t wcs1
[5] = L
"Test";
73 char mbs
[5 * MB_LEN_MAX
];
75 // Test basic functionality
76 ASSERT(wcslen (wcs1
) == 4);
77 ASSERT(wcstombs(mbs
, wcs1
, 5 * MB_LEN_MAX
) > 0);
78 ASSERT(mbstowcs(wcs2
, mbs
, 5) > 0);
79 ASSERT(wcs1
[3] == L
't');
80 ASSERT(wcs2
[3] == L
't');
81 ASSERT(!wcscmp(wcs1
, wcs2
));
83 // glibc with _FORTIFY_SOURCE == 2 is not standard-compliant (and fails the tests below)
84 // However, Ubuntu decided to make _FORTIFY_SOURCE = 2 the default for GCC.
85 // Ubuntu 24.04 LTS changed this to _FORTIFY_SOURCE = 3 when optimization is enabled
86 // https://bugs.launchpad.net/ubuntu/+source/gcc-13/+bug/2012440
87 #if !(defined(__GNUC__) && (_FORTIFY_SOURCE == 2 || _FORTIFY_SOURCE == 3))
88 // Test for 0-terminated strings
89 ASSERT(wcstombs(mbs
, wcs1
, 1000) > 0);
90 ASSERT(mbstowcs(wcs2
, mbs
, 1000) > 0);
91 ASSERT(!wcscmp(wcs1
, wcs2
));
94 // Test for unterminated strings
97 ASSERT(wcstombs(mbs
, wcs1
, 2) == 2);
98 ASSERT(!strcmp("Te", mbs
));
99 ASSERT(mbstowcs(wcs2
, mbs
, 2) == 2);
100 ASSERT(!wcscmp(L
"Te", wcs2
));
105 #ifdef TEST_wcharrestart
109 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
110 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
116 ASSERT(mbrtowc(&w
, c
, 1, &ps
) == 1);
117 ASSERT(w
== (L
"C")[0]);
118 ASSERT(wcrtomb(c
, w
, &ps
) == 1);
120 ASSERT(mbrtowc(&w
, c
, 1, &ps
) == mbrlen(c
, 1, &ps
));
121 #ifdef __STDC_ISO_10646__
123 ASSERT(wcrtomb(c
, 0x110000, 0) == -1); // Invalid: Out of 21-bit Unicode range.
124 ASSERT(errno
== EILSEQ
);
125 ASSERT(wcrtomb(c
, 0xd800, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
126 ASSERT(wcrtomb(c
, 0xdfff, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
133 #ifdef TEST_char16restart
137 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
138 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !(defined(__SDCC_mcs51) && defined(__SDCC_MODEL_SMALL))
139 #if !defined(__APPLE__) && !defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
140 #if !defined(__FreeBSD__) || __FreeBSD_version >= 1302000 // Known FreeBSD 13.2 bug #272758.
146 ASSERT(mbrtoc16(c16
, c
, 1, &ps
) == 1);
148 ASSERT(mbrtoc16(c16
+ 1, c
+ 1, 1, &ps
) == 0); // Also puts ps back into the initial conversion state.
149 ASSERT(c16
[0] == (u
"C")[0]);
150 ASSERT(c16rtomb(c
, c16
[0], &ps
) == 1);
153 ASSERT(c16rtomb(0, c16
[0], 0) == 1);
155 #ifdef __STDC_UTF_16__
156 ASSERT(c16rtomb(c
, 0xdc00, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
157 ASSERT(errno
== EILSEQ
);
160 ASSERT(c16rtomb(c
, u
'\0', 0) == 1); // Converting a 0 character resets internal state.
162 #ifdef __SDCC // The standard was defective (fixed in C2X). SDCC always behaves according to the fixed standard.
163 ASSERT(c16rtomb(c
, 0xd800, 0) == 0);
164 ASSERT(c16rtomb(c
, 0xd800, 0) == -1); // Invalid: Unpaired UTF-16 surrogate.
166 ASSERT(errno
== EILSEQ
);
168 ASSERT(c16rtomb(c
, u
'\0', 0) == 1); // Converting a 0 character resets internal state.
178 #ifdef TEST_char32restart
182 #if !defined( __SDCC_pdk14) && !defined( __SDCC_pdk15) // Lack of memory
183 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
184 #if !defined(__APPLE__) && !defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
185 #if !defined(__FreeBSD__) || __FreeBSD_version >= 1302000 // Known FreeBSD 13.2 bug #272758.
191 ASSERT(mbrtoc32(c32
, c
, 1, &ps
) == 1);
193 ASSERT(mbrtoc32(c32
+ 1, c
+ 1, 1, &ps
) == 0); // Also puts ps back into the initial conversion state.
194 ASSERT(c32
[0] == (U
"C")[0]);
195 ASSERT(c32rtomb(c
, c32
[0], &ps
) == 1);