UnicodeData has precedence over EastAsianWidth
[glibc.git] / libio / tst-widetext.c
blob6d5fa33e77a3f5f9ac9950cbc9c4c98a4e7f6936
1 /* Test program for the wide character stream functions handling larger
2 amounts of text.
3 Copyright (C) 2000-2017 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, see
19 <http://www.gnu.org/licenses/>. */
21 #include <assert.h>
22 #include <iconv.h>
23 #include <locale.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <wchar.h>
30 /* Approximate size of the file (must be larger). */
31 #define SIZE 210000
34 static int
35 do_test (void)
37 char name[] = "/tmp/widetext.out.XXXXXX";
38 char mbbuf[SIZE];
39 char mb2buf[SIZE];
40 wchar_t wcbuf[SIZE];
41 wchar_t wc2buf[SIZE];
42 size_t mbsize;
43 size_t wcsize;
44 int fd;
45 FILE *fp;
46 size_t n;
47 int res;
48 int status = 0;
49 wchar_t *wcp;
51 setlocale (LC_ALL, "de_DE.UTF-8");
52 printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
54 /* Read the file into memory. */
55 mbsize = fread (mbbuf, 1, SIZE, stdin);
56 if (mbsize == 0)
58 printf ("%u: cannot read input file from standard input: %m\n",
59 __LINE__);
60 exit (1);
63 printf ("INFO: input file has %Zd bytes\n", mbsize);
65 /* First convert the text to wide characters. We use iconv here. */
67 iconv_t cd;
68 char *inbuf = mbbuf;
69 size_t inleft = mbsize;
70 char *outbuf = (char *) wcbuf;
71 size_t outleft = sizeof (wcbuf);
72 size_t nonr;
74 cd = iconv_open ("WCHAR_T", "UTF-8");
75 if (cd == (iconv_t) -1)
77 printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
78 __LINE__);
79 exit (1);
82 /* We must need only one call and there must be no losses. */
83 nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
84 if (nonr != 0 && nonr != (size_t) -1)
86 printf ("%u: iconv performed %Zd nonreversible conversions\n",
87 __LINE__, nonr);
88 exit (1);
91 if (nonr == (size_t) -1)
93 printf ("\
94 %u: iconv returned with %Zd and errno = %m (inleft: %Zd, outleft: %Zd)\n",
95 __LINE__, nonr, inleft, outleft);
96 exit (1);
99 if (inleft != 0)
101 printf ("%u: iconv didn't convert all input\n", __LINE__);
102 exit (1);
105 iconv_close (cd);
107 if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
109 printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
110 exit (1);
113 wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
114 assert (wcsize + 1 <= SIZE);
117 /* Now that we finished the preparations, run the first test. We
118 are writing the wide char data out and read it back in. We write
119 and read single characters. */
121 fd = mkstemp (name);
122 if (fd == -1)
124 printf ("%u: cannot open temporary file: %m\n", __LINE__);
125 exit (1);
128 unlink (name);
130 fp = fdopen (dup (fd), "w");
131 if (fp == NULL)
133 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
134 exit (1);
137 for (n = 0; n < wcsize; ++n)
139 if (fputwc (wcbuf[n], fp) == WEOF)
141 printf ("%u: fputwc failed: %m\n", __LINE__);
142 exit (1);
146 res = fclose (fp);
147 if (res != 0)
149 printf ("%u: fclose after single-character writing failed (%d): %m\n",
150 __LINE__, res);
151 exit (1);
154 lseek (fd, SEEK_SET, 0);
155 fp = fdopen (dup (fd), "r");
156 if (fp == NULL)
158 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
159 exit (1);
162 for (n = 0; n < wcsize; ++n)
164 wint_t wch = fgetwc (fp);
165 if (wch == WEOF)
167 printf ("%u: fgetwc failed (idx %Zd): %m\n", __LINE__, n);
168 exit (1);
170 wc2buf[n] = wch;
173 /* There should be nothing else. */
174 if (fgetwc (fp) != WEOF)
176 printf ("%u: too many characters available with fgetwc\n", __LINE__);
177 status = 1;
179 else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
181 printf ("%u: buffer read with fgetwc differs\n", __LINE__);
182 status = 1;
185 res = fclose (fp);
186 if (res != 0)
188 printf ("%u: fclose after single-character reading failed (%d): %m\n",
189 __LINE__, res);
190 exit (1);
193 /* Just make sure there are no two errors which hide each other, read the
194 file using the `char' functions. */
196 lseek (fd, SEEK_SET, 0);
197 fp = fdopen (fd, "r");
198 if (fp == NULL)
200 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
201 exit (1);
204 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
206 printf ("%u: cannot read all of the temp file\n", __LINE__);
207 status = 1;
209 else
211 /* Make sure there is nothing left. */
212 if (fgetc (fp) != EOF)
214 printf ("%u: more input available\n", __LINE__);
215 status = 1;
218 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
220 printf ("%u: buffer written with fputwc differs\n", __LINE__);
221 status = 1;
225 res = fclose (fp);
226 if (res != 0)
228 printf ("%u: fclose after single-character reading failed (%d): %m\n",
229 __LINE__, res);
230 exit (1);
233 /* Now to reading and writing line-wise. */
235 fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
236 if (fd == -1)
238 printf ("%u: cannot open temporary file: %m\n", __LINE__);
239 exit (1);
242 unlink (name);
244 fp = fdopen (dup (fd), "w");
245 if (fp == NULL)
247 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
248 exit (1);
251 for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
253 wchar_t *wendp = wcschr (wcp, L'\n');
255 if (wendp != NULL)
257 /* Temporarily NUL terminate the line. */
258 wchar_t save = wendp[1];
259 wendp[1] = L'\0';
261 fputws (wcp, fp);
263 wendp[1] = save;
264 wcp = &wendp[1];
266 else
268 fputws (wcp, fp);
269 wcp = wcschr (wcp, L'\0');
270 assert (wcp == &wcbuf[wcsize]);
274 res = fclose (fp);
275 if (res != 0)
277 printf ("%u: fclose after line-wise writing failed (%d): %m\n",
278 __LINE__, res);
279 exit (1);
282 lseek (fd, SEEK_SET, 0);
283 fp = fdopen (dup (fd), "r");
284 if (fp == NULL)
286 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
287 exit (1);
290 for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
292 if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
294 printf ("%u: short read using fgetws (only %td of %Zd)\n",
295 __LINE__, wcp - wc2buf, wcsize);
296 status = 1;
297 break;
299 wcp = wcschr (wcp, L'\0');
302 if (wcp > &wc2buf[wcsize])
304 printf ("%u: fgetws read too much\n", __LINE__);
305 status = 1;
307 else if (fgetwc (fp) != WEOF)
309 /* There should be nothing else. */
310 printf ("%u: too many characters available with fgetws\n", __LINE__);
311 status = 1;
314 if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
316 printf ("%u: buffer read with fgetws differs\n", __LINE__);
317 status = 1;
320 res = fclose (fp);
321 if (res != 0)
323 printf ("%u: fclose after single-character reading failed (%d): %m\n",
324 __LINE__, res);
325 exit (1);
328 /* Just make sure there are no two errors which hide each other, read the
329 file using the `char' functions. */
331 lseek (fd, SEEK_SET, 0);
332 fp = fdopen (fd, "r");
333 if (fp == NULL)
335 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
336 exit (1);
339 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
341 printf ("%u: cannot read all of the temp file\n", __LINE__);
342 status = 1;
344 else
346 /* Make sure there is nothing left. */
347 if (fgetc (fp) != EOF)
349 printf ("%u: more input available\n", __LINE__);
350 status = 1;
353 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
355 printf ("%u: buffer written with fputws differs\n", __LINE__);
356 status = 1;
360 res = fclose (fp);
361 if (res != 0)
363 printf ("%u: fclose after single-character reading failed (%d): %m\n",
364 __LINE__, res);
365 exit (1);
368 return status;
371 #define TEST_FUNCTION do_test ()
372 #include "../test-skeleton.c"