Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Christian Kellner <gicmo@gnome.org>
21 : : */
22 : :
23 : : #include "config.h"
24 : : #include "gfilterinputstream.h"
25 : : #include "ginputstream.h"
26 : : #include "glibintl.h"
27 : :
28 : :
29 : : /**
30 : : * GFilterInputStream:
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 : 570857 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM)
75 : :
76 : : static void
77 : 110 : g_filter_input_stream_class_init (GFilterInputStreamClass *klass)
78 : : {
79 : : GObjectClass *object_class;
80 : : GInputStreamClass *istream_class;
81 : :
82 : 110 : object_class = G_OBJECT_CLASS (klass);
83 : 110 : object_class->get_property = g_filter_input_stream_get_property;
84 : 110 : object_class->set_property = g_filter_input_stream_set_property;
85 : 110 : object_class->finalize = g_filter_input_stream_finalize;
86 : :
87 : 110 : istream_class = G_INPUT_STREAM_CLASS (klass);
88 : 110 : istream_class->read_fn = g_filter_input_stream_read;
89 : 110 : istream_class->skip = g_filter_input_stream_skip;
90 : 110 : istream_class->close_fn = g_filter_input_stream_close;
91 : :
92 : : /**
93 : : * GFilterInputStream:base-stream:
94 : : *
95 : : * The underlying base stream on which the I/O ops will be done.
96 : : */
97 : 110 : g_object_class_install_property (object_class,
98 : : PROP_BASE_STREAM,
99 : : g_param_spec_object ("base-stream", NULL, NULL,
100 : : G_TYPE_INPUT_STREAM,
101 : : G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
102 : : G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
103 : :
104 : : /**
105 : : * GFilterInputStream:close-base-stream:
106 : : *
107 : : * Whether the base stream should be closed when the filter stream is closed.
108 : : */
109 : 110 : g_object_class_install_property (object_class,
110 : : PROP_CLOSE_BASE,
111 : : g_param_spec_boolean ("close-base-stream", NULL, NULL,
112 : : TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
113 : : G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
114 : 110 : }
115 : :
116 : : static void
117 : 3830 : g_filter_input_stream_set_property (GObject *object,
118 : : guint prop_id,
119 : : const GValue *value,
120 : : GParamSpec *pspec)
121 : : {
122 : : GFilterInputStream *filter_stream;
123 : : GObject *obj;
124 : :
125 : 3830 : filter_stream = G_FILTER_INPUT_STREAM (object);
126 : :
127 : 3830 : switch (prop_id)
128 : : {
129 : 1915 : case PROP_BASE_STREAM:
130 : 1915 : obj = g_value_dup_object (value);
131 : 1915 : filter_stream->base_stream = G_INPUT_STREAM (obj);
132 : 1915 : break;
133 : :
134 : 1915 : case PROP_CLOSE_BASE:
135 : 1915 : g_filter_input_stream_set_close_base_stream (filter_stream,
136 : : g_value_get_boolean (value));
137 : 1915 : break;
138 : :
139 : 0 : default:
140 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
141 : 0 : break;
142 : : }
143 : :
144 : 3830 : }
145 : :
146 : : static void
147 : 2 : g_filter_input_stream_get_property (GObject *object,
148 : : guint prop_id,
149 : : GValue *value,
150 : : GParamSpec *pspec)
151 : : {
152 : : GFilterInputStream *filter_stream;
153 : : GFilterInputStreamPrivate *priv;
154 : :
155 : 2 : filter_stream = G_FILTER_INPUT_STREAM (object);
156 : 2 : priv = g_filter_input_stream_get_instance_private (filter_stream);
157 : :
158 : 2 : switch (prop_id)
159 : : {
160 : 1 : case PROP_BASE_STREAM:
161 : 1 : g_value_set_object (value, filter_stream->base_stream);
162 : 1 : break;
163 : :
164 : 1 : case PROP_CLOSE_BASE:
165 : 1 : g_value_set_boolean (value, priv->close_base);
166 : 1 : break;
167 : :
168 : 0 : default:
169 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 : 0 : break;
171 : : }
172 : :
173 : 2 : }
174 : :
175 : : static void
176 : 1915 : g_filter_input_stream_finalize (GObject *object)
177 : : {
178 : : GFilterInputStream *stream;
179 : :
180 : 1915 : stream = G_FILTER_INPUT_STREAM (object);
181 : :
182 : 1915 : g_object_unref (stream->base_stream);
183 : :
184 : 1915 : G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object);
185 : 1915 : }
186 : :
187 : : static void
188 : 1915 : g_filter_input_stream_init (GFilterInputStream *stream)
189 : : {
190 : 1915 : }
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: (transfer none): a #GInputStream.
199 : : **/
200 : : GInputStream *
201 : 4 : g_filter_input_stream_get_base_stream (GFilterInputStream *stream)
202 : : {
203 : 4 : g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL);
204 : :
205 : 4 : 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 : : * Returns: %TRUE if the base stream will be closed.
216 : : **/
217 : : gboolean
218 : 1 : g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream)
219 : : {
220 : : GFilterInputStreamPrivate *priv;
221 : :
222 : 1 : g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE);
223 : :
224 : 1 : priv = g_filter_input_stream_get_instance_private (stream);
225 : :
226 : 1 : return priv->close_base;
227 : : }
228 : :
229 : : /**
230 : : * g_filter_input_stream_set_close_base_stream:
231 : : * @stream: a #GFilterInputStream.
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 : 3718 : g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream,
238 : : gboolean close_base)
239 : : {
240 : : GFilterInputStreamPrivate *priv;
241 : :
242 : 3718 : g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream));
243 : :
244 : 3718 : close_base = !!close_base;
245 : :
246 : 3718 : priv = g_filter_input_stream_get_instance_private (stream);
247 : :
248 : 3718 : if (priv->close_base != close_base)
249 : : {
250 : 3716 : priv->close_base = close_base;
251 : 3716 : g_object_notify (G_OBJECT (stream), "close-base-stream");
252 : : }
253 : : }
254 : :
255 : : static gssize
256 : 4 : g_filter_input_stream_read (GInputStream *stream,
257 : : void *buffer,
258 : : gsize count,
259 : : GCancellable *cancellable,
260 : : GError **error)
261 : : {
262 : : GFilterInputStream *filter_stream;
263 : : GInputStream *base_stream;
264 : : gssize nread;
265 : :
266 : 4 : filter_stream = G_FILTER_INPUT_STREAM (stream);
267 : 4 : base_stream = filter_stream->base_stream;
268 : :
269 : 4 : nread = g_input_stream_read (base_stream,
270 : : buffer,
271 : : count,
272 : : cancellable,
273 : : error);
274 : :
275 : 4 : return nread;
276 : : }
277 : :
278 : : static gssize
279 : 2 : g_filter_input_stream_skip (GInputStream *stream,
280 : : gsize count,
281 : : GCancellable *cancellable,
282 : : GError **error)
283 : : {
284 : : GFilterInputStream *filter_stream;
285 : : GInputStream *base_stream;
286 : : gssize nskipped;
287 : :
288 : 2 : filter_stream = G_FILTER_INPUT_STREAM (stream);
289 : 2 : base_stream = filter_stream->base_stream;
290 : :
291 : 2 : nskipped = g_input_stream_skip (base_stream,
292 : : count,
293 : : cancellable,
294 : : error);
295 : 2 : return nskipped;
296 : : }
297 : :
298 : : static gboolean
299 : 1915 : g_filter_input_stream_close (GInputStream *stream,
300 : : GCancellable *cancellable,
301 : : GError **error)
302 : : {
303 : 1915 : GFilterInputStream *filter_stream = G_FILTER_INPUT_STREAM (stream);
304 : 1915 : GFilterInputStreamPrivate *priv = g_filter_input_stream_get_instance_private (filter_stream);
305 : 1915 : gboolean res = TRUE;
306 : :
307 : 1915 : if (priv->close_base)
308 : : {
309 : 110 : res = g_input_stream_close (filter_stream->base_stream,
310 : : cancellable,
311 : : error);
312 : : }
313 : :
314 : 1915 : return res;
315 : : }
|