• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.1 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, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Christian Kellner <gicmo@gnome.org>
19  */
20 
21 #include "config.h"
22 #include "gfilterinputstream.h"
23 #include "ginputstream.h"
24 #include "glibintl.h"
25 
26 
27 /**
28  * SECTION:gfilterinputstream
29  * @short_description: Filter Input Stream
30  * @include: gio/gio.h
31  *
32  * Base class for input stream implementations that perform some
33  * kind of filtering operation on a base stream. Typical examples
34  * of filtering operations are character set conversion, compression
35  * and byte order flipping.
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 typedef struct
70 {
71   gboolean close_base;
72 } GFilterInputStreamPrivate;
73 
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(GFilterInputStream,g_filter_input_stream,G_TYPE_INPUT_STREAM)74 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
75 
76 static void
77 g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
78 {
79   GObjectClass *object_class;
80   GInputStreamClass *istream_class;
81 
82   object_class = G_OBJECT_CLASS (klass);
83   object_class->get_property = g_filter_input_stream_get_property;
84   object_class->set_property = g_filter_input_stream_set_property;
85   object_class->finalize     = g_filter_input_stream_finalize;
86 
87   istream_class = G_INPUT_STREAM_CLASS (klass);
88   istream_class->read_fn  = g_filter_input_stream_read;
89   istream_class->skip  = g_filter_input_stream_skip;
90   istream_class->close_fn = g_filter_input_stream_close;
91 
92   g_object_class_install_property (object_class,
93                                    PROP_BASE_STREAM,
94                                    g_param_spec_object ("base-stream",
95                                                          P_("The Filter Base Stream"),
96                                                          P_("The underlying base stream on which the io ops will be done."),
97                                                          G_TYPE_INPUT_STREAM,
98                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
99                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
100 
101   g_object_class_install_property (object_class,
102                                    PROP_CLOSE_BASE,
103                                    g_param_spec_boolean ("close-base-stream",
104                                                          P_("Close Base Stream"),
105                                                          P_("If the base stream should be closed when the filter stream is closed."),
106                                                          TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
107                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
108 }
109 
110 static void
g_filter_input_stream_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)111 g_filter_input_stream_set_property (GObject         *object,
112                                     guint            prop_id,
113                                     const GValue    *value,
114                                     GParamSpec      *pspec)
115 {
116   GFilterInputStream *filter_stream;
117   GObject *obj;
118 
119   filter_stream = G_FILTER_INPUT_STREAM (object);
120 
121   switch (prop_id)
122     {
123     case PROP_BASE_STREAM:
124       obj = g_value_dup_object (value);
125       filter_stream->base_stream = G_INPUT_STREAM (obj);
126       break;
127 
128     case PROP_CLOSE_BASE:
129       g_filter_input_stream_set_close_base_stream (filter_stream,
130                                                    g_value_get_boolean (value));
131       break;
132 
133     default:
134       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
135       break;
136     }
137 
138 }
139 
140 static void
g_filter_input_stream_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)141 g_filter_input_stream_get_property (GObject    *object,
142                                     guint       prop_id,
143                                     GValue     *value,
144                                     GParamSpec *pspec)
145 {
146   GFilterInputStream *filter_stream;
147   GFilterInputStreamPrivate *priv;
148 
149   filter_stream = G_FILTER_INPUT_STREAM (object);
150   priv = g_filter_input_stream_get_instance_private (filter_stream);
151 
152   switch (prop_id)
153     {
154     case PROP_BASE_STREAM:
155       g_value_set_object (value, filter_stream->base_stream);
156       break;
157 
158     case PROP_CLOSE_BASE:
159       g_value_set_boolean (value, priv->close_base);
160       break;
161 
162     default:
163       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
164       break;
165     }
166 
167 }
168 
169 static void
g_filter_input_stream_finalize(GObject * object)170 g_filter_input_stream_finalize (GObject *object)
171 {
172   GFilterInputStream *stream;
173 
174   stream = G_FILTER_INPUT_STREAM (object);
175 
176   g_object_unref (stream->base_stream);
177 
178   G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object);
179 }
180 
181 static void
g_filter_input_stream_init(GFilterInputStream * stream)182 g_filter_input_stream_init (GFilterInputStream *stream)
183 {
184 }
185 
186 /**
187  * g_filter_input_stream_get_base_stream:
188  * @stream: a #GFilterInputStream.
189  *
190  * Gets the base stream for the filter stream.
191  *
192  * Returns: (transfer none): a #GInputStream.
193  **/
194 GInputStream *
g_filter_input_stream_get_base_stream(GFilterInputStream * stream)195 g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
196 {
197   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL);
198 
199   return stream->base_stream;
200 }
201 
202 /**
203  * g_filter_input_stream_get_close_base_stream:
204  * @stream: a #GFilterInputStream.
205  *
206  * Returns whether the base stream will be closed when @stream is
207  * closed.
208  *
209  * Returns: %TRUE if the base stream will be closed.
210  **/
211 gboolean
g_filter_input_stream_get_close_base_stream(GFilterInputStream * stream)212 g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream)
213 {
214   GFilterInputStreamPrivate *priv;
215 
216   g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE);
217 
218   priv = g_filter_input_stream_get_instance_private (stream);
219 
220   return priv->close_base;
221 }
222 
223 /**
224  * g_filter_input_stream_set_close_base_stream:
225  * @stream: a #GFilterInputStream.
226  * @close_base: %TRUE to close the base stream.
227  *
228  * Sets whether the base stream will be closed when @stream is closed.
229  **/
230 void
g_filter_input_stream_set_close_base_stream(GFilterInputStream * stream,gboolean close_base)231 g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
232                                              gboolean            close_base)
233 {
234   GFilterInputStreamPrivate *priv;
235 
236   g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream));
237 
238   close_base = !!close_base;
239 
240   priv = g_filter_input_stream_get_instance_private (stream);
241 
242   if (priv->close_base != close_base)
243     {
244       priv->close_base = close_base;
245       g_object_notify (G_OBJECT (stream), "close-base-stream");
246     }
247 }
248 
249 static gssize
g_filter_input_stream_read(GInputStream * stream,void * buffer,gsize count,GCancellable * cancellable,GError ** error)250 g_filter_input_stream_read (GInputStream  *stream,
251                             void          *buffer,
252                             gsize          count,
253                             GCancellable  *cancellable,
254                             GError       **error)
255 {
256   GFilterInputStream *filter_stream;
257   GInputStream       *base_stream;
258   gssize              nread;
259 
260   filter_stream = G_FILTER_INPUT_STREAM (stream);
261   base_stream = filter_stream->base_stream;
262 
263   nread = g_input_stream_read (base_stream,
264                                buffer,
265                                count,
266                                cancellable,
267                                error);
268 
269   return nread;
270 }
271 
272 static gssize
g_filter_input_stream_skip(GInputStream * stream,gsize count,GCancellable * cancellable,GError ** error)273 g_filter_input_stream_skip (GInputStream  *stream,
274                             gsize          count,
275                             GCancellable  *cancellable,
276                             GError       **error)
277 {
278   GFilterInputStream *filter_stream;
279   GInputStream       *base_stream;
280   gssize              nskipped;
281 
282   filter_stream = G_FILTER_INPUT_STREAM (stream);
283   base_stream = filter_stream->base_stream;
284 
285   nskipped = g_input_stream_skip (base_stream,
286                                   count,
287                                   cancellable,
288                                   error);
289   return nskipped;
290 }
291 
292 static gboolean
g_filter_input_stream_close(GInputStream * stream,GCancellable * cancellable,GError ** error)293 g_filter_input_stream_close (GInputStream  *stream,
294                              GCancellable  *cancellable,
295                              GError       **error)
296 {
297   GFilterInputStream *filter_stream = G_FILTER_INPUT_STREAM (stream);
298   GFilterInputStreamPrivate *priv = g_filter_input_stream_get_instance_private (filter_stream);
299   gboolean res = TRUE;
300 
301   if (priv->close_base)
302     {
303       res = g_input_stream_close (filter_stream->base_stream,
304                                   cancellable,
305                                   error);
306     }
307 
308   return res;
309 }
310