From: Bruno Haible Date: Tue, 7 Nov 2006 14:46:06 +0000 (+0000) Subject: New module 'fd-ostream': Output stream referring to a file descriptor. X-Git-Tag: v0.17~669 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=763b2e7e6d78e5f79d1362b2c043258f5a67bfa8;p=thirdparty%2Fgettext.git New module 'fd-ostream': Output stream referring to a file descriptor. --- diff --git a/gnulib-local/lib/fd-ostream.oo.c b/gnulib-local/lib/fd-ostream.oo.c new file mode 100644 index 000000000..06a9e44d7 --- /dev/null +++ b/gnulib-local/lib/fd-ostream.oo.c @@ -0,0 +1,170 @@ +/* Output stream referring to a file descriptor. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include + +/* Specification. */ +#include "fd-ostream.h" + +#include +#include +#include +#include + +#include "error.h" +#include "exit.h" +#include "full-write.h" +#include "xalloc.h" +#include "gettext.h" + +#define _(str) gettext (str) + +struct fd_ostream : struct ostream +{ +fields: + int fd; + char *filename; + char *buffer; /* A buffer, or NULL. */ + size_t avail; /* Number of bytes available in the buffer. */ +}; + +#define BUFSIZE 4096 + +/* Implementation of ostream_t methods. */ + +static void +fd_ostream::write_mem (fd_ostream_t stream, const void *data, size_t len) +{ + if (len > 0) + { + if (stream->buffer != NULL) + { + /* Buffered. */ + assert (stream->avail > 0); + #if 0 /* unoptimized */ + do + { + size_t n = (len <= stream->avail ? len : stream->avail); + if (n > 0) + { + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + stream->avail -= n; + len -= n; + } + if (stream->avail == 0) + { + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + stream->avail = BUFSIZE; + } + } + while (len > 0); + #else /* optimized */ + if (len < stream->avail) + { + /* Move the data into the buffer. */ + memcpy (stream->buffer + BUFSIZE - stream->avail, data, len); + stream->avail -= len; + } + else + { + /* Split the data into: + - a first chunk, which is added to the buffer and output, + - a series of chunks of size BUFSIZE, which can be output + directly, without going through the buffer, and + - a last chunk, which is copied to the buffer. */ + size_t n = stream->avail; + memcpy (stream->buffer + BUFSIZE - stream->avail, data, n); + data = (char *) data + n; + len -= n; + if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + + while (len >= BUFSIZE) + { + if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + data = (char *) data + BUFSIZE; + len -= BUFSIZE; + } + + if (len > 0) + memcpy (stream->buffer, data, len); + stream->avail = BUFSIZE - len; + } + #endif + assert (stream->avail > 0); + } + else + { + /* Unbuffered. */ + if (full_write (stream->fd, data, len) < len) + error (EXIT_FAILURE, errno, _("error writing to %s"), + stream->filename); + } + } +} + +static void +fd_ostream::flush (fd_ostream_t stream) +{ + if (stream->buffer != NULL && stream->avail < BUFSIZE) + { + size_t filled = BUFSIZE - stream->avail; + if (full_write (stream->fd, stream->buffer, filled) < filled) + error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename); + stream->avail = BUFSIZE; + } +} + +static void +fd_ostream::free (fd_ostream_t stream) +{ + fd_ostream_flush (stream); + free (stream->filename); + free (stream); +} + +/* Constructor. */ + +fd_ostream_t +fd_ostream_create (int fd, const char *filename, bool buffered) +{ + fd_ostream_t stream = + (struct fd_ostream_representation *) + xmalloc (sizeof (struct fd_ostream_representation) + + (buffered ? BUFSIZE : 0)); + + stream->base.vtable = &fd_ostream_vtable; + stream->fd = fd; + stream->filename = xstrdup (filename); + if (buffered) + { + stream->buffer = + (char *) (void *) stream + sizeof (struct fd_ostream_representation); + stream->avail = BUFSIZE; + } + else + stream->buffer = NULL; + + return stream; +} diff --git a/gnulib-local/lib/fd-ostream.oo.h b/gnulib-local/lib/fd-ostream.oo.h new file mode 100644 index 000000000..c9495f5c3 --- /dev/null +++ b/gnulib-local/lib/fd-ostream.oo.h @@ -0,0 +1,49 @@ +/* Output stream referring to a file descriptor. + Copyright (C) 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2006. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _FD_OSTREAM_H +#define _FD_OSTREAM_H + +#include + +#include "ostream.h" + + +struct fd_ostream : struct ostream +{ +methods: +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Create an output stream referring to the file descriptor FD. + FILENAME is used only for error messages. + Note that the resulting stream must be closed before FD can be closed. */ +extern fd_ostream_t fd_ostream_create (int fd, const char *filename, + bool buffered); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FD_OSTREAM_H */ diff --git a/gnulib-local/modules/fd-ostream b/gnulib-local/modules/fd-ostream new file mode 100644 index 000000000..1ac8af403 --- /dev/null +++ b/gnulib-local/modules/fd-ostream @@ -0,0 +1,33 @@ +Description: +Output stream referring to a file descriptor. + +Files: +lib/fd-ostream.oo.h +lib/fd-ostream.oo.c + +Depends-on: +ostream +error +exit +full-write +gettext +xalloc + +configure.ac: + +Makefile.am: +lib_SOURCES += fd-ostream.c +fd-ostream.h fd-ostream.c : $(top_srcdir)/build-aux/moopp fd-ostream.oo.h fd-ostream.oo.c ostream.oo.h + $(top_srcdir)/build-aux/moopp $(srcdir)/fd-ostream.oo.c $(srcdir)/fd-ostream.oo.h $(srcdir)/ostream.oo.h +BUILT_SOURCES += fd-ostream.h fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h +CLEANFILES += fd-ostream.h fd-ostream.c fd_ostream.priv.h fd_ostream.vt.h + +Include: +"fd-ostream.h" + +License: +GPL + +Maintainer: +Bruno Haible +