Merge branch 'master' into gdbus-codegen
[platform/upstream/glib.git] / gio / gfilterinputstream.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 "gfilterinputstream.h"
25 #include "ginputstream.h"
26 #include "gsimpleasyncresult.h"
27 #include "glibintl.h"
28
29
30 /**
31  * SECTION:gfilterinputstream
32  * @short_description: Filter Input Stream
33  * @include: gio/gio.h
34  *
35  * Base class for input 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_input_stream_set_property (GObject      *object,
48                                                     guint         prop_id,
49                                                     const GValue *value,
50                                                     GParamSpec   *pspec);
51
52 static void     g_filter_input_stream_get_property (GObject      *object,
53                                                     guint         prop_id,
54                                                     GValue       *value,
55                                                     GParamSpec   *pspec);
56 static void     g_filter_input_stream_finalize     (GObject *object);
57
58
59 static gssize   g_filter_input_stream_read         (GInputStream         *stream,
60                                                     void                 *buffer,
61                                                     gsize                 count,
62                                                     GCancellable         *cancellable,
63                                                     GError              **error);
64 static gssize   g_filter_input_stream_skip         (GInputStream         *stream,
65                                                     gsize                 count,
66                                                     GCancellable         *cancellable,
67                                                     GError              **error);
68 static gboolean g_filter_input_stream_close        (GInputStream         *stream,
69                                                     GCancellable         *cancellable,
70                                                     GError              **error);
71
72 G_DEFINE_ABSTRACT_TYPE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
73
74 #define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \
75   G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamPrivate)
76
77 typedef struct
78 {
79   gboolean close_base;
80   GAsyncReadyCallback outstanding_callback;
81   gpointer outstanding_user_data;
82 } GFilterInputStreamPrivate;
83
84 static void
85 g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
86 {
87   GObjectClass *object_class;
88   GInputStreamClass *istream_class;
89
90   object_class = G_OBJECT_CLASS (klass);
91   object_class->get_property = g_filter_input_stream_get_property;
92   object_class->set_property = g_filter_input_stream_set_property;
93   object_class->finalize     = g_filter_input_stream_finalize;
94
95   istream_class = G_INPUT_STREAM_CLASS (klass);
96   istream_class->read_fn  = g_filter_input_stream_read;
97   istream_class->skip  = g_filter_input_stream_skip;
98   istream_class->close_fn = g_filter_input_stream_close;
99
100   g_type_class_add_private (klass, sizeof (GFilterInputStreamPrivate));
101
102   g_object_class_install_property (object_class,
103                                    PROP_BASE_STREAM,
104                                    g_param_spec_object ("base-stream",
105                                                          P_("The Filter Base Stream"),
106                                                          P_("The underlying base stream on which the io ops will be done."),
107                                                          G_TYPE_INPUT_STREAM,
108                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
109                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
110
111   g_object_class_install_property (object_class,
112                                    PROP_CLOSE_BASE,
113                                    g_param_spec_boolean ("close-base-stream",
114                                                          P_("Close Base Stream"),
115                                                          P_("If the base stream should be closed when the filter stream is closed."),
116                                                          TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
117                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
118 }
119
120 static void
121 g_filter_input_stream_set_property (GObject         *object,
122                                     guint            prop_id,
123                                     const GValue    *value,
124                                     GParamSpec      *pspec)
125 {
126   GFilterInputStream *filter_stream;
127   GObject *obj;
128
129   filter_stream = G_FILTER_INPUT_STREAM (object);
130
131   switch (prop_id) 
132     {
133     case PROP_BASE_STREAM:
134       obj = g_value_dup_object (value);
135       filter_stream->base_stream = G_INPUT_STREAM (obj); 
136       break;
137
138     case PROP_CLOSE_BASE:
139       g_filter_input_stream_set_close_base_stream (filter_stream,
140                                                    g_value_get_boolean (value));
141       break;
142
143     default:
144       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
145       break;
146     }
147
148 }
149
150 static void
151 g_filter_input_stream_get_property (GObject    *object,
152                                     guint       prop_id,
153                                     GValue     *value,
154                                     GParamSpec *pspec)
155 {
156   GFilterInputStream *filter_stream;
157
158   filter_stream = G_FILTER_INPUT_STREAM (object);
159
160   switch (prop_id)
161     {
162     case PROP_BASE_STREAM:
163       g_value_set_object (value, filter_stream->base_stream);
164       break;
165
166     case PROP_CLOSE_BASE:
167       g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base);
168       break;
169
170     default:
171       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
172       break;
173     }
174
175 }
176
177 static void
178 g_filter_input_stream_finalize (GObject *object)
179 {
180   GFilterInputStream *stream;
181
182   stream = G_FILTER_INPUT_STREAM (object);
183
184   g_object_unref (stream->base_stream);
185
186   G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object);
187 }
188
189 static void
190 g_filter_input_stream_init (GFilterInputStream *stream)
191 {
192
193 }
194
195 /**
196  * g_filter_input_stream_get_base_stream:
197  * @stream: a #GFilterInputStream.
198  * 
199  * Gets the base stream for the filter stream.
200  *
201  * Returns: (transfer none): a #GInputStream.
202  **/
203 GInputStream *
204 g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
205 {
206   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL);
207
208   return stream->base_stream;
209 }
210
211 /**
212  * g_filter_input_stream_get_close_base_stream:
213  * @stream: a #GFilterInputStream.
214  *
215  * Returns whether the base stream will be closed when @stream is
216  * closed.
217  *
218  * Return value: %TRUE if the base stream will be closed.
219  **/
220 gboolean
221 g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream)
222 {
223   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE);
224
225   return GET_PRIVATE (stream)->close_base;
226 }
227
228 /**
229  * g_filter_input_stream_set_close_base_stream:
230  * @stream: a #GFilterInputStream.
231  * @close_base: %TRUE to close the base stream.
232  *
233  * Sets whether the base stream will be closed when @stream is closed.
234  **/
235 void
236 g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
237                                              gboolean            close_base)
238 {
239   GFilterInputStreamPrivate *priv;
240
241   g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream));
242
243   close_base = !!close_base;
244  
245   priv = GET_PRIVATE (stream);
246
247   if (priv->close_base != close_base)
248     {
249       priv->close_base = close_base;
250       g_object_notify (G_OBJECT (stream), "close-base-stream");
251     }
252 }
253
254 static gssize
255 g_filter_input_stream_read (GInputStream  *stream,
256                             void          *buffer,
257                             gsize          count,
258                             GCancellable  *cancellable,
259                             GError       **error)
260 {
261   GFilterInputStream *filter_stream;
262   GInputStream       *base_stream;
263   gssize              nread;
264
265   filter_stream = G_FILTER_INPUT_STREAM (stream);
266   base_stream = filter_stream->base_stream;
267
268   nread = g_input_stream_read (base_stream,
269                                buffer,
270                                count,
271                                cancellable,
272                                error);
273
274   return nread;
275 }
276
277 static gssize
278 g_filter_input_stream_skip (GInputStream  *stream,
279                             gsize          count,
280                             GCancellable  *cancellable,
281                             GError       **error)
282 {
283   GFilterInputStream *filter_stream;
284   GInputStream       *base_stream;
285   gssize              nskipped;
286
287   filter_stream = G_FILTER_INPUT_STREAM (stream);
288   base_stream = filter_stream->base_stream;
289
290   nskipped = g_input_stream_skip (base_stream,
291                                   count,
292                                   cancellable,
293                                   error);
294   return nskipped;
295 }
296
297 static gboolean
298 g_filter_input_stream_close (GInputStream  *stream,
299                              GCancellable  *cancellable,
300                              GError       **error)
301 {
302   gboolean res = TRUE;
303
304   if (GET_PRIVATE (stream)->close_base)
305     {
306       GFilterInputStream *filter_stream;
307       GInputStream       *base_stream;
308
309       filter_stream = G_FILTER_INPUT_STREAM (stream);
310       base_stream = filter_stream->base_stream;
311
312       res = g_input_stream_close (base_stream,
313                                   cancellable,
314                                   error);
315     }
316
317   return res;
318 }