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
30int
31main(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