1 /* Output stream referring to a file descriptor.
2 Copyright (C) 2006-2007, 2015 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "fd-ostream.h"
29 #include "full-write.h"
33 #define _(str) gettext (str)
35 struct fd_ostream : struct ostream
40 char *buffer; /* A buffer, or NULL. */
41 size_t avail; /* Number of bytes available in the buffer. */
46 /* Implementation of ostream_t methods. */
49 fd_ostream::write_mem (fd_ostream_t stream, const void *data, size_t len)
53 if (stream->buffer != NULL)
56 assert (stream->avail > 0);
57 #if 0 /* unoptimized */
60 size_t n = (len <= stream->avail ? len : stream->avail);
63 memcpy (stream->buffer + BUFSIZE - stream->avail, data, n);
64 data = (char *) data + n;
68 if (stream->avail == 0)
70 if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
71 error (EXIT_FAILURE, errno, _("error writing to %s"),
73 stream->avail = BUFSIZE;
78 if (len < stream->avail)
80 /* Move the data into the buffer. */
81 memcpy (stream->buffer + BUFSIZE - stream->avail, data, len);
86 /* Split the data into:
87 - a first chunk, which is added to the buffer and output,
88 - a series of chunks of size BUFSIZE, which can be output
89 directly, without going through the buffer, and
90 - a last chunk, which is copied to the buffer. */
91 size_t n = stream->avail;
92 memcpy (stream->buffer + BUFSIZE - stream->avail, data, n);
93 data = (char *) data + n;
95 if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
96 error (EXIT_FAILURE, errno, _("error writing to %s"),
99 while (len >= BUFSIZE)
101 if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE)
102 error (EXIT_FAILURE, errno, _("error writing to %s"),
104 data = (char *) data + BUFSIZE;
109 memcpy (stream->buffer, data, len);
110 stream->avail = BUFSIZE - len;
113 assert (stream->avail > 0);
118 if (full_write (stream->fd, data, len) < len)
119 error (EXIT_FAILURE, errno, _("error writing to %s"),
126 fd_ostream::flush (fd_ostream_t stream)
128 if (stream->buffer != NULL && stream->avail < BUFSIZE)
130 size_t filled = BUFSIZE - stream->avail;
131 if (full_write (stream->fd, stream->buffer, filled) < filled)
132 error (EXIT_FAILURE, errno, _("error writing to %s"), stream->filename);
133 stream->avail = BUFSIZE;
138 fd_ostream::free (fd_ostream_t stream)
140 fd_ostream_flush (stream);
141 free (stream->filename);
148 fd_ostream_create (int fd, const char *filename, bool buffered)
150 fd_ostream_t stream =
151 (struct fd_ostream_representation *)
152 xmalloc (sizeof (struct fd_ostream_representation)
153 + (buffered ? BUFSIZE : 0));
155 stream->base.vtable = &fd_ostream_vtable;
157 stream->filename = xstrdup (filename);
161 (char *) (void *) stream + sizeof (struct fd_ostream_representation);
162 stream->avail = BUFSIZE;
165 stream->buffer = NULL;