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 | |
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 (oclass: object_class, |
93 | property_id: PROP_BASE_STREAM, |
94 | pspec: g_param_spec_object (name: "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 | flags: 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 (oclass: object_class, |
102 | property_id: PROP_CLOSE_BASE, |
103 | pspec: g_param_spec_boolean (name: "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, flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT | |
107 | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
108 | } |
109 | |
110 | static void |
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 (stream: filter_stream, |
130 | close_base: 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 |
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 (self: filter_stream); |
151 | |
152 | switch (prop_id) |
153 | { |
154 | case PROP_BASE_STREAM: |
155 | g_value_set_object (value, v_object: filter_stream->base_stream); |
156 | break; |
157 | |
158 | case PROP_CLOSE_BASE: |
159 | g_value_set_boolean (value, v_boolean: 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 |
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 (object: stream->base_stream); |
177 | |
178 | G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object); |
179 | } |
180 | |
181 | static void |
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 * |
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 |
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 (self: 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 |
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 (self: stream); |
241 | |
242 | if (priv->close_base != close_base) |
243 | { |
244 | priv->close_base = close_base; |
245 | g_object_notify (G_OBJECT (stream), property_name: "close-base-stream" ); |
246 | } |
247 | } |
248 | |
249 | static gssize |
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 (stream: base_stream, |
264 | buffer, |
265 | count, |
266 | cancellable, |
267 | error); |
268 | |
269 | return nread; |
270 | } |
271 | |
272 | static gssize |
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 (stream: base_stream, |
286 | count, |
287 | cancellable, |
288 | error); |
289 | return nskipped; |
290 | } |
291 | |
292 | static gboolean |
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 (self: filter_stream); |
299 | gboolean res = TRUE; |
300 | |
301 | if (priv->close_base) |
302 | { |
303 | res = g_input_stream_close (stream: filter_stream->base_stream, |
304 | cancellable, |
305 | error); |
306 | } |
307 | |
308 | return res; |
309 | } |
310 | |