• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* Output stream referring to a file descriptor.
2   Copyright (C) 2006-2007 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2006.
4
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.
9
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.
14
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/>.  */
17
18#include <config.h>
19
20/* Specification.  */
21#include "fd-ostream.h"
22
23#include <assert.h>
24#include <errno.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "error.h"
29#include "full-write.h"
30#include "xalloc.h"
31#include "gettext.h"
32
33#define _(str) gettext (str)
34
35struct fd_ostream : struct ostream
36{
37fields:
38  int fd;
39  char *filename;
40  char *buffer;			/* A buffer, or NULL.  */
41  size_t avail;			/* Number of bytes available in the buffer.  */
42};
43
44#define BUFSIZE 4096
45
46/* Implementation of ostream_t methods.  */
47
48static void
49fd_ostream::write_mem (fd_ostream_t stream, const void *data, size_t len)
50{
51  if (len > 0)
52    {
53      if (stream->buffer != NULL)
54	{
55	  /* Buffered.  */
56	  assert (stream->avail > 0);
57	  #if 0 /* unoptimized */
58	  do
59	    {
60	      size_t n = (len <= stream->avail ? len : stream->avail);
61	      if (n > 0)
62		{
63		  memcpy (stream->buffer + BUFSIZE - stream->avail, data, n);
64		  data = (char *) data + n;
65		  stream->avail -= n;
66		  len -= n;
67		}
68	      if (stream->avail == 0)
69		{
70		  if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
71		    error (EXIT_FAILURE, errno, _("error writing to %s"),
72			   stream->filename);
73		  stream->avail = BUFSIZE;
74		}
75	    }
76	  while (len > 0);
77	  #else /* optimized */
78	  if (len < stream->avail)
79	    {
80	      /* Move the data into the buffer.  */
81	      memcpy (stream->buffer + BUFSIZE - stream->avail, data, len);
82	      stream->avail -= len;
83	    }
84	  else
85	    {
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;
94	      len -= n;
95	      if (full_write (stream->fd, stream->buffer, BUFSIZE) < BUFSIZE)
96		error (EXIT_FAILURE, errno, _("error writing to %s"),
97		       stream->filename);
98
99	      while (len >= BUFSIZE)
100		{
101		  if (full_write (stream->fd, data, BUFSIZE) < BUFSIZE)
102		    error (EXIT_FAILURE, errno, _("error writing to %s"),
103			   stream->filename);
104		  data = (char *) data + BUFSIZE;
105		  len -= BUFSIZE;
106		}
107
108	      if (len > 0)
109		memcpy (stream->buffer, data, len);
110	      stream->avail = BUFSIZE - len;
111	    }
112	  #endif
113	  assert (stream->avail > 0);
114	}
115      else
116	{
117	  /* Unbuffered.  */
118	  if (full_write (stream->fd, data, len) < len)
119	    error (EXIT_FAILURE, errno, _("error writing to %s"),
120		   stream->filename);
121	}
122    }
123}
124
125static void
126fd_ostream::flush (fd_ostream_t stream)
127{
128  if (stream->buffer != NULL && stream->avail < BUFSIZE)
129    {
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;
134    }
135}
136
137static void
138fd_ostream::free (fd_ostream_t stream)
139{
140  fd_ostream_flush (stream);
141  free (stream->filename);
142  free (stream);
143}
144
145/* Constructor.  */
146
147fd_ostream_t
148fd_ostream_create (int fd, const char *filename, bool buffered)
149{
150  fd_ostream_t stream =
151    (struct fd_ostream_representation *)
152    xmalloc (sizeof (struct fd_ostream_representation)
153	     + (buffered ? BUFSIZE : 0));
154
155  stream->base.vtable = &fd_ostream_vtable;
156  stream->fd = fd;
157  stream->filename = xstrdup (filename);
158  if (buffered)
159    {
160      stream->buffer =
161	(char *) (void *) stream + sizeof (struct fd_ostream_representation);
162      stream->avail = BUFSIZE;
163    }
164  else
165    stream->buffer = NULL;
166
167  return stream;
168}
169