xref: /haiku/src/tests/system/libroot/posix/gnulib-test-mbsnrtowcs.c (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /* Test of conversion of string to wide string.
2  Copyright (C) 2008-2011 Free Software Foundation, Inc.
3 
4  This program is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 3 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16 
17 /* Written by Bruno Haible <bruno@clisp.org>, 2008.  */
18 
19 #undef NDEBUG
20 #include <assert.h>
21 #include <locale.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <wchar.h>
25 
26 
27 #define BUFSIZE 10
28 
29 
30 int
31 main(int argc, char *argv[])
32 {
33 	mbstate_t state;
34 	wchar_t wc;
35 	size_t ret;
36 	int mode;
37 
38 	/* configure should already have checked that the locale is supported.  */
39 	if (setlocale(LC_ALL, "") == NULL) {
40 		fprintf(stderr, "unable to set standard locale\n");
41 		return 1;
42 	}
43 
44 	/* Test NUL byte input.  */
45 	{
46 		const char *src;
47 
48 		memset(&state, '\0', sizeof(mbstate_t));
49 
50 		src = "";
51 		ret = mbsnrtowcs(NULL, &src, 1, 0, &state);
52 		assert(ret == 0);
53 		assert(mbsinit (&state));
54 
55 		src = "";
56 		ret = mbsnrtowcs(NULL, &src, 1, 1, &state);
57 		assert(ret == 0);
58 		assert(mbsinit (&state));
59 
60 		wc = (wchar_t) 0xBADFACE;
61 		src = "";
62 		ret = mbsnrtowcs(&wc, &src, 1, 0, &state);
63 		assert(ret == 0);
64 		assert(wc == (wchar_t) 0xBADFACE);
65 		assert(mbsinit (&state));
66 
67 		wc = (wchar_t) 0xBADFACE;
68 		src = "";
69 		ret = mbsnrtowcs(&wc, &src, 1, 1, &state);
70 		assert(ret == 0);
71 		assert(wc == 0);
72 		assert(mbsinit (&state));
73 	}
74 
75 	for (mode = '1'; mode <= '4'; ++mode) {
76 		int unlimited;
77 		for (unlimited = 0; unlimited < 2; unlimited++) {
78 			wchar_t buf[BUFSIZE];
79 			const char *src;
80 			mbstate_t temp_state;
81 
82 			{
83 				size_t i;
84 				for (i = 0; i < BUFSIZE; i++)
85 					buf[i] = (wchar_t) 0xBADFACE;
86 			}
87 
88 			switch (mode) {
89 				case '1':
90 					/* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
91 		    	printf("ISO8859-1 ...\n");
92 				{
93 					char input[] = "B\374\337er"; /* "Büßer" */
94 					memset(&state, '\0', sizeof(mbstate_t));
95 
96 					if (setlocale (LC_ALL, "en_US.ISO8859-1") == NULL) {
97 						fprintf(stderr,
98 							"unable to set ISO8859-1 locale, skipping\n");
99 						break;
100 					}
101 
102 					wc = (wchar_t) 0xBADFACE;
103 					ret = mbrtowc(&wc, input, 1, &state);
104 					assert(ret == 1);
105 					assert(wc == 'B');
106 					assert(mbsinit (&state));
107 					input[0] = '\0';
108 
109 					wc = (wchar_t) 0xBADFACE;
110 					ret = mbrtowc(&wc, input + 1, 1, &state);
111 					assert(ret == 1);
112 					assert(wctob (wc) == (unsigned char) '\374');
113 					assert(mbsinit (&state));
114 					input[1] = '\0';
115 
116 					src = input + 2;
117 					temp_state = state;
118 					ret = mbsnrtowcs(NULL, &src, 4, unlimited ? BUFSIZE : 1,
119 						&temp_state);
120 					assert(ret == 3);
121 					assert(src == input + 2);
122 					assert(mbsinit (&state));
123 
124 					src = input + 2;
125 					ret = mbsnrtowcs(buf, &src, 4, unlimited ? BUFSIZE : 1,
126 						&state);
127 					assert(ret == (unlimited ? 3 : 1));
128 					assert(src == (unlimited ? NULL : input + 3));
129 					assert(wctob (buf[0]) == (unsigned char) '\337');
130 					if (unlimited) {
131 						assert(buf[1] == 'e');
132 						assert(buf[2] == 'r');
133 						assert(buf[3] == 0);
134 						assert(buf[4] == (wchar_t) 0xBADFACE);
135 					} else
136 						assert(buf[1] == (wchar_t) 0xBADFACE);
137 					assert(mbsinit (&state));
138 				}
139 					break;
140 
141 				case '2':
142 					/* Locale encoding is UTF-8.  */
143 		    	printf("UTF-8 ...\n");
144 				{
145 					char input[] = "B\303\274\303\237er"; /* "Büßer" */
146 					memset(&state, '\0', sizeof(mbstate_t));
147 
148 					if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) {
149 						fprintf(stderr,
150 							"unable to set UTF-8 locale, skipping\n");
151 						break;
152 					}
153 
154 					wc = (wchar_t) 0xBADFACE;
155 					ret = mbrtowc(&wc, input, 1, &state);
156 					assert(ret == 1);
157 					assert(wc == 'B');
158 					assert(mbsinit (&state));
159 					input[0] = '\0';
160 
161 					wc = (wchar_t) 0xBADFACE;
162 					ret = mbrtowc(&wc, input + 1, 1, &state);
163 					assert(ret == (size_t)(-2));
164 					assert(wc == (wchar_t) 0xBADFACE);
165 					assert(!mbsinit (&state));
166 					input[1] = '\0';
167 
168 // Copying mbstate_t doesn't really copy the ICU-converter's state, so this
169 // doesn't work on Haiku.
170 #ifndef __HAIKU__
171 					src = input + 2;
172 					temp_state = state;
173 					ret = mbsnrtowcs(NULL, &src, 6, unlimited ? BUFSIZE : 2,
174 						&temp_state);
175 					assert(ret == 4);
176 					assert(src == input + 2);
177 					assert(!mbsinit (&state));
178 #endif
179 
180 					src = input + 2;
181 					ret = mbsnrtowcs(buf, &src, 6, unlimited ? BUFSIZE : 2,
182 						&state);
183 					assert(ret == (unlimited ? 4 : 2));
184 					assert(src == (unlimited ? NULL : input + 5));
185 					assert(wctob (buf[0]) == EOF);
186 					assert(wctob (buf[1]) == EOF);
187 					if (unlimited) {
188 						assert(buf[2] == 'e');
189 						assert(buf[3] == 'r');
190 						assert(buf[4] == 0);
191 						assert(buf[5] == (wchar_t) 0xBADFACE);
192 					} else
193 						assert(buf[2] == (wchar_t) 0xBADFACE);
194 					assert(mbsinit (&state));
195 				}
196 					break;
197 
198 				case '3':
199 					/* Locale encoding is EUC-JP.  */
200 		    	printf("EUC-JP ...\n");
201 				{
202 					char input[] = "<\306\374\313\334\270\354>"; /* "<日本語>" */
203 					memset(&state, '\0', sizeof(mbstate_t));
204 
205 					if (setlocale (LC_ALL, "en_US.EUC-JP") == NULL) {
206 						fprintf(stderr,
207 							"unable to set EUC-JP locale, skipping\n");
208 						break;
209 					}
210 
211 					wc = (wchar_t) 0xBADFACE;
212 					ret = mbrtowc(&wc, input, 1, &state);
213 					assert(ret == 1);
214 					assert(wc == '<');
215 					assert(mbsinit (&state));
216 					input[0] = '\0';
217 
218 					wc = (wchar_t) 0xBADFACE;
219 					ret = mbrtowc(&wc, input + 1, 2, &state);
220 					assert(ret == 2);
221 					assert(wctob (wc) == EOF);
222 					assert(mbsinit (&state));
223 					input[1] = '\0';
224 					input[2] = '\0';
225 
226 					wc = (wchar_t) 0xBADFACE;
227 					ret = mbrtowc(&wc, input + 3, 1, &state);
228 					assert(ret == (size_t)(-2));
229 					assert(wc == (wchar_t) 0xBADFACE);
230 					assert(!mbsinit (&state));
231 					input[3] = '\0';
232 
233 // Copying mbstate_t doesn't really copy the ICU-converter's state, so this
234 // doesn't work on Haiku.
235 #ifndef __HAIKU__
236 					src = input + 4;
237 					temp_state = state;
238 					ret = mbsnrtowcs(NULL, &src, 5, unlimited ? BUFSIZE : 2,
239 						&temp_state);
240 					assert(ret == 3);
241 					assert(src == input + 4);
242 					assert(!mbsinit (&state));
243 #endif
244 
245 					src = input + 4;
246 					ret = mbsnrtowcs(buf, &src, 5, unlimited ? BUFSIZE : 2,
247 						&state);
248 					assert(ret == (unlimited ? 3 : 2));
249 					assert(src == (unlimited ? NULL : input + 7));
250 					assert(wctob (buf[0]) == EOF);
251 					assert(wctob (buf[1]) == EOF);
252 					if (unlimited) {
253 						assert(buf[2] == '>');
254 						assert(buf[3] == 0);
255 						assert(buf[4] == (wchar_t) 0xBADFACE);
256 					} else
257 						assert(buf[2] == (wchar_t) 0xBADFACE);
258 					assert(mbsinit (&state));
259 				}
260 					break;
261 
262 				case '4':
263 					/* Locale encoding is GB18030.  */
264 		    	printf("GB18030 ...\n");
265 				{
266 					char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
267 					memset(&state, '\0', sizeof(mbstate_t));
268 
269 					if (setlocale (LC_ALL, "en_US.GB18030") == NULL) {
270 						fprintf(stderr,
271 							"unable to set GB18030 locale, skipping\n");
272 						break;
273 					}
274 
275 					wc = (wchar_t) 0xBADFACE;
276 					ret = mbrtowc(&wc, input, 1, &state);
277 					assert(ret == 1);
278 					assert(wc == 'B');
279 					assert(mbsinit (&state));
280 					input[0] = '\0';
281 
282 					wc = (wchar_t) 0xBADFACE;
283 					ret = mbrtowc(&wc, input + 1, 1, &state);
284 					assert(ret == (size_t)(-2));
285 					assert(wc == (wchar_t) 0xBADFACE);
286 					assert(!mbsinit (&state));
287 					input[1] = '\0';
288 
289 // Copying mbstate_t doesn't really copy the ICU-converter's state, so this
290 // doesn't work on Haiku.
291 #ifndef __HAIKU__
292 					src = input + 2;
293 					temp_state = state;
294 					ret = mbsnrtowcs(NULL, &src, 8, unlimited ? BUFSIZE : 2,
295 						&temp_state);
296 					assert(ret == 4);
297 					assert(src == input + 2);
298 					assert(!mbsinit (&state));
299 #endif
300 
301 					src = input + 2;
302 					ret = mbsnrtowcs(buf, &src, 8, unlimited ? BUFSIZE : 2,
303 						&state);
304 					assert(ret == (unlimited ? 4 : 2));
305 					assert(src == (unlimited ? NULL : input + 7));
306 					assert(wctob (buf[0]) == EOF);
307 					assert(wctob (buf[1]) == EOF);
308 					if (unlimited) {
309 						assert(buf[2] == 'e');
310 						assert(buf[3] == 'r');
311 						assert(buf[4] == 0);
312 						assert(buf[5] == (wchar_t) 0xBADFACE);
313 					} else
314 						assert(buf[2] == (wchar_t) 0xBADFACE);
315 					assert(mbsinit (&state));
316 				}
317 					break;
318 
319 				default:
320 					return 1;
321 			}
322 		}
323 	}
324 
325 	return 0;
326 }
327