(root)/
gettext-0.22.4/
libtextstyle/
lib/
iconv-ostream.c
       1  /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
       2  
       3  #if !IS_CPLUSPLUS
       4  #define iconv_ostream_representation any_ostream_representation
       5  #endif
       6  #line 1 "iconv-ostream.oo.c"
       7  /* Output stream that converts the output to another encoding.
       8     Copyright (C) 2006-2007, 2010, 2019-2020 Free Software Foundation, Inc.
       9     Written by Bruno Haible <bruno@clisp.org>, 2006.
      10  
      11     This program is free software: you can redistribute it and/or modify
      12     it under the terms of the GNU General Public License as published by
      13     the Free Software Foundation; either version 3 of the License, or
      14     (at your option) any later version.
      15  
      16     This program is distributed in the hope that it will be useful,
      17     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19     GNU General Public License for more details.
      20  
      21     You should have received a copy of the GNU General Public License
      22     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      23  
      24  #include <config.h>
      25  
      26  /* Specification.  */
      27  #include "iconv-ostream.h"
      28  
      29  #if HAVE_ICONV
      30  
      31  #include <errno.h>
      32  #include <iconv.h>
      33  #include <stdlib.h>
      34  #include <string.h>
      35  
      36  #include "c-strcase.h"
      37  #include "error.h"
      38  #include "xalloc.h"
      39  #include "gettext.h"
      40  
      41  #define _(str) gettext (str)
      42  
      43  #endif /* HAVE_ICONV */
      44  
      45  #line 46 "iconv-ostream.c"
      46  #include "iconv_ostream.priv.h"
      47  
      48  const typeinfo_t iconv_ostream_typeinfo = { "iconv_ostream" };
      49  
      50  static const typeinfo_t * const iconv_ostream_superclasses[] =
      51    { iconv_ostream_SUPERCLASSES };
      52  
      53  #define super ostream_vtable
      54  
      55  #line 56 "iconv-ostream.oo.c"
      56  
      57  #if HAVE_ICONV
      58  
      59  /* Implementation of ostream_t methods.  */
      60  
      61  static void
      62  iconv_ostream__write_mem (iconv_ostream_t stream, const void *data, size_t len)
      63  {
      64    if (len > 0)
      65      {
      66        #define BUFFERSIZE 256
      67        char inbuffer[BUFFERSIZE];
      68        size_t inbufcount;
      69  
      70        inbufcount = stream->buflen;
      71        if (inbufcount > 0)
      72          memcpy (inbuffer, stream->buf, inbufcount);
      73        for (;;)
      74          {
      75            /* At this point, inbuffer[0..inbufcount-1] is filled.  */
      76            {
      77              /* Combine the previous rest with a chunk of new input.  */
      78              size_t n =
      79                (len <= BUFFERSIZE - inbufcount ? len : BUFFERSIZE - inbufcount);
      80  
      81              if (n > 0)
      82                {
      83                  memcpy (inbuffer + inbufcount, data, n);
      84                  data = (const char *) data + n;
      85                  inbufcount += n;
      86                  len -= n;
      87                }
      88            }
      89            {
      90              /* Attempt to convert the combined input.  */
      91              char outbuffer[8*BUFFERSIZE];
      92  
      93              const char *inptr = inbuffer;
      94              size_t insize = inbufcount;
      95              char *outptr = outbuffer;
      96              size_t outsize = sizeof (outbuffer);
      97  
      98              size_t res = iconv (stream->cd,
      99                                  (ICONV_CONST char **) &inptr, &insize,
     100                                  &outptr, &outsize);
     101              #if !defined _LIBICONV_VERSION \
     102                  && !(defined __GLIBC__ && !defined __UCLIBC__)
     103              /* Irix iconv() inserts a NUL byte if it cannot convert.
     104                 NetBSD iconv() inserts a question mark if it cannot convert.
     105                 Only GNU libiconv and GNU libc are known to prefer to fail rather
     106                 than doing a lossy conversion.  */
     107              if (res > 0)
     108                {
     109                  errno = EILSEQ;
     110                  res = -1;
     111                }
     112              #endif
     113              if (res == (size_t)(-1) && errno != EINVAL)
     114                error (EXIT_FAILURE, 0, _("%s: cannot convert from %s to %s"),
     115                       "iconv_ostream",
     116                       stream->from_encoding, stream->to_encoding);
     117              /* Output the converted part.  */
     118              if (sizeof (outbuffer) - outsize > 0)
     119                ostream_write_mem (stream->destination,
     120                                   outbuffer, sizeof (outbuffer) - outsize);
     121              /* Put back the unconverted part.  */
     122              if (insize > BUFSIZE)
     123                error (EXIT_FAILURE, 0, _("%s: shift sequence too long"),
     124                       "iconv_ostream");
     125              if (len == 0)
     126                {
     127                  if (insize > 0)
     128                    memcpy (stream->buf, inptr, insize);
     129                  stream->buflen = insize;
     130                  break;
     131                }
     132              if (insize > 0)
     133                memmove (inbuffer, inptr, insize);
     134              inbufcount = insize;
     135            }
     136          }
     137        #undef BUFFERSIZE
     138      }
     139  }
     140  
     141  static void
     142  iconv_ostream__flush (iconv_ostream_t stream, ostream_flush_scope_t scope)
     143  {
     144    /* For scope == FLUSH_THIS_STREAM, there's nothing we can do here, since
     145       stream->buf[] contains only a few bytes that don't correspond to a
     146       character.  */
     147    if (scope != FLUSH_THIS_STREAM)
     148      ostream_flush (stream->destination, scope);
     149  }
     150  
     151  static void
     152  iconv_ostream__free (iconv_ostream_t stream)
     153  {
     154    /* Silently ignore the few bytes in stream->buf[] that don't correspond to a
     155       character.  */
     156  
     157    /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
     158    #if defined _LIBICONV_VERSION \
     159        || !(((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) \
     160              && !defined __UCLIBC__) \
     161             || defined __sun)
     162    {
     163      char outbuffer[2048];
     164      char *outptr = outbuffer;
     165      size_t outsize = sizeof (outbuffer);
     166      size_t res = iconv (stream->cd, NULL, NULL, &outptr, &outsize);
     167      if (res == (size_t)(-1))
     168        error (EXIT_FAILURE, 0, _("%s: cannot convert from %s to %s"),
     169               "iconv_ostream", stream->from_encoding, stream->to_encoding);
     170      /* Output the converted part.  */
     171      if (sizeof (outbuffer) - outsize > 0)
     172        ostream_write_mem (stream->destination,
     173                           outbuffer, sizeof (outbuffer) - outsize);
     174    }
     175    #endif
     176  
     177    iconv_close (stream->cd);
     178    free (stream->from_encoding);
     179    free (stream->to_encoding);
     180    free (stream);
     181  }
     182  
     183  /* Constructor.  */
     184  
     185  iconv_ostream_t
     186  iconv_ostream_create (const char *from_encoding, const char *to_encoding,
     187                        ostream_t destination)
     188  {
     189    iconv_ostream_t stream = XMALLOC (struct iconv_ostream_representation);
     190  
     191    stream->base.vtable = &iconv_ostream_vtable;
     192    stream->destination = destination;
     193    stream->from_encoding = xstrdup (from_encoding);
     194    stream->to_encoding = xstrdup (to_encoding);
     195  
     196    /* Avoid glibc-2.1 bug with EUC-KR.  */
     197    #if ((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) \
     198         && !defined __UCLIBC__) \
     199        && !defined _LIBICONV_VERSION
     200    if (c_strcasecmp (from_encoding, "EUC-KR") == 0
     201        || c_strcasecmp (to_encoding, "EUC-KR") == 0)
     202      stream->cd = (iconv_t)(-1):
     203    else
     204    #endif
     205      stream->cd = iconv_open (to_encoding, from_encoding);
     206    if (stream->cd == (iconv_t)(-1))
     207      {
     208        if (iconv_open ("UTF-8", from_encoding) == (iconv_t)(-1))
     209          error (EXIT_FAILURE, 0, _("%s does not support conversion from %s"),
     210                 "iconv", from_encoding);
     211        else if (iconv_open (to_encoding, "UTF-8") == (iconv_t)(-1))
     212          error (EXIT_FAILURE, 0, _("%s does not support conversion to %s"),
     213                 "iconv", to_encoding);
     214        else
     215          error (EXIT_FAILURE, 0,
     216                 _("%s does not support conversion from %s to %s"),
     217                 "iconv", from_encoding, to_encoding);
     218      }
     219  
     220    stream->buflen = 0;
     221  
     222    return stream;
     223  }
     224  
     225  /* Accessors.  */
     226  
     227  static const char *
     228  iconv_ostream__get_from_encoding (iconv_ostream_t stream)
     229  {
     230    return stream->from_encoding;
     231  }
     232  
     233  static const char *
     234  iconv_ostream__get_to_encoding (iconv_ostream_t stream)
     235  {
     236    return stream->to_encoding;
     237  }
     238  
     239  static ostream_t
     240  iconv_ostream__get_destination (iconv_ostream_t stream)
     241  {
     242    return stream->destination;
     243  }
     244  
     245  /* Instanceof test.  */
     246  
     247  bool
     248  is_instance_of_iconv_ostream (ostream_t stream)
     249  {
     250    return IS_INSTANCE (stream, ostream, iconv_ostream);
     251  }
     252  
     253  #else
     254  
     255  static void
     256  iconv_ostream__write_mem (iconv_ostream_t stream, const void *data, size_t len)
     257  {
     258    abort ();
     259  }
     260  
     261  static void
     262  iconv_ostream__flush (iconv_ostream_t stream)
     263  {
     264    abort ();
     265  }
     266  
     267  static void
     268  iconv_ostream__free (iconv_ostream_t stream)
     269  {
     270    abort ();
     271  }
     272  
     273  /* Accessors.  */
     274  
     275  static const char *
     276  iconv_ostream__get_from_encoding (iconv_ostream_t stream)
     277  {
     278    abort ();
     279  }
     280  
     281  static const char *
     282  iconv_ostream__get_to_encoding (iconv_ostream_t stream)
     283  {
     284    abort ();
     285  }
     286  
     287  static ostream_t
     288  iconv_ostream__get_destination (iconv_ostream_t stream)
     289  {
     290    abort ();
     291  }
     292  
     293  /* Instanceof test.  */
     294  
     295  bool
     296  is_instance_of_iconv_ostream (ostream_t stream)
     297  {
     298    return false;
     299  }
     300  
     301  #endif /* HAVE_ICONV */
     302  
     303  #line 304 "iconv-ostream.c"
     304  
     305  const struct iconv_ostream_implementation iconv_ostream_vtable =
     306  {
     307    iconv_ostream_superclasses,
     308    sizeof (iconv_ostream_superclasses) / sizeof (iconv_ostream_superclasses[0]),
     309    sizeof (struct iconv_ostream_representation),
     310    iconv_ostream__write_mem,
     311    iconv_ostream__flush,
     312    iconv_ostream__free,
     313    iconv_ostream__get_from_encoding,
     314    iconv_ostream__get_to_encoding,
     315    iconv_ostream__get_destination,
     316  };
     317  
     318  #if !HAVE_INLINE
     319  
     320  /* Define the functions that invoke the methods.  */
     321  
     322  void
     323  iconv_ostream_write_mem (iconv_ostream_t first_arg, const void *data, size_t len)
     324  {
     325    const struct iconv_ostream_implementation *vtable =
     326      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     327    vtable->write_mem (first_arg,data,len);
     328  }
     329  
     330  void
     331  iconv_ostream_flush (iconv_ostream_t first_arg, ostream_flush_scope_t scope)
     332  {
     333    const struct iconv_ostream_implementation *vtable =
     334      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     335    vtable->flush (first_arg,scope);
     336  }
     337  
     338  void
     339  iconv_ostream_free (iconv_ostream_t first_arg)
     340  {
     341    const struct iconv_ostream_implementation *vtable =
     342      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     343    vtable->free (first_arg);
     344  }
     345  
     346  const char *
     347  iconv_ostream_get_from_encoding (iconv_ostream_t first_arg)
     348  {
     349    const struct iconv_ostream_implementation *vtable =
     350      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     351    return vtable->get_from_encoding (first_arg);
     352  }
     353  
     354  const char *
     355  iconv_ostream_get_to_encoding (iconv_ostream_t first_arg)
     356  {
     357    const struct iconv_ostream_implementation *vtable =
     358      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     359    return vtable->get_to_encoding (first_arg);
     360  }
     361  
     362  ostream_t
     363  iconv_ostream_get_destination (iconv_ostream_t first_arg)
     364  {
     365    const struct iconv_ostream_implementation *vtable =
     366      ((struct iconv_ostream_representation_header *) (struct iconv_ostream_representation *) first_arg)->vtable;
     367    return vtable->get_destination (first_arg);
     368  }
     369  
     370  #endif