9f9c9a3223a609d9c1c626dc648e6073c76da2ac
[gnulib.git] / tests / test-mbsrtowcs.c
1 /* Test of conversion of string to wide string.
2    Copyright (C) 2008 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 #include <config.h>
20
21 #include <wchar.h>
22
23 #include <locale.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #define ASSERT(expr) \
29   do                                                                         \
30     {                                                                        \
31       if (!(expr))                                                           \
32         {                                                                    \
33           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
34           fflush (stderr);                                                   \
35           abort ();                                                          \
36         }                                                                    \
37     }                                                                        \
38   while (0)
39
40 int
41 main (int argc, char *argv[])
42 {
43   mbstate_t state;
44   wchar_t wc;
45   size_t ret;
46
47   /* configure should already have checked that the locale is supported.  */
48   if (setlocale (LC_ALL, "") == NULL)
49     return 1;
50
51   /* Test NUL byte input.  */
52   {
53     const char *src;
54
55     memset (&state, '\0', sizeof (mbstate_t));
56
57     src = "";
58     ret = mbsrtowcs (NULL, &src, 0, &state);
59     ASSERT (ret == 0);
60     ASSERT (mbsinit (&state));
61
62     src = "";
63     ret = mbsrtowcs (NULL, &src, 1, &state);
64     ASSERT (ret == 0);
65     ASSERT (mbsinit (&state));
66
67     wc = (wchar_t) 0xBADFACE;
68     src = "";
69     ret = mbsrtowcs (&wc, &src, 0, &state);
70     ASSERT (ret == 0);
71     ASSERT (wc == (wchar_t) 0xBADFACE);
72     ASSERT (mbsinit (&state));
73
74     wc = (wchar_t) 0xBADFACE;
75     src = "";
76     ret = mbsrtowcs (&wc, &src, 1, &state);
77     ASSERT (ret == 0);
78     ASSERT (wc == 0);
79     ASSERT (mbsinit (&state));
80   }
81
82   if (argc > 1)
83     {
84       int unlimited;
85
86       for (unlimited = 0; unlimited < 2; unlimited++)
87         {
88           #define BUFSIZE 10
89           wchar_t buf[BUFSIZE];
90           const char *src;
91
92           {
93             size_t i;
94             for (i = 0; i < BUFSIZE; i++)
95               buf[i] = (wchar_t) 0xBADFACE;
96           }
97
98           switch (argv[1][0])
99             {
100             case '1':
101               /* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
102               {
103                 char input[] = "B\374\337er"; /* "Büßer" */
104                 memset (&state, '\0', sizeof (mbstate_t));
105
106                 wc = (wchar_t) 0xBADFACE;
107                 ret = mbrtowc (&wc, input, 1, &state);
108                 ASSERT (ret == 1);
109                 ASSERT (wc == 'B');
110                 ASSERT (mbsinit (&state));
111                 input[0] = '\0';
112
113                 wc = (wchar_t) 0xBADFACE;
114                 ret = mbrtowc (&wc, input + 1, 1, &state);
115                 ASSERT (ret == 1);
116                 ASSERT (wctob (wc) == (unsigned char) '\374');
117                 ASSERT (mbsinit (&state));
118                 input[1] = '\0';
119
120                 src = input + 2;
121                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 1, &state);
122                 ASSERT (ret == 3);
123                 ASSERT (src == input + 2);
124                 ASSERT (mbsinit (&state));
125
126                 src = input + 2;
127                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 1, &state);
128                 ASSERT (ret == (unlimited ? 3 : 1));
129                 ASSERT (src == (unlimited ? NULL : input + 3));
130                 ASSERT (wctob (buf[0]) == (unsigned char) '\337');
131                 if (unlimited)
132                   {
133                     ASSERT (buf[1] == 'e');
134                     ASSERT (buf[2] == 'r');
135                     ASSERT (buf[3] == 0);
136                     ASSERT (buf[4] == (wchar_t) 0xBADFACE);
137                   }
138                 else
139                   ASSERT (buf[1] == (wchar_t) 0xBADFACE);
140                 ASSERT (mbsinit (&state));
141               }
142               return 0;
143
144             case '2':
145               /* Locale encoding is UTF-8.  */
146               {
147                 char input[] = "B\303\274\303\237er"; /* "Büßer" */
148                 memset (&state, '\0', sizeof (mbstate_t));
149
150                 wc = (wchar_t) 0xBADFACE;
151                 ret = mbrtowc (&wc, input, 1, &state);
152                 ASSERT (ret == 1);
153                 ASSERT (wc == 'B');
154                 ASSERT (mbsinit (&state));
155                 input[0] = '\0';
156
157                 wc = (wchar_t) 0xBADFACE;
158                 ret = mbrtowc (&wc, input + 1, 1, &state);
159                 ASSERT (ret == (size_t)(-2));
160                 ASSERT (wc == (wchar_t) 0xBADFACE);
161                 ASSERT (!mbsinit (&state));
162                 input[1] = '\0';
163
164                 src = input + 2;
165                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &state);
166                 ASSERT (ret == 4);
167                 ASSERT (src == input + 2);
168                 ASSERT (!mbsinit (&state));
169
170                 src = input + 2;
171                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
172                 ASSERT (ret == (unlimited ? 4 : 2));
173                 ASSERT (src == (unlimited ? NULL : input + 5));
174                 ASSERT (wctob (buf[0]) == EOF);
175                 ASSERT (wctob (buf[1]) == EOF);
176                 if (unlimited)
177                   {
178                     ASSERT (buf[2] == 'e');
179                     ASSERT (buf[3] == 'r');
180                     ASSERT (buf[4] == 0);
181                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
182                   }
183                 else
184                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
185                 ASSERT (mbsinit (&state));
186               }
187               return 0;
188
189             case '3':
190               /* Locale encoding is EUC-JP.  */
191               {
192                 char input[] = "B\217\253\344\217\251\316er"; /* "Büßer" */
193                 memset (&state, '\0', sizeof (mbstate_t));
194
195                 wc = (wchar_t) 0xBADFACE;
196                 ret = mbrtowc (&wc, input, 1, &state);
197                 ASSERT (ret == 1);
198                 ASSERT (wc == 'B');
199                 ASSERT (mbsinit (&state));
200                 input[0] = '\0';
201
202                 wc = (wchar_t) 0xBADFACE;
203                 ret = mbrtowc (&wc, input + 1, 1, &state);
204                 ASSERT (ret == (size_t)(-2));
205                 ASSERT (wc == (wchar_t) 0xBADFACE);
206                 ASSERT (!mbsinit (&state));
207                 input[1] = '\0';
208
209                 src = input + 2;
210                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &state);
211                 ASSERT (ret == 4);
212                 ASSERT (src == input + 2);
213                 ASSERT (!mbsinit (&state));
214
215                 src = input + 2;
216                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
217                 ASSERT (ret == (unlimited ? 4 : 2));
218                 ASSERT (src == (unlimited ? NULL : input + 7));
219                 ASSERT (wctob (buf[0]) == EOF);
220                 ASSERT (wctob (buf[1]) == EOF);
221                 if (unlimited)
222                   {
223                     ASSERT (buf[2] == 'e');
224                     ASSERT (buf[3] == 'r');
225                     ASSERT (buf[4] == 0);
226                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
227                   }
228                 else
229                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
230                 ASSERT (mbsinit (&state));
231               }
232               return 0;
233
234             case '4':
235               /* Locale encoding is GB18030.  */
236               {
237                 char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
238                 memset (&state, '\0', sizeof (mbstate_t));
239
240                 wc = (wchar_t) 0xBADFACE;
241                 ret = mbrtowc (&wc, input, 1, &state);
242                 ASSERT (ret == 1);
243                 ASSERT (wc == 'B');
244                 ASSERT (mbsinit (&state));
245                 input[0] = '\0';
246
247                 wc = (wchar_t) 0xBADFACE;
248                 ret = mbrtowc (&wc, input + 1, 1, &state);
249                 ASSERT (ret == (size_t)(-2));
250                 ASSERT (wc == (wchar_t) 0xBADFACE);
251                 ASSERT (!mbsinit (&state));
252                 input[1] = '\0';
253
254                 src = input + 2;
255                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &state);
256                 ASSERT (ret == 4);
257                 ASSERT (src == input + 2);
258                 ASSERT (!mbsinit (&state));
259
260                 src = input + 2;
261                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
262                 ASSERT (ret == (unlimited ? 4 : 2));
263                 ASSERT (src == (unlimited ? NULL : input + 7));
264                 ASSERT (wctob (buf[0]) == EOF);
265                 ASSERT (wctob (buf[1]) == EOF);
266                 if (unlimited)
267                   {
268                     ASSERT (buf[2] == 'e');
269                     ASSERT (buf[3] == 'r');
270                     ASSERT (buf[4] == 0);
271                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
272                   }
273                 else
274                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
275                 ASSERT (mbsinit (&state));
276               }
277               return 0;
278
279             default:
280               return 1;
281             }
282         }
283
284       return 0;
285     }
286
287   return 1;
288 }