27fd58ce19d3c912a833568b0ca98a27cab48f43
[pspp] / 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[] = "<\306\374\313\334\270\354>"; /* "<日本語>" */
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 == '<');
199                 ASSERT (mbsinit (&state));
200                 input[0] = '\0';
201
202                 wc = (wchar_t) 0xBADFACE;
203                 ret = mbrtowc (&wc, input + 1, 2, &state);
204                 ASSERT (ret == 2);
205                 ASSERT (wctob (wc) == EOF);
206                 ASSERT (mbsinit (&state));
207                 input[1] = '\0';
208                 input[2] = '\0';
209
210                 wc = (wchar_t) 0xBADFACE;
211                 ret = mbrtowc (&wc, input + 3, 1, &state);
212                 ASSERT (ret == (size_t)(-2));
213                 ASSERT (wc == (wchar_t) 0xBADFACE);
214                 ASSERT (!mbsinit (&state));
215                 input[3] = '\0';
216
217                 src = input + 4;
218                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &state);
219                 ASSERT (ret == 3);
220                 ASSERT (src == input + 4);
221                 ASSERT (!mbsinit (&state));
222
223                 src = input + 4;
224                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
225                 ASSERT (ret == (unlimited ? 3 : 2));
226                 ASSERT (src == (unlimited ? NULL : input + 7));
227                 ASSERT (wctob (buf[0]) == EOF);
228                 ASSERT (wctob (buf[1]) == EOF);
229                 if (unlimited)
230                   {
231                     ASSERT (buf[2] == '>');
232                     ASSERT (buf[3] == 0);
233                     ASSERT (buf[4] == (wchar_t) 0xBADFACE);
234                   }
235                 else
236                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
237                 ASSERT (mbsinit (&state));
238               }
239               return 0;
240
241             case '4':
242               /* Locale encoding is GB18030.  */
243               {
244                 char input[] = "B\250\271\201\060\211\070er"; /* "Büßer" */
245                 memset (&state, '\0', sizeof (mbstate_t));
246
247                 wc = (wchar_t) 0xBADFACE;
248                 ret = mbrtowc (&wc, input, 1, &state);
249                 ASSERT (ret == 1);
250                 ASSERT (wc == 'B');
251                 ASSERT (mbsinit (&state));
252                 input[0] = '\0';
253
254                 wc = (wchar_t) 0xBADFACE;
255                 ret = mbrtowc (&wc, input + 1, 1, &state);
256                 ASSERT (ret == (size_t)(-2));
257                 ASSERT (wc == (wchar_t) 0xBADFACE);
258                 ASSERT (!mbsinit (&state));
259                 input[1] = '\0';
260
261                 src = input + 2;
262                 ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &state);
263                 ASSERT (ret == 4);
264                 ASSERT (src == input + 2);
265                 ASSERT (!mbsinit (&state));
266
267                 src = input + 2;
268                 ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
269                 ASSERT (ret == (unlimited ? 4 : 2));
270                 ASSERT (src == (unlimited ? NULL : input + 7));
271                 ASSERT (wctob (buf[0]) == EOF);
272                 ASSERT (wctob (buf[1]) == EOF);
273                 if (unlimited)
274                   {
275                     ASSERT (buf[2] == 'e');
276                     ASSERT (buf[3] == 'r');
277                     ASSERT (buf[4] == 0);
278                     ASSERT (buf[5] == (wchar_t) 0xBADFACE);
279                   }
280                 else
281                   ASSERT (buf[2] == (wchar_t) 0xBADFACE);
282                 ASSERT (mbsinit (&state));
283               }
284               return 0;
285
286             default:
287               return 1;
288             }
289         }
290
291       return 0;
292     }
293
294   return 1;
295 }