2006-03-05 Roland McGrath <roland@frob.com>
[glibc/history.git] / libio / tst-widetext.c
blob48444380d8788e6324fe486fddee282d10e1ddfe
1 /* Test program for the wide character stream functions handling larger
2 amounts of text.
3 Copyright (C) 2000, 2002 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
22 #include <assert.h>
23 #include <iconv.h>
24 #include <locale.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <wchar.h>
31 /* Approximate size of the file (must be larger). */
32 #define SIZE 210000
35 int
36 main (void)
38 char name[] = "/tmp/widetext.out.XXXXXX";
39 char mbbuf[SIZE];
40 char mb2buf[SIZE];
41 wchar_t wcbuf[SIZE];
42 wchar_t wc2buf[SIZE];
43 size_t mbsize;
44 size_t wcsize;
45 int fd;
46 FILE *fp;
47 size_t n;
48 int res;
49 int status = 0;
50 wchar_t *wcp;
52 setlocale (LC_ALL, "de_DE.UTF-8");
53 printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
55 /* Read the file into memory. */
56 mbsize = fread (mbbuf, 1, SIZE, stdin);
57 if (mbsize == 0)
59 printf ("%u: cannot read input file from standard input: %m\n",
60 __LINE__);
61 exit (1);
64 printf ("INFO: input file has %Zd bytes\n", mbsize);
66 /* First convert the text to wide characters. We use iconv here. */
68 iconv_t cd;
69 char *inbuf = mbbuf;
70 size_t inleft = mbsize;
71 char *outbuf = (char *) wcbuf;
72 size_t outleft = sizeof (wcbuf);
73 size_t nonr;
75 cd = iconv_open ("WCHAR_T", "UTF-8");
76 if (cd == (iconv_t) -1)
78 printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
79 __LINE__);
80 exit (1);
83 /* We must need only one call and there must be no losses. */
84 nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
85 if (nonr != 0 && nonr != (size_t) -1)
87 printf ("%u: iconv performed %Zd nonreversible conversions\n",
88 __LINE__, nonr);
89 exit (1);
92 if (nonr == (size_t) -1)
94 printf ("\
95 %u: iconv returned with %Zd and errno = %m (inleft: %Zd, outleft: %Zd)\n",
96 __LINE__, nonr, inleft, outleft);
97 exit (1);
100 if (inleft != 0)
102 printf ("%u: iconv didn't convert all input\n", __LINE__);
103 exit (1);
106 iconv_close (cd);
108 if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
110 printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
111 exit (1);
114 wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
115 assert (wcsize + 1 <= SIZE);
118 /* Now that we finished the preparations, run the first test. We
119 are writing the wide char data out and read it back in. We write
120 and read single characters. */
122 fd = mkstemp (name);
123 if (fd == -1)
125 printf ("%u: cannot open temporary file: %m\n", __LINE__);
126 exit (1);
129 unlink (name);
131 fp = fdopen (dup (fd), "w");
132 if (fp == NULL)
134 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
135 exit (1);
138 for (n = 0; n < wcsize; ++n)
140 if (fputwc (wcbuf[n], fp) == WEOF)
142 printf ("%u: fputwc failed: %m\n", __LINE__);
143 exit (1);
147 res = fclose (fp);
148 if (res != 0)
150 printf ("%u: fclose after single-character writing failed (%d): %m\n",
151 __LINE__, res);
152 exit (1);
155 lseek (fd, SEEK_SET, 0);
156 fp = fdopen (dup (fd), "r");
157 if (fp == NULL)
159 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
160 exit (1);
163 for (n = 0; n < wcsize; ++n)
165 wint_t wch = fgetwc (fp);
166 if (wch == WEOF)
168 printf ("%u: fgetwc failed (idx %Zd): %m\n", __LINE__, n);
169 exit (1);
171 wc2buf[n] = wch;
174 /* There should be nothing else. */
175 if (fgetwc (fp) != WEOF)
177 printf ("%u: too many characters available with fgetwc\n", __LINE__);
178 status = 1;
180 else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
182 printf ("%u: buffer read with fgetwc differs\n", __LINE__);
183 status = 1;
186 res = fclose (fp);
187 if (res != 0)
189 printf ("%u: fclose after single-character reading failed (%d): %m\n",
190 __LINE__, res);
191 exit (1);
194 /* Just make sure there are no two errors which hide each other, read the
195 file using the `char' functions. */
197 lseek (fd, SEEK_SET, 0);
198 fp = fdopen (fd, "r");
199 if (fp == NULL)
201 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
202 exit (1);
205 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
207 printf ("%u: cannot read all of the temp file\n", __LINE__);
208 status = 1;
210 else
212 /* Make sure there is nothing left. */
213 if (fgetc (fp) != EOF)
215 printf ("%u: more input available\n", __LINE__);
216 status = 1;
219 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
221 printf ("%u: buffer written with fputwc differs\n", __LINE__);
222 status = 1;
226 res = fclose (fp);
227 if (res != 0)
229 printf ("%u: fclose after single-character reading failed (%d): %m\n",
230 __LINE__, res);
231 exit (1);
234 /* Now to reading and writing line-wise. */
236 fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
237 if (fd == -1)
239 printf ("%u: cannot open temporary file: %m\n", __LINE__);
240 exit (1);
243 unlink (name);
245 fp = fdopen (dup (fd), "w");
246 if (fp == NULL)
248 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
249 exit (1);
252 for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
254 wchar_t *wendp = wcschr (wcp, L'\n');
256 if (wendp != NULL)
258 /* Temporarily NUL terminate the line. */
259 wchar_t save = wendp[1];
260 wendp[1] = L'\0';
262 fputws (wcp, fp);
264 wendp[1] = save;
265 wcp = &wendp[1];
267 else
269 fputws (wcp, fp);
270 wcp = wcschr (wcp, L'\0');
271 assert (wcp == &wcbuf[wcsize]);
275 res = fclose (fp);
276 if (res != 0)
278 printf ("%u: fclose after line-wise writing failed (%d): %m\n",
279 __LINE__, res);
280 exit (1);
283 lseek (fd, SEEK_SET, 0);
284 fp = fdopen (dup (fd), "r");
285 if (fp == NULL)
287 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
288 exit (1);
291 for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
293 if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
295 printf ("%u: short read using fgetws (only %Zd of %Zd)\n",
296 __LINE__, wcp - wc2buf, wcsize);
297 status = 1;
298 break;
300 wcp = wcschr (wcp, L'\0');
303 if (wcp > &wc2buf[wcsize])
305 printf ("%u: fgetws read too much\n", __LINE__);
306 status = 1;
308 else if (fgetwc (fp) != WEOF)
310 /* There should be nothing else. */
311 printf ("%u: too many characters available with fgetws\n", __LINE__);
312 status = 1;
315 if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
317 printf ("%u: buffer read with fgetws differs\n", __LINE__);
318 status = 1;
321 res = fclose (fp);
322 if (res != 0)
324 printf ("%u: fclose after single-character reading failed (%d): %m\n",
325 __LINE__, res);
326 exit (1);
329 /* Just make sure there are no two errors which hide each other, read the
330 file using the `char' functions. */
332 lseek (fd, SEEK_SET, 0);
333 fp = fdopen (fd, "r");
334 if (fp == NULL)
336 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
337 exit (1);
340 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
342 printf ("%u: cannot read all of the temp file\n", __LINE__);
343 status = 1;
345 else
347 /* Make sure there is nothing left. */
348 if (fgetc (fp) != EOF)
350 printf ("%u: more input available\n", __LINE__);
351 status = 1;
354 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
356 printf ("%u: buffer written with fputws differs\n", __LINE__);
357 status = 1;
361 res = fclose (fp);
362 if (res != 0)
364 printf ("%u: fclose after single-character reading failed (%d): %m\n",
365 __LINE__, res);
366 exit (1);
369 return status;