Merge remote branch 'gvdb/master'
[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 #include "gioalias.h"
30
31 /**
32  * SECTION:gfilterinputstream
33  * @short_description: Filter Input Stream
34  * @include: gio/gio.h
35  *
36  **/
37
38 enum {
39   PROP_0,
40   PROP_BASE_STREAM,
41   PROP_CLOSE_BASE
42 };
43
44 static void     g_filter_input_stream_set_property (GObject      *object,
45                                                     guint         prop_id,
46                                                     const GValue *value,
47                                                     GParamSpec   *pspec);
48
49 static void     g_filter_input_stream_get_property (GObject      *object,
50                                                     guint         prop_id,
51                                                     GValue       *value,
52                                                     GParamSpec   *pspec);
53 static void     g_filter_input_stream_finalize     (GObject *object);
54
55
56 static gssize   g_filter_input_stream_read         (GInputStream         *stream,
57                                                     void                 *buffer,
58                                                     gsize                 count,
59                                                     GCancellable         *cancellable,
60                                                     GError              **error);
61 static gssize   g_filter_input_stream_skip         (GInputStream         *stream,
62                                                     gsize                 count,
63                                                     GCancellable         *cancellable,
64                                                     GError              **error);
65 static gboolean g_filter_input_stream_close        (GInputStream         *stream,
66                                                     GCancellable         *cancellable,
67                                                     GError              **error);
68
69 G_DEFINE_TYPE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
70
71 #define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \
72   G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamPrivate)
73
74 typedef struct
75 {
76   gboolean close_base;
77   GAsyncReadyCallback outstanding_callback;
78   gpointer outstanding_user_data;
79 } GFilterInputStreamPrivate;
80
81 static void
82 g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
83 {
84   GObjectClass *object_class;
85   GInputStreamClass *istream_class;
86
87   object_class = G_OBJECT_CLASS (klass);
88   object_class->get_property = g_filter_input_stream_get_property;
89   object_class->set_property = g_filter_input_stream_set_property;
90   object_class->finalize     = g_filter_input_stream_finalize;
91
92   istream_class = G_INPUT_STREAM_CLASS (klass);
93   istream_class->read_fn  = g_filter_input_stream_read;
94   istream_class->skip  = g_filter_input_stream_skip;
95   istream_class->close_fn = g_filter_input_stream_close;
96
97   g_type_class_add_private (klass, sizeof (GFilterInputStreamPrivate));
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_INPUT_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_input_stream_set_property (GObject         *object,
119                                     guint            prop_id,
120                                     const GValue    *value,
121                                     GParamSpec      *pspec)
122 {
123   GFilterInputStream *filter_stream;
124   GObject *obj;
125
126   filter_stream = G_FILTER_INPUT_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_INPUT_STREAM (obj); 
133       break;
134
135     case PROP_CLOSE_BASE:
136       g_filter_input_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_input_stream_get_property (GObject    *object,
149                                     guint       prop_id,
150                                     GValue     *value,
151                                     GParamSpec *pspec)
152 {
153   GFilterInputStream *filter_stream;
154
155   filter_stream = G_FILTER_INPUT_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_input_stream_finalize (GObject *object)
176 {
177   GFilterInputStream *stream;
178
179   stream = G_FILTER_INPUT_STREAM (object);
180
181   g_object_unref (stream->base_stream);
182
183   G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object);
184 }
185
186 static void
187 g_filter_input_stream_init (GFilterInputStream *stream)
188 {
189
190 }
191
192 /**
193  * g_filter_input_stream_get_base_stream:
194  * @stream: a #GFilterInputStream.
195  * 
196  * Gets the base stream for the filter stream.
197  *
198  * Returns: a #GInputStream.
199  **/
200 GInputStream *
201 g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
202 {
203   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL);
204
205   return stream->base_stream;
206 }
207
208 /**
209  * g_filter_input_stream_get_close_base_stream:
210  * @stream: a #GFilterInputStream.
211  *
212  * Returns whether the base stream will be closed when @stream is
213  * closed.
214  *
215  * Return value: %TRUE if the base stream will be closed.
216  **/
217 gboolean
218 g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream)
219 {
220   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE);
221
222   return GET_PRIVATE (stream)->close_base;
223 }
224
225 /**
226  * g_filter_input_stream_set_close_base_stream:
227  * @stream: a #GFilterInputStream.
228  * @close_base: %TRUE to close the base stream.
229  *
230  * Sets whether the base stream will be closed when @stream is closed.
231  **/
232 void
233 g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
234                                              gboolean            close_base)
235 {
236   GFilterInputStreamPrivate *priv;
237
238   g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream));
239
240   close_base = !!close_base;
241  
242   priv = GET_PRIVATE (stream);
243
244   if (priv->close_base != close_base)
245     {
246       priv->close_base = close_base;
247       g_object_notify (G_OBJECT (stream), "close-base-stream");
248     }
249 }
250
251 static gssize
252 g_filter_input_stream_read (GInputStream  *stream,
253                             void          *buffer,
254                             gsize          count,
255                             GCancellable  *cancellable,
256                             GError       **error)
257 {
258   GFilterInputStream *filter_stream;
259   GInputStream       *base_stream;
260   gssize              nread;
261
262   filter_stream = G_FILTER_INPUT_STREAM (stream);
263   base_stream = filter_stream->base_stream;
264
265   nread = g_input_stream_read (base_stream,
266                                buffer,
267                                count,
268                                cancellable,
269                                error);
270
271   return nread;
272 }
273
274 static gssize
275 g_filter_input_stream_skip (GInputStream  *stream,
276                             gsize          count,
277                             GCancellable  *cancellable,
278                             GError       **error)
279 {
280   GFilterInputStream *filter_stream;
281   GInputStream       *base_stream;
282   gssize              nskipped;
283
284   filter_stream = G_FILTER_INPUT_STREAM (stream);
285   base_stream = filter_stream->base_stream;
286
287   nskipped = g_input_stream_skip (base_stream,
288                                   count,
289                                   cancellable,
290                                   error);
291   return nskipped;
292 }
293
294 static gboolean
295 g_filter_input_stream_close (GInputStream  *stream,
296                              GCancellable  *cancellable,
297                              GError       **error)
298 {
299   gboolean res = TRUE;
300
301   if (GET_PRIVATE (stream)->close_base)
302     {
303       GFilterInputStream *filter_stream;
304       GInputStream       *base_stream;
305
306       filter_stream = G_FILTER_INPUT_STREAM (stream);
307       base_stream = filter_stream->base_stream;
308
309       res = g_input_stream_close (base_stream,
310                                   cancellable,
311                                   error);
312     }
313
314   return res;
315 }
316
317 #define __G_FILTER_INPUT_STREAM_C__
318 #include "gioaliasdef.c"