(root)/
gettext-0.22.4/
libtextstyle/
lib/
fd-ostream.c
       1  /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
       2  
       3  #if !IS_CPLUSPLUS
       4  #define fd_ostream_representation any_ostream_representation
       5  #endif
       6  #line 1 "fd-ostream.oo.c"
       7  /* Output stream referring to a file descriptor.
       8     Copyright (C) 2006-2007, 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 "fd-ostream.h"
      28  
      29  #include <assert.h>
      30  #include <errno.h>
      31  #include <stdlib.h>
      32  #include <string.h>
      33  #include <unistd.h>
      34  #if HAVE_TCDRAIN
      35  # include <termios.h>
      36  #endif
      37  
      38  #include "error.h"
      39  #include "full-write.h"
      40  #include "xalloc.h"
      41  #include "gettext.h"
      42  
      43  #define _(str) gettext (str)
      44  
      45  #line 46 "fd-ostream.c"
      46  #include "fd_ostream.priv.h"
      47  
      48  const typeinfo_t fd_ostream_typeinfo = { "fd_ostream" };
      49  
      50  static const typeinfo_t * const fd_ostream_superclasses[] =
      51    { fd_ostream_SUPERCLASSES };
      52  
      53  #define super ostream_vtable
      54  
      55  #line 47 "fd-ostream.oo.c"
      56  
      57  #define BUFSIZE 4096
      58  
      59  #if HAVE_TCDRAIN
      60  
      61  /* EINTR handling for tcdrain().
      62     This function can return -1/EINTR even though we don't have any
      63     signal handlers set up, namely when we get interrupted via SIGSTOP.  */
      64  
      65  static inline int
      66  nonintr_tcdrain (int fd)
      67  {
      68    int retval;
      69  
      70    do
      71      retval = tcdrain (fd);
      72    while (retval < 0 && errno == EINTR);
      73  
      74    return retval;
      75  }
      76  
      77  #endif
      78  
      79  /* Implementation of ostream_t methods.  */
      80  
      81  static void
      82  fd_ostream__write_mem (fd_ostream_t stream, const void *data, size_t len)
      83  {
      84    if (len > 0)
      85      {
      86        if (stream->buffer != NULL)
      87          {
      88            /* Buffered.  */
      89            assert (stream->avail > 0);
      90            #if 0 /* unoptimized */
      91            do
      92              {
      93                size_t n = (len <= stream->avail ? len : stream->avail);
      94                if (n > 0)
      95                  {
      96                    memcpy (stream->buffer + BUFSIZE - stream->avail, data, n);
      97                    data = (const char *) data + n;
      98                    stream->avail -= n;
      99                    len -= n;
     100                  }
     101                if (stream->avail == 0)
     102                  {
     103                    if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
     104                      error (EXIT_FAILURE, errno, _("error writing to %s"),
     105                             stream->filename);
     106                    stream->avail = BUFSIZE;
     107                  }
     108              }
     109            while (len > 0);
     110            #else /* optimized */
     111            if (len < stream->avail)
     112              {
     113                /* Move the data into the buffer.  */
     114                memcpy (stream->buffer + BUFSIZE - stream->avail, data, len);
     115                stream->avail -= len;
     116              }
     117            else
     118              {
     119                /* Split the data into:
     120                     - a first chunk, which is added to the buffer and output,
     121                     - a series of chunks of size BUFSIZE, which can be output
     122                       directly, without going through the buffer, and
     123                     - a last chunk, which is copied to the buffer.  */
     124                size_t n = stream->avail;
     125                memcpy (stream->buffer + BUFSIZE - stream->avail, data, n);
     126                data = (const char *) data + n;
     127                len -= n;
     128                if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
     129                  error (EXIT_FAILURE, errno, _("error writing to %s"),
     130                         stream->filename);
     131  
     132                while (len >= BUFSIZE)
     133                  {
     134                    if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE)
     135                      error (EXIT_FAILURE, errno, _("error writing to %s"),
     136                             stream->filename);
     137                    data = (const char *) data + BUFSIZE;
     138                    len -= BUFSIZE;
     139                  }
     140  
     141                if (len > 0)
     142                  memcpy (stream->buffer, data, len);
     143                stream->avail = BUFSIZE - len;
     144              }
     145            #endif
     146            assert (stream->avail > 0);
     147          }
     148        else
     149          {
     150            /* Unbuffered.  */
     151            if (full_write (stream->fd, data, len) < len)
     152              error (EXIT_FAILURE, errno, _("error writing to %s"),
     153                     stream->filename);
     154          }
     155      }
     156  }
     157  
     158  static void
     159  fd_ostream__flush (fd_ostream_t stream, ostream_flush_scope_t scope)
     160  {
     161    if (stream->buffer != NULL && stream->avail < BUFSIZE)
     162      {
     163        size_t filled = BUFSIZE - stream->avail;
     164        if (full_write (stream->fd, stream->buffer, filled) < filled)
     165          error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename);
     166        stream->avail = BUFSIZE;
     167      }
     168    if (scope == FLUSH_ALL)
     169      {
     170        /* For streams connected to a disk file:  */
     171        fsync (stream->fd);
     172        #if HAVE_TCDRAIN
     173        /* For streams connected to a terminal:  */
     174        nonintr_tcdrain (stream->fd);
     175        #endif
     176      }
     177  }
     178  
     179  static void
     180  fd_ostream__free (fd_ostream_t stream)
     181  {
     182    fd_ostream_flush (stream, FLUSH_THIS_STREAM);
     183    free (stream->filename);
     184    free (stream);
     185  }
     186  
     187  /* Constructor.  */
     188  
     189  fd_ostream_t
     190  fd_ostream_create (int fd, const char *filename, bool buffered)
     191  {
     192    fd_ostream_t stream =
     193      (struct fd_ostream_representation *)
     194      xmalloc (sizeof (struct fd_ostream_representation)
     195               + (buffered ? BUFSIZE : 0));
     196  
     197    stream->base.vtable = &fd_ostream_vtable;
     198    stream->fd = fd;
     199    stream->filename = xstrdup (filename);
     200    if (buffered)
     201      {
     202        stream->buffer =
     203          (char *) (void *) stream + sizeof (struct fd_ostream_representation);
     204        stream->avail = BUFSIZE;
     205      }
     206    else
     207      stream->buffer = NULL;
     208  
     209    return stream;
     210  }
     211  
     212  /* Accessors.  */
     213  
     214  static int
     215  fd_ostream__get_descriptor (fd_ostream_t stream)
     216  {
     217    return stream->fd;
     218  }
     219  
     220  static const char *
     221  fd_ostream__get_filename (fd_ostream_t stream)
     222  {
     223    return stream->filename;
     224  }
     225  
     226  static bool
     227  fd_ostream__is_buffered (fd_ostream_t stream)
     228  {
     229    return stream->buffer != NULL;
     230  }
     231  
     232  /* Instanceof test.  */
     233  
     234  bool
     235  is_instance_of_fd_ostream (ostream_t stream)
     236  {
     237    return IS_INSTANCE (stream, ostream, fd_ostream);
     238  }
     239  
     240  #line 241 "fd-ostream.c"
     241  
     242  const struct fd_ostream_implementation fd_ostream_vtable =
     243  {
     244    fd_ostream_superclasses,
     245    sizeof (fd_ostream_superclasses) / sizeof (fd_ostream_superclasses[0]),
     246    sizeof (struct fd_ostream_representation),
     247    fd_ostream__write_mem,
     248    fd_ostream__flush,
     249    fd_ostream__free,
     250    fd_ostream__get_descriptor,
     251    fd_ostream__get_filename,
     252    fd_ostream__is_buffered,
     253  };
     254  
     255  #if !HAVE_INLINE
     256  
     257  /* Define the functions that invoke the methods.  */
     258  
     259  void
     260  fd_ostream_write_mem (fd_ostream_t first_arg, const void *data, size_t len)
     261  {
     262    const struct fd_ostream_implementation *vtable =
     263      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     264    vtable->write_mem (first_arg,data,len);
     265  }
     266  
     267  void
     268  fd_ostream_flush (fd_ostream_t first_arg, ostream_flush_scope_t scope)
     269  {
     270    const struct fd_ostream_implementation *vtable =
     271      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     272    vtable->flush (first_arg,scope);
     273  }
     274  
     275  void
     276  fd_ostream_free (fd_ostream_t first_arg)
     277  {
     278    const struct fd_ostream_implementation *vtable =
     279      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     280    vtable->free (first_arg);
     281  }
     282  
     283  int
     284  fd_ostream_get_descriptor (fd_ostream_t first_arg)
     285  {
     286    const struct fd_ostream_implementation *vtable =
     287      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     288    return vtable->get_descriptor (first_arg);
     289  }
     290  
     291  const char *
     292  fd_ostream_get_filename (fd_ostream_t first_arg)
     293  {
     294    const struct fd_ostream_implementation *vtable =
     295      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     296    return vtable->get_filename (first_arg);
     297  }
     298  
     299  bool
     300  fd_ostream_is_buffered (fd_ostream_t first_arg)
     301  {
     302    const struct fd_ostream_implementation *vtable =
     303      ((struct fd_ostream_representation_header *) (struct fd_ostream_representation *) first_arg)->vtable;
     304    return vtable->is_buffered (first_arg);
     305  }
     306  
     307  #endif