Blame libio/tst-widetext.c

Packit 6c4009
/* Test program for the wide character stream functions handling larger
Packit 6c4009
   amounts of text.
Packit 6c4009
   Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@cygnus.com>.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <iconv.h>
Packit 6c4009
#include <locale.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <wchar.h>
Packit 6c4009
Packit 6c4009
/* Approximate size of the file (must be larger).  */
Packit 6c4009
#define SIZE 210000
Packit 6c4009
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  char name[] = "/tmp/widetext.out.XXXXXX";
Packit 6c4009
  char mbbuf[SIZE];
Packit 6c4009
  char mb2buf[SIZE];
Packit 6c4009
  wchar_t wcbuf[SIZE];
Packit 6c4009
  wchar_t wc2buf[SIZE];
Packit 6c4009
  size_t mbsize;
Packit 6c4009
  size_t wcsize;
Packit 6c4009
  int fd;
Packit 6c4009
  FILE *fp;
Packit 6c4009
  size_t n;
Packit 6c4009
  int res;
Packit 6c4009
  int status = 0;
Packit 6c4009
  wchar_t *wcp;
Packit 6c4009
Packit 6c4009
  setlocale (LC_ALL, "de_DE.UTF-8");
Packit 6c4009
  printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
Packit 6c4009
Packit 6c4009
  /* Read the file into memory.  */
Packit 6c4009
  mbsize = fread (mbbuf, 1, SIZE, stdin);
Packit 6c4009
  if (mbsize == 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: cannot read input file from standard input: %m\n",
Packit 6c4009
	      __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
   printf ("INFO: input file has %Zd bytes\n", mbsize);
Packit 6c4009
Packit 6c4009
  /* First convert the text to wide characters.  We use iconv here.  */
Packit 6c4009
  {
Packit 6c4009
    iconv_t cd;
Packit 6c4009
    char *inbuf = mbbuf;
Packit 6c4009
    size_t inleft = mbsize;
Packit 6c4009
    char *outbuf = (char *) wcbuf;
Packit 6c4009
    size_t outleft = sizeof (wcbuf);
Packit 6c4009
    size_t nonr;
Packit 6c4009
Packit 6c4009
    cd = iconv_open ("WCHAR_T", "UTF-8");
Packit 6c4009
    if (cd == (iconv_t) -1)
Packit 6c4009
      {
Packit 6c4009
	printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
Packit 6c4009
		__LINE__);
Packit 6c4009
	exit (1);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
    /* We must need only one call and there must be no losses.  */
Packit 6c4009
    nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
Packit 6c4009
    if (nonr != 0 && nonr != (size_t) -1)
Packit 6c4009
      {
Packit 6c4009
	printf ("%u: iconv performed %Zd nonreversible conversions\n",
Packit 6c4009
		__LINE__, nonr);
Packit 6c4009
	exit (1);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
    if  (nonr == (size_t) -1)
Packit 6c4009
      {
Packit 6c4009
	printf ("\
Packit 6c4009
%u: iconv returned with %Zd and errno = %m (inleft: %Zd, outleft: %Zd)\n",
Packit 6c4009
		__LINE__, nonr, inleft, outleft);
Packit 6c4009
	exit (1);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
    if (inleft != 0)
Packit 6c4009
      {
Packit 6c4009
	printf ("%u: iconv didn't convert all input\n", __LINE__);
Packit 6c4009
	exit (1);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
    iconv_close (cd);
Packit 6c4009
Packit 6c4009
    if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
Packit 6c4009
      {
Packit 6c4009
	printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
Packit 6c4009
	exit (1);
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
    wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
Packit 6c4009
    assert (wcsize + 1 <= SIZE);
Packit 6c4009
  }
Packit 6c4009
Packit 6c4009
  /* Now that we finished the preparations, run the first test.  We
Packit 6c4009
     are writing the wide char data out and read it back in.  We write
Packit 6c4009
     and read single characters.  */
Packit 6c4009
Packit 6c4009
  fd = mkstemp (name);
Packit 6c4009
  if (fd == -1)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: cannot open temporary file: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  unlink (name);
Packit 6c4009
Packit 6c4009
  fp = fdopen (dup (fd), "w");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (n = 0; n < wcsize; ++n)
Packit 6c4009
    {
Packit 6c4009
      if (fputwc (wcbuf[n], fp) == WEOF)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: fputwc failed: %m\n", __LINE__);
Packit 6c4009
	  exit (1);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after single-character writing failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  lseek (fd, SEEK_SET, 0);
Packit 6c4009
  fp = fdopen (dup (fd), "r");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (n = 0; n < wcsize; ++n)
Packit 6c4009
    {
Packit 6c4009
      wint_t wch = fgetwc (fp);
Packit 6c4009
      if (wch == WEOF)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: fgetwc failed (idx %Zd): %m\n", __LINE__, n);
Packit 6c4009
	  exit (1);
Packit 6c4009
	}
Packit 6c4009
      wc2buf[n] = wch;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* There should be nothing else.  */
Packit 6c4009
  if (fgetwc (fp) != WEOF)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: too many characters available with fgetwc\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
  else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: buffer read with fgetwc differs\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after single-character reading failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Just make sure there are no two errors which hide each other, read the
Packit 6c4009
     file using the `char' functions.  */
Packit 6c4009
Packit 6c4009
  lseek (fd, SEEK_SET, 0);
Packit 6c4009
  fp = fdopen (fd, "r");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (fread (mb2buf, 1, mbsize, fp) != mbsize)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: cannot read all of the temp file\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      /* Make sure there is nothing left.  */
Packit 6c4009
      if (fgetc (fp) != EOF)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: more input available\n", __LINE__);
Packit 6c4009
	  status = 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (memcmp (mb2buf, mbbuf, mbsize) != 0)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: buffer written with fputwc differs\n", __LINE__);
Packit 6c4009
	  status = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after single-character reading failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Now to reading and writing line-wise.  */
Packit 6c4009
Packit 6c4009
  fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
Packit 6c4009
  if (fd == -1)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: cannot open temporary file: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  unlink (name);
Packit 6c4009
Packit 6c4009
  fp = fdopen (dup (fd), "w");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
Packit 6c4009
    {
Packit 6c4009
      wchar_t *wendp = wcschr (wcp, L'\n');
Packit 6c4009
Packit 6c4009
      if (wendp != NULL)
Packit 6c4009
	{
Packit 6c4009
	  /* Temporarily NUL terminate the line.  */
Packit 6c4009
	  wchar_t save = wendp[1];
Packit 6c4009
	  wendp[1] = L'\0';
Packit 6c4009
Packit 6c4009
	  fputws (wcp, fp);
Packit 6c4009
Packit 6c4009
	  wendp[1] = save;
Packit 6c4009
	  wcp = &wendp[1];
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  fputws (wcp, fp);
Packit 6c4009
	  wcp = wcschr (wcp, L'\0');
Packit 6c4009
	  assert (wcp == &wcbuf[wcsize]);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after line-wise writing failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  lseek (fd, SEEK_SET, 0);
Packit 6c4009
  fp = fdopen (dup (fd), "r");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
Packit 6c4009
    {
Packit 6c4009
      if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: short read using fgetws (only %td of %Zd)\n",
Packit 6c4009
		  __LINE__, wcp - wc2buf, wcsize);
Packit 6c4009
	  status = 1;
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
      wcp = wcschr (wcp, L'\0');
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (wcp > &wc2buf[wcsize])
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fgetws read too much\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
  else if (fgetwc (fp) != WEOF)
Packit 6c4009
    {
Packit 6c4009
      /* There should be nothing else.  */
Packit 6c4009
      printf ("%u: too many characters available with fgetws\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: buffer read with fgetws differs\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after single-character reading failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Just make sure there are no two errors which hide each other, read the
Packit 6c4009
     file using the `char' functions.  */
Packit 6c4009
Packit 6c4009
  lseek (fd, SEEK_SET, 0);
Packit 6c4009
  fp = fdopen (fd, "r");
Packit 6c4009
  if (fp == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (fread (mb2buf, 1, mbsize, fp) != mbsize)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: cannot read all of the temp file\n", __LINE__);
Packit 6c4009
      status = 1;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      /* Make sure there is nothing left.  */
Packit 6c4009
      if (fgetc (fp) != EOF)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: more input available\n", __LINE__);
Packit 6c4009
	  status = 1;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (memcmp (mb2buf, mbbuf, mbsize) != 0)
Packit 6c4009
	{
Packit 6c4009
	  printf ("%u: buffer written with fputws differs\n", __LINE__);
Packit 6c4009
	  status = 1;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  res = fclose (fp);
Packit 6c4009
  if (res != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("%u: fclose after single-character reading failed (%d): %m\n",
Packit 6c4009
	      __LINE__, res);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define TEST_FUNCTION do_test ()
Packit 6c4009
#include "../test-skeleton.c"