Merge remote-tracking branch 'gvdb/master'
[platform/upstream/glib.git] / gio / gfilteroutputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Christian Kellner <gicmo@gnome.org> 
21  */
22
23 #include "config.h"
24 #include "gfilteroutputstream.h"
25 #include "gsimpleasyncresult.h"
26 #include "goutputstream.h"
27 #include "glibintl.h"
28
29
30 /**
31  * SECTION:gfilteroutputstream
32  * @short_description: Filter Output Stream
33  * @include: gio/gio.h
34  *
35  * Base class for output stream implementations that perform some
36  * kind of filtering operation on a base stream. Typical examples
37  * of filtering operations are character set conversion, compression
38  * and byte order flipping.
39  */
40
41 enum {
42   PROP_0,
43   PROP_BASE_STREAM,
44   PROP_CLOSE_BASE
45 };
46
47 static void     g_filter_output_stream_set_property (GObject      *object,
48                                                      guint         prop_id,
49                                                      const GValue *value,
50                                                      GParamSpec   *pspec);
51
52 static void     g_filter_output_stream_get_property (GObject    *object,
53                                                      guint       prop_id,
54                                                      GValue     *value,
55                                                      GParamSpec *pspec);
56 static void     g_filter_output_stream_dispose      (GObject *object);
57
58
59 static gssize   g_filter_output_stream_write        (GOutputStream *stream,
60                                                      const void    *buffer,
61                                                      gsize          count,
62                                                      GCancellable  *cancellable,
63                                                      GError       **error);
64 static gboolean g_filter_output_stream_flush        (GOutputStream    *stream,
65                                                      GCancellable  *cancellable,
66                                                      GError          **error);
67 static gboolean g_filter_output_stream_close        (GOutputStream  *stream,
68                                                      GCancellable   *cancellable,
69                                                      GError        **error);
70
71 G_DEFINE_ABSTRACT_TYPE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM)
72
73 #define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \
74   G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStreamPrivate)
75
76 typedef struct
77 {
78   gboolean close_base;
79 } GFilterOutputStreamPrivate;
80
81 static void
82 g_filter_output_stream_class_init (GFilterOutputStreamClass *klass)
83 {
84   GObjectClass *object_class;
85   GOutputStreamClass *ostream_class;
86
87   object_class = G_OBJECT_CLASS (klass);
88   object_class->get_property = g_filter_output_stream_get_property;
89   object_class->set_property = g_filter_output_stream_set_property;
90   object_class->dispose      = g_filter_output_stream_dispose;
91     
92   ostream_class = G_OUTPUT_STREAM_CLASS (klass);
93   ostream_class->write_fn = g_filter_output_stream_write;
94   ostream_class->flush = g_filter_output_stream_flush;
95   ostream_class->close_fn = g_filter_output_stream_close;
96
97   g_type_class_add_private (klass, sizeof (GFilterOutputStreamPrivate));
98
99   g_object_class_install_property (object_class,
100                                    PROP_BASE_STREAM,
101                                    g_param_spec_object ("base-stream",
102                                                          P_("The Filter Base Stream"),
103                                                          P_("The underlying base stream on which the io ops will be done."),
104                                                          G_TYPE_OUTPUT_STREAM,
105                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
106                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
107
108   g_object_class_install_property (object_class,
109                                    PROP_CLOSE_BASE,
110                                    g_param_spec_boolean ("close-base-stream",
111                                                          P_("Close Base Stream"),
112                                                          P_("If the base stream should be closed when the filter stream is closed."),
113                                                          TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
114                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
115 }
116
117 static void
118 g_filter_output_stream_set_property (GObject      *object,
119                                      guint         prop_id,
120                                      const GValue *value,
121                                      GParamSpec   *pspec)
122 {
123   GFilterOutputStream *filter_stream;
124   GObject *obj;
125
126   filter_stream = G_FILTER_OUTPUT_STREAM (object);
127
128   switch (prop_id) 
129     {
130     case PROP_BASE_STREAM:
131       obj = g_value_dup_object (value);
132       filter_stream->base_stream = G_OUTPUT_STREAM (obj);
133       break;
134
135     case PROP_CLOSE_BASE:
136       g_filter_output_stream_set_close_base_stream (filter_stream,
137                                                     g_value_get_boolean (value));
138       break;
139
140     default:
141       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
142       break;
143     }
144
145 }
146
147 static void
148 g_filter_output_stream_get_property (GObject    *object,
149                                      guint       prop_id,
150                                      GValue     *value,
151                                      GParamSpec *pspec)
152 {
153   GFilterOutputStream *filter_stream;
154
155   filter_stream = G_FILTER_OUTPUT_STREAM (object);
156
157   switch (prop_id)
158     {
159     case PROP_BASE_STREAM:
160       g_value_set_object (value, filter_stream->base_stream);
161       break;
162
163     case PROP_CLOSE_BASE:
164       g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base);
165       break;
166
167     default:
168       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169       break;
170     }
171
172 }
173
174 static void
175 g_filter_output_stream_dispose (GObject *object)
176 {
177   GFilterOutputStream *stream;
178
179   stream = G_FILTER_OUTPUT_STREAM (object);
180
181   G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object);
182   
183   if (stream->base_stream)
184     {
185       g_object_unref (stream->base_stream);
186       stream->base_stream = NULL;
187     }
188 }
189
190
191 static void
192 g_filter_output_stream_init (GFilterOutputStream *stream)
193 {
194 }
195
196 /**
197  * g_filter_output_stream_get_base_stream:
198  * @stream: a #GFilterOutputStream.
199  * 
200  * Gets the base stream for the filter stream.
201  *
202  * Returns: (transfer none): a #GOutputStream.
203  **/
204 GOutputStream *
205 g_filter_output_stream_get_base_stream (GFilterOutputStream *stream)
206 {
207   g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), NULL);
208
209   return stream->base_stream;
210 }
211
212 /**
213  * g_filter_output_stream_get_close_base_stream:
214  * @stream: a #GFilterOutputStream.
215  *
216  * Returns whether the base stream will be closed when @stream is
217  * closed.
218  *
219  * Return value: %TRUE if the base stream will be closed.
220  **/
221 gboolean
222 g_filter_output_stream_get_close_base_stream (GFilterOutputStream *stream)
223 {
224   g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), FALSE);
225
226   return GET_PRIVATE (stream)->close_base;
227 }
228
229 /**
230  * g_filter_output_stream_set_close_base_stream:
231  * @stream: a #GFilterOutputStream.
232  * @close_base: %TRUE to close the base stream.
233  *
234  * Sets whether the base stream will be closed when @stream is closed.
235  **/
236 void
237 g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream,
238                                               gboolean             close_base)
239 {
240   GFilterOutputStreamPrivate *priv;
241
242   g_return_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream));
243
244   close_base = !!close_base;
245
246   priv = GET_PRIVATE (stream);
247
248   if (priv->close_base != close_base)
249     {
250       priv->close_base = close_base;
251       g_object_notify (G_OBJECT (stream), "close-base-stream");
252     }
253 }
254
255 static gssize
256 g_filter_output_stream_write (GOutputStream  *stream,
257                               const void     *buffer,
258                               gsize           count,
259                               GCancellable   *cancellable,
260                               GError        **error)
261 {
262   GFilterOutputStream *filter_stream;
263   gssize nwritten;
264
265   filter_stream = G_FILTER_OUTPUT_STREAM (stream);
266
267   nwritten = g_output_stream_write (filter_stream->base_stream,
268                                     buffer,
269                                     count,
270                                     cancellable,
271                                     error);
272
273   return nwritten;
274 }
275
276 static gboolean
277 g_filter_output_stream_flush (GOutputStream  *stream,
278                               GCancellable   *cancellable,
279                               GError        **error)
280 {
281   GFilterOutputStream *filter_stream;
282   gboolean res;
283
284   filter_stream = G_FILTER_OUTPUT_STREAM (stream);
285
286   res = g_output_stream_flush (filter_stream->base_stream,
287                                cancellable,
288                                error);
289
290   return res;
291 }
292
293 static gboolean
294 g_filter_output_stream_close (GOutputStream  *stream,
295                               GCancellable   *cancellable,
296                               GError        **error)
297 {
298   gboolean res = TRUE;
299
300   if (GET_PRIVATE (stream)->close_base)
301     {
302       GFilterOutputStream *filter_stream;
303
304       filter_stream = G_FILTER_OUTPUT_STREAM (stream);
305
306       res = g_output_stream_close (filter_stream->base_stream,
307                                    cancellable,
308                                    error);
309     }
310
311   return res;
312 }