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 "gfilteroutputstream.h" |
23 | #include "goutputstream.h" |
24 | #include "glibintl.h" |
25 | |
26 | |
27 | /** |
28 | * SECTION:gfilteroutputstream |
29 | * @short_description: Filter Output Stream |
30 | * @include: gio/gio.h |
31 | * |
32 | * Base class for output 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_output_stream_set_property (GObject *object, |
45 | guint prop_id, |
46 | const GValue *value, |
47 | GParamSpec *pspec); |
48 | |
49 | static void g_filter_output_stream_get_property (GObject *object, |
50 | guint prop_id, |
51 | GValue *value, |
52 | GParamSpec *pspec); |
53 | static void g_filter_output_stream_dispose (GObject *object); |
54 | |
55 | |
56 | static gssize g_filter_output_stream_write (GOutputStream *stream, |
57 | const void *buffer, |
58 | gsize count, |
59 | GCancellable *cancellable, |
60 | GError **error); |
61 | static gboolean g_filter_output_stream_flush (GOutputStream *stream, |
62 | GCancellable *cancellable, |
63 | GError **error); |
64 | static gboolean g_filter_output_stream_close (GOutputStream *stream, |
65 | GCancellable *cancellable, |
66 | GError **error); |
67 | |
68 | typedef struct |
69 | { |
70 | gboolean close_base; |
71 | } GFilterOutputStreamPrivate; |
72 | |
73 | G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM) |
74 | |
75 | static void |
76 | g_filter_output_stream_class_init (GFilterOutputStreamClass *klass) |
77 | { |
78 | GObjectClass *object_class; |
79 | GOutputStreamClass *ostream_class; |
80 | |
81 | object_class = G_OBJECT_CLASS (klass); |
82 | object_class->get_property = g_filter_output_stream_get_property; |
83 | object_class->set_property = g_filter_output_stream_set_property; |
84 | object_class->dispose = g_filter_output_stream_dispose; |
85 | |
86 | ostream_class = G_OUTPUT_STREAM_CLASS (klass); |
87 | ostream_class->write_fn = g_filter_output_stream_write; |
88 | ostream_class->flush = g_filter_output_stream_flush; |
89 | ostream_class->close_fn = g_filter_output_stream_close; |
90 | |
91 | g_object_class_install_property (oclass: object_class, |
92 | property_id: PROP_BASE_STREAM, |
93 | pspec: g_param_spec_object (name: "base-stream" , |
94 | P_("The Filter Base Stream" ), |
95 | P_("The underlying base stream on which the io ops will be done." ), |
96 | G_TYPE_OUTPUT_STREAM, |
97 | flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | |
98 | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
99 | |
100 | g_object_class_install_property (oclass: object_class, |
101 | property_id: PROP_CLOSE_BASE, |
102 | pspec: g_param_spec_boolean (name: "close-base-stream" , |
103 | P_("Close Base Stream" ), |
104 | P_("If the base stream should be closed when the filter stream is closed." ), |
105 | TRUE, flags: G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | |
106 | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); |
107 | } |
108 | |
109 | static void |
110 | g_filter_output_stream_set_property (GObject *object, |
111 | guint prop_id, |
112 | const GValue *value, |
113 | GParamSpec *pspec) |
114 | { |
115 | GFilterOutputStream *filter_stream; |
116 | GObject *obj; |
117 | |
118 | filter_stream = G_FILTER_OUTPUT_STREAM (object); |
119 | |
120 | switch (prop_id) |
121 | { |
122 | case PROP_BASE_STREAM: |
123 | obj = g_value_dup_object (value); |
124 | filter_stream->base_stream = G_OUTPUT_STREAM (obj); |
125 | break; |
126 | |
127 | case PROP_CLOSE_BASE: |
128 | g_filter_output_stream_set_close_base_stream (stream: filter_stream, |
129 | close_base: g_value_get_boolean (value)); |
130 | break; |
131 | |
132 | default: |
133 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
134 | break; |
135 | } |
136 | |
137 | } |
138 | |
139 | static void |
140 | g_filter_output_stream_get_property (GObject *object, |
141 | guint prop_id, |
142 | GValue *value, |
143 | GParamSpec *pspec) |
144 | { |
145 | GFilterOutputStream *filter_stream; |
146 | GFilterOutputStreamPrivate *priv; |
147 | |
148 | filter_stream = G_FILTER_OUTPUT_STREAM (object); |
149 | priv = g_filter_output_stream_get_instance_private (self: filter_stream); |
150 | |
151 | switch (prop_id) |
152 | { |
153 | case PROP_BASE_STREAM: |
154 | g_value_set_object (value, v_object: filter_stream->base_stream); |
155 | break; |
156 | |
157 | case PROP_CLOSE_BASE: |
158 | g_value_set_boolean (value, v_boolean: priv->close_base); |
159 | break; |
160 | |
161 | default: |
162 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
163 | break; |
164 | } |
165 | |
166 | } |
167 | |
168 | static void |
169 | g_filter_output_stream_dispose (GObject *object) |
170 | { |
171 | GFilterOutputStream *stream; |
172 | |
173 | stream = G_FILTER_OUTPUT_STREAM (object); |
174 | |
175 | G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object); |
176 | |
177 | if (stream->base_stream) |
178 | { |
179 | g_object_unref (object: stream->base_stream); |
180 | stream->base_stream = NULL; |
181 | } |
182 | } |
183 | |
184 | |
185 | static void |
186 | g_filter_output_stream_init (GFilterOutputStream *stream) |
187 | { |
188 | } |
189 | |
190 | /** |
191 | * g_filter_output_stream_get_base_stream: |
192 | * @stream: a #GFilterOutputStream. |
193 | * |
194 | * Gets the base stream for the filter stream. |
195 | * |
196 | * Returns: (transfer none): a #GOutputStream. |
197 | **/ |
198 | GOutputStream * |
199 | g_filter_output_stream_get_base_stream (GFilterOutputStream *stream) |
200 | { |
201 | g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), NULL); |
202 | |
203 | return stream->base_stream; |
204 | } |
205 | |
206 | /** |
207 | * g_filter_output_stream_get_close_base_stream: |
208 | * @stream: a #GFilterOutputStream. |
209 | * |
210 | * Returns whether the base stream will be closed when @stream is |
211 | * closed. |
212 | * |
213 | * Returns: %TRUE if the base stream will be closed. |
214 | **/ |
215 | gboolean |
216 | g_filter_output_stream_get_close_base_stream (GFilterOutputStream *stream) |
217 | { |
218 | GFilterOutputStreamPrivate *priv; |
219 | |
220 | g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), FALSE); |
221 | |
222 | priv = g_filter_output_stream_get_instance_private (self: stream); |
223 | |
224 | return priv->close_base; |
225 | } |
226 | |
227 | /** |
228 | * g_filter_output_stream_set_close_base_stream: |
229 | * @stream: a #GFilterOutputStream. |
230 | * @close_base: %TRUE to close the base stream. |
231 | * |
232 | * Sets whether the base stream will be closed when @stream is closed. |
233 | **/ |
234 | void |
235 | g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream, |
236 | gboolean close_base) |
237 | { |
238 | GFilterOutputStreamPrivate *priv; |
239 | |
240 | g_return_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream)); |
241 | |
242 | close_base = !!close_base; |
243 | |
244 | priv = g_filter_output_stream_get_instance_private (self: stream); |
245 | |
246 | if (priv->close_base != close_base) |
247 | { |
248 | priv->close_base = close_base; |
249 | g_object_notify (G_OBJECT (stream), property_name: "close-base-stream" ); |
250 | } |
251 | } |
252 | |
253 | static gssize |
254 | g_filter_output_stream_write (GOutputStream *stream, |
255 | const void *buffer, |
256 | gsize count, |
257 | GCancellable *cancellable, |
258 | GError **error) |
259 | { |
260 | GFilterOutputStream *filter_stream; |
261 | gssize nwritten; |
262 | |
263 | filter_stream = G_FILTER_OUTPUT_STREAM (stream); |
264 | |
265 | nwritten = g_output_stream_write (stream: filter_stream->base_stream, |
266 | buffer, |
267 | count, |
268 | cancellable, |
269 | error); |
270 | |
271 | return nwritten; |
272 | } |
273 | |
274 | static gboolean |
275 | g_filter_output_stream_flush (GOutputStream *stream, |
276 | GCancellable *cancellable, |
277 | GError **error) |
278 | { |
279 | GFilterOutputStream *filter_stream; |
280 | gboolean res; |
281 | |
282 | filter_stream = G_FILTER_OUTPUT_STREAM (stream); |
283 | |
284 | res = g_output_stream_flush (stream: filter_stream->base_stream, |
285 | cancellable, |
286 | error); |
287 | |
288 | return res; |
289 | } |
290 | |
291 | static gboolean |
292 | g_filter_output_stream_close (GOutputStream *stream, |
293 | GCancellable *cancellable, |
294 | GError **error) |
295 | { |
296 | GFilterOutputStream *filter_stream = G_FILTER_OUTPUT_STREAM (stream); |
297 | GFilterOutputStreamPrivate *priv = g_filter_output_stream_get_instance_private (self: filter_stream); |
298 | gboolean res = TRUE; |
299 | |
300 | if (priv->close_base) |
301 | { |
302 | res = g_output_stream_close (stream: filter_stream->base_stream, |
303 | cancellable, |
304 | error); |
305 | } |
306 | |
307 | return res; |
308 | } |
309 | |