Back to index

glibc  2.9
tst-widetext.c
Go to the documentation of this file.
00001 /* Test program for the wide character stream functions handling larger
00002    amounts of text.
00003    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@cygnus.com>.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include <assert.h>
00023 #include <iconv.h>
00024 #include <locale.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <wchar.h>
00030 
00031 /* Approximate size of the file (must be larger).  */
00032 #define SIZE 210000
00033 
00034 
00035 int
00036 main (void)
00037 {
00038   char name[] = "/tmp/widetext.out.XXXXXX";
00039   char mbbuf[SIZE];
00040   char mb2buf[SIZE];
00041   wchar_t wcbuf[SIZE];
00042   wchar_t wc2buf[SIZE];
00043   size_t mbsize;
00044   size_t wcsize;
00045   int fd;
00046   FILE *fp;
00047   size_t n;
00048   int res;
00049   int status = 0;
00050   wchar_t *wcp;
00051 
00052   setlocale (LC_ALL, "de_DE.UTF-8");
00053   printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
00054 
00055   /* Read the file into memory.  */
00056   mbsize = fread (mbbuf, 1, SIZE, stdin);
00057   if (mbsize == 0)
00058     {
00059       printf ("%u: cannot read input file from standard input: %m\n",
00060              __LINE__);
00061       exit (1);
00062     }
00063 
00064    printf ("INFO: input file has %Zd bytes\n", mbsize);
00065 
00066   /* First convert the text to wide characters.  We use iconv here.  */
00067   {
00068     iconv_t cd;
00069     char *inbuf = mbbuf;
00070     size_t inleft = mbsize;
00071     char *outbuf = (char *) wcbuf;
00072     size_t outleft = sizeof (wcbuf);
00073     size_t nonr;
00074 
00075     cd = iconv_open ("WCHAR_T", "UTF-8");
00076     if (cd == (iconv_t) -1)
00077       {
00078        printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
00079               __LINE__);
00080        exit (1);
00081       }
00082 
00083     /* We must need only one call and there must be no losses.  */
00084     nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
00085     if (nonr != 0 && nonr != (size_t) -1)
00086       {
00087        printf ("%u: iconv performed %Zd nonreversible conversions\n",
00088               __LINE__, nonr);
00089        exit (1);
00090       }
00091 
00092     if  (nonr == (size_t) -1)
00093       {
00094        printf ("\
00095 %u: iconv returned with %Zd and errno = %m (inleft: %Zd, outleft: %Zd)\n",
00096               __LINE__, nonr, inleft, outleft);
00097        exit (1);
00098       }
00099 
00100     if (inleft != 0)
00101       {
00102        printf ("%u: iconv didn't convert all input\n", __LINE__);
00103        exit (1);
00104       }
00105 
00106     iconv_close (cd);
00107 
00108     if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
00109       {
00110        printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
00111        exit (1);
00112       }
00113 
00114     wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
00115     assert (wcsize + 1 <= SIZE);
00116   }
00117 
00118   /* Now that we finished the preparations, run the first test.  We
00119      are writing the wide char data out and read it back in.  We write
00120      and read single characters.  */
00121 
00122   fd = mkstemp (name);
00123   if (fd == -1)
00124     {
00125       printf ("%u: cannot open temporary file: %m\n", __LINE__);
00126       exit (1);
00127     }
00128 
00129   unlink (name);
00130 
00131   fp = fdopen (dup (fd), "w");
00132   if (fp == NULL)
00133     {
00134       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
00135       exit (1);
00136     }
00137 
00138   for (n = 0; n < wcsize; ++n)
00139     {
00140       if (fputwc (wcbuf[n], fp) == WEOF)
00141        {
00142          printf ("%u: fputwc failed: %m\n", __LINE__);
00143          exit (1);
00144        }
00145     }
00146 
00147   res = fclose (fp);
00148   if (res != 0)
00149     {
00150       printf ("%u: fclose after single-character writing failed (%d): %m\n",
00151              __LINE__, res);
00152       exit (1);
00153     }
00154 
00155   lseek (fd, SEEK_SET, 0);
00156   fp = fdopen (dup (fd), "r");
00157   if (fp == NULL)
00158     {
00159       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
00160       exit (1);
00161     }
00162 
00163   for (n = 0; n < wcsize; ++n)
00164     {
00165       wint_t wch = fgetwc (fp);
00166       if (wch == WEOF)
00167        {
00168          printf ("%u: fgetwc failed (idx %Zd): %m\n", __LINE__, n);
00169          exit (1);
00170        }
00171       wc2buf[n] = wch;
00172     }
00173 
00174   /* There should be nothing else.  */
00175   if (fgetwc (fp) != WEOF)
00176     {
00177       printf ("%u: too many characters available with fgetwc\n", __LINE__);
00178       status = 1;
00179     }
00180   else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
00181     {
00182       printf ("%u: buffer read with fgetwc differs\n", __LINE__);
00183       status = 1;
00184     }
00185 
00186   res = fclose (fp);
00187   if (res != 0)
00188     {
00189       printf ("%u: fclose after single-character reading failed (%d): %m\n",
00190              __LINE__, res);
00191       exit (1);
00192     }
00193 
00194   /* Just make sure there are no two errors which hide each other, read the
00195      file using the `char' functions.  */
00196 
00197   lseek (fd, SEEK_SET, 0);
00198   fp = fdopen (fd, "r");
00199   if (fp == NULL)
00200     {
00201       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
00202       exit (1);
00203     }
00204 
00205   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
00206     {
00207       printf ("%u: cannot read all of the temp file\n", __LINE__);
00208       status = 1;
00209     }
00210   else
00211     {
00212       /* Make sure there is nothing left.  */
00213       if (fgetc (fp) != EOF)
00214        {
00215          printf ("%u: more input available\n", __LINE__);
00216          status = 1;
00217        }
00218 
00219       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
00220        {
00221          printf ("%u: buffer written with fputwc differs\n", __LINE__);
00222          status = 1;
00223        }
00224     }
00225 
00226   res = fclose (fp);
00227   if (res != 0)
00228     {
00229       printf ("%u: fclose after single-character reading failed (%d): %m\n",
00230              __LINE__, res);
00231       exit (1);
00232     }
00233 
00234   /* Now to reading and writing line-wise.  */
00235 
00236   fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
00237   if (fd == -1)
00238     {
00239       printf ("%u: cannot open temporary file: %m\n", __LINE__);
00240       exit (1);
00241     }
00242 
00243   unlink (name);
00244 
00245   fp = fdopen (dup (fd), "w");
00246   if (fp == NULL)
00247     {
00248       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
00249       exit (1);
00250     }
00251 
00252   for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
00253     {
00254       wchar_t *wendp = wcschr (wcp, L'\n');
00255 
00256       if (wendp != NULL)
00257        {
00258          /* Temporarily NUL terminate the line.  */
00259          wchar_t save = wendp[1];
00260          wendp[1] = L'\0';
00261 
00262          fputws (wcp, fp);
00263 
00264          wendp[1] = save;
00265          wcp = &wendp[1];
00266        }
00267       else
00268        {
00269          fputws (wcp, fp);
00270          wcp = wcschr (wcp, L'\0');
00271          assert (wcp == &wcbuf[wcsize]);
00272        }
00273     }
00274 
00275   res = fclose (fp);
00276   if (res != 0)
00277     {
00278       printf ("%u: fclose after line-wise writing failed (%d): %m\n",
00279              __LINE__, res);
00280       exit (1);
00281     }
00282 
00283   lseek (fd, SEEK_SET, 0);
00284   fp = fdopen (dup (fd), "r");
00285   if (fp == NULL)
00286     {
00287       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
00288       exit (1);
00289     }
00290 
00291   for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
00292     {
00293       if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
00294        {
00295          printf ("%u: short read using fgetws (only %Zd of %Zd)\n",
00296                 __LINE__, wcp - wc2buf, wcsize);
00297          status = 1;
00298          break;
00299        }
00300       wcp = wcschr (wcp, L'\0');
00301     }
00302 
00303   if (wcp > &wc2buf[wcsize])
00304     {
00305       printf ("%u: fgetws read too much\n", __LINE__);
00306       status = 1;
00307     }
00308   else if (fgetwc (fp) != WEOF)
00309     {
00310       /* There should be nothing else.  */
00311       printf ("%u: too many characters available with fgetws\n", __LINE__);
00312       status = 1;
00313     }
00314 
00315   if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
00316     {
00317       printf ("%u: buffer read with fgetws differs\n", __LINE__);
00318       status = 1;
00319     }
00320 
00321   res = fclose (fp);
00322   if (res != 0)
00323     {
00324       printf ("%u: fclose after single-character reading failed (%d): %m\n",
00325              __LINE__, res);
00326       exit (1);
00327     }
00328 
00329   /* Just make sure there are no two errors which hide each other, read the
00330      file using the `char' functions.  */
00331 
00332   lseek (fd, SEEK_SET, 0);
00333   fp = fdopen (fd, "r");
00334   if (fp == NULL)
00335     {
00336       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
00337       exit (1);
00338     }
00339 
00340   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
00341     {
00342       printf ("%u: cannot read all of the temp file\n", __LINE__);
00343       status = 1;
00344     }
00345   else
00346     {
00347       /* Make sure there is nothing left.  */
00348       if (fgetc (fp) != EOF)
00349        {
00350          printf ("%u: more input available\n", __LINE__);
00351          status = 1;
00352        }
00353 
00354       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
00355        {
00356          printf ("%u: buffer written with fputws differs\n", __LINE__);
00357          status = 1;
00358        }
00359     }
00360 
00361   res = fclose (fp);
00362   if (res != 0)
00363     {
00364       printf ("%u: fclose after single-character reading failed (%d): %m\n",
00365              __LINE__, res);
00366       exit (1);
00367     }
00368 
00369   return status;
00370 }