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 (at) gnome.org> 21 */ 22 23 #include "config.h" 24 #include "gfilteroutputstream.h" 25 #include "gsimpleasyncresult.h" 26 #include "goutputstream.h" 27 #include "glibintl.h" 28 29 #include "gioalias.h" 30 31 /** 32 * SECTION:gfilteroutputstream 33 * @short_description: Filter Output 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_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 static void g_filter_output_stream_write_async (GOutputStream *stream, 68 const void *buffer, 69 gsize count, 70 int io_priority, 71 GCancellable *cancellable, 72 GAsyncReadyCallback callback, 73 gpointer data); 74 static gssize g_filter_output_stream_write_finish (GOutputStream *stream, 75 GAsyncResult *result, 76 GError **error); 77 static void g_filter_output_stream_flush_async (GOutputStream *stream, 78 int io_priority, 79 GCancellable *cancellable, 80 GAsyncReadyCallback callback, 81 gpointer data); 82 static gboolean g_filter_output_stream_flush_finish (GOutputStream *stream, 83 GAsyncResult *result, 84 GError **error); 85 static void g_filter_output_stream_close_async (GOutputStream *stream, 86 int io_priority, 87 GCancellable *cancellable, 88 GAsyncReadyCallback callback, 89 gpointer data); 90 static gboolean g_filter_output_stream_close_finish (GOutputStream *stream, 91 GAsyncResult *result, 92 GError **error); 93 94 95 96 G_DEFINE_TYPE (GFilterOutputStream, g_filter_output_stream, G_TYPE_OUTPUT_STREAM) 97 98 #define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \ 99 G_TYPE_FILTER_OUTPUT_STREAM, GFilterOutputStreamPrivate) 100 101 typedef struct 102 { 103 gboolean close_base; 104 } GFilterOutputStreamPrivate; 105 106 static void 107 g_filter_output_stream_class_init (GFilterOutputStreamClass *klass) 108 { 109 GObjectClass *object_class; 110 GOutputStreamClass *ostream_class; 111 112 object_class = G_OBJECT_CLASS (klass); 113 object_class->get_property = g_filter_output_stream_get_property; 114 object_class->set_property = g_filter_output_stream_set_property; 115 object_class->dispose = g_filter_output_stream_dispose; 116 117 ostream_class = G_OUTPUT_STREAM_CLASS (klass); 118 ostream_class->write_fn = g_filter_output_stream_write; 119 ostream_class->flush = g_filter_output_stream_flush; 120 ostream_class->close_fn = g_filter_output_stream_close; 121 ostream_class->write_async = g_filter_output_stream_write_async; 122 ostream_class->write_finish = g_filter_output_stream_write_finish; 123 ostream_class->flush_async = g_filter_output_stream_flush_async; 124 ostream_class->flush_finish = g_filter_output_stream_flush_finish; 125 ostream_class->close_async = g_filter_output_stream_close_async; 126 ostream_class->close_finish = g_filter_output_stream_close_finish; 127 128 g_type_class_add_private (klass, sizeof (GFilterOutputStreamPrivate)); 129 130 g_object_class_install_property (object_class, 131 PROP_BASE_STREAM, 132 g_param_spec_object ("base-stream", 133 P_("The Filter Base Stream"), 134 P_("The underlying base stream on which the io ops will be done."), 135 G_TYPE_OUTPUT_STREAM, 136 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 137 G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); 138 139 g_object_class_install_property (object_class, 140 PROP_CLOSE_BASE, 141 g_param_spec_boolean ("close-base-stream", 142 P_("Close Base Stream"), 143 P_("If the base stream should be closed when the filter stream is closed."), 144 TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 145 G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); 146 } 147 148 static void 149 g_filter_output_stream_set_property (GObject *object, 150 guint prop_id, 151 const GValue *value, 152 GParamSpec *pspec) 153 { 154 GFilterOutputStream *filter_stream; 155 GObject *obj; 156 157 filter_stream = G_FILTER_OUTPUT_STREAM (object); 158 159 switch (prop_id) 160 { 161 case PROP_BASE_STREAM: 162 obj = g_value_dup_object (value); 163 filter_stream->base_stream = G_OUTPUT_STREAM (obj); 164 break; 165 166 case PROP_CLOSE_BASE: 167 g_filter_output_stream_set_close_base_stream (filter_stream, 168 g_value_get_boolean (value)); 169 break; 170 171 default: 172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 173 break; 174 } 175 176 } 177 178 static void 179 g_filter_output_stream_get_property (GObject *object, 180 guint prop_id, 181 GValue *value, 182 GParamSpec *pspec) 183 { 184 GFilterOutputStream *filter_stream; 185 186 filter_stream = G_FILTER_OUTPUT_STREAM (object); 187 188 switch (prop_id) 189 { 190 case PROP_BASE_STREAM: 191 g_value_set_object (value, filter_stream->base_stream); 192 break; 193 194 case PROP_CLOSE_BASE: 195 g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base); 196 break; 197 198 default: 199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 200 break; 201 } 202 203 } 204 205 static void 206 g_filter_output_stream_dispose (GObject *object) 207 { 208 GFilterOutputStream *stream; 209 210 stream = G_FILTER_OUTPUT_STREAM (object); 211 212 G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object); 213 214 if (stream->base_stream) 215 { 216 g_object_unref (stream->base_stream); 217 stream->base_stream = NULL; 218 } 219 } 220 221 222 static void 223 g_filter_output_stream_init (GFilterOutputStream *stream) 224 { 225 } 226 227 /** 228 * g_filter_output_stream_get_base_stream: 229 * @stream: a #GFilterOutputStream. 230 * 231 * Gets the base stream for the filter stream. 232 * 233 * Returns: a #GOutputStream. 234 **/ 235 GOutputStream * 236 g_filter_output_stream_get_base_stream (GFilterOutputStream *stream) 237 { 238 g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), NULL); 239 240 return stream->base_stream; 241 } 242 243 /** 244 * g_filter_output_stream_get_close_base_stream: 245 * @stream: a #GFilterOutputStream. 246 * 247 * Returns whether the base stream will be closed when @stream is 248 * closed. 249 * 250 * Return value: %TRUE if the base stream will be closed. 251 **/ 252 gboolean 253 g_filter_output_stream_get_close_base_stream (GFilterOutputStream *stream) 254 { 255 g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), FALSE); 256 257 return GET_PRIVATE (stream)->close_base; 258 } 259 260 /** 261 * g_filter_output_stream_set_close_base_stream: 262 * @stream: a #GFilterOutputStream. 263 * @close_base: %TRUE to close the base stream. 264 * 265 * Sets whether the base stream will be closed when @stream is closed. 266 **/ 267 void 268 g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream, 269 gboolean close_base) 270 { 271 GFilterOutputStreamPrivate *priv; 272 273 g_return_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream)); 274 275 close_base = !!close_base; 276 277 priv = GET_PRIVATE (stream); 278 279 if (priv->close_base != close_base) 280 { 281 priv->close_base = close_base; 282 g_object_notify (G_OBJECT (stream), "close-base-stream"); 283 } 284 } 285 286 static gssize 287 g_filter_output_stream_write (GOutputStream *stream, 288 const void *buffer, 289 gsize count, 290 GCancellable *cancellable, 291 GError **error) 292 { 293 GFilterOutputStream *filter_stream; 294 gssize nwritten; 295 296 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 297 298 nwritten = g_output_stream_write (filter_stream->base_stream, 299 buffer, 300 count, 301 cancellable, 302 error); 303 304 return nwritten; 305 } 306 307 static gboolean 308 g_filter_output_stream_flush (GOutputStream *stream, 309 GCancellable *cancellable, 310 GError **error) 311 { 312 GFilterOutputStream *filter_stream; 313 gboolean res; 314 315 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 316 317 res = g_output_stream_flush (filter_stream->base_stream, 318 cancellable, 319 error); 320 321 return res; 322 } 323 324 static gboolean 325 g_filter_output_stream_close (GOutputStream *stream, 326 GCancellable *cancellable, 327 GError **error) 328 { 329 gboolean res = TRUE; 330 331 if (GET_PRIVATE (stream)->close_base) 332 { 333 GFilterOutputStream *filter_stream; 334 335 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 336 337 res = g_output_stream_close (filter_stream->base_stream, 338 cancellable, 339 error); 340 } 341 342 return res; 343 } 344 345 static void 346 g_filter_output_stream_write_async (GOutputStream *stream, 347 const void *buffer, 348 gsize count, 349 int io_priority, 350 GCancellable *cancellable, 351 GAsyncReadyCallback callback, 352 gpointer data) 353 { 354 GFilterOutputStream *filter_stream; 355 356 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 357 358 g_output_stream_write_async (filter_stream->base_stream, 359 buffer, 360 count, 361 io_priority, 362 cancellable, 363 callback, 364 data); 365 366 } 367 368 static gssize 369 g_filter_output_stream_write_finish (GOutputStream *stream, 370 GAsyncResult *result, 371 GError **error) 372 { 373 GFilterOutputStream *filter_stream; 374 gssize nwritten; 375 376 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 377 378 nwritten = g_output_stream_write_finish (filter_stream->base_stream, 379 result, 380 error); 381 382 return nwritten; 383 } 384 385 static void 386 g_filter_output_stream_flush_async (GOutputStream *stream, 387 int io_priority, 388 GCancellable *cancellable, 389 GAsyncReadyCallback callback, 390 gpointer data) 391 { 392 GFilterOutputStream *filter_stream; 393 394 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 395 396 g_output_stream_flush_async (filter_stream->base_stream, 397 io_priority, 398 cancellable, 399 callback, 400 data); 401 } 402 403 static gboolean 404 g_filter_output_stream_flush_finish (GOutputStream *stream, 405 GAsyncResult *result, 406 GError **error) 407 { 408 GFilterOutputStream *filter_stream; 409 gboolean res; 410 411 filter_stream = G_FILTER_OUTPUT_STREAM (stream); 412 413 res = g_output_stream_flush_finish (filter_stream->base_stream, 414 result, 415 error); 416 417 return res; 418 } 419 420 static void 421 g_filter_output_stream_close_ready (GObject *object, 422 GAsyncResult *result, 423 gpointer user_data) 424 { 425 GSimpleAsyncResult *simple = user_data; 426 GError *error = NULL; 427 428 g_output_stream_close_finish (G_OUTPUT_STREAM (object), result, &error); 429 430 if (error) 431 { 432 g_simple_async_result_set_from_error (simple, error); 433 g_error_free (error); 434 } 435 436 g_simple_async_result_complete (simple); 437 g_object_unref (simple); 438 } 439 440 static void 441 g_filter_output_stream_close_async (GOutputStream *stream, 442 int io_priority, 443 GCancellable *cancellable, 444 GAsyncReadyCallback callback, 445 gpointer user_data) 446 { 447 GSimpleAsyncResult *simple; 448 449 simple = g_simple_async_result_new (G_OBJECT (stream), 450 callback, user_data, 451 g_filter_output_stream_close_async); 452 453 if (GET_PRIVATE (stream)->close_base) 454 { 455 GFilterOutputStream *filter_stream = G_FILTER_OUTPUT_STREAM (stream); 456 457 g_output_stream_close_async (filter_stream->base_stream, 458 io_priority, cancellable, 459 g_filter_output_stream_close_ready, 460 g_object_ref (simple)); 461 } 462 else 463 /* do nothing */ 464 g_simple_async_result_complete_in_idle (simple); 465 466 g_object_unref (simple); 467 } 468 469 static gboolean 470 g_filter_output_stream_close_finish (GOutputStream *stream, 471 GAsyncResult *result, 472 GError **error) 473 { 474 GSimpleAsyncResult *simple; 475 476 g_return_val_if_fail (g_simple_async_result_is_valid ( 477 result, G_OBJECT (stream), g_filter_output_stream_close_async), FALSE); 478 479 simple = G_SIMPLE_ASYNC_RESULT (result); 480 481 return !g_simple_async_result_propagate_error (simple, error); 482 } 483 484 #define __G_FILTER_OUTPUT_STREAM_C__ 485 #include "gioaliasdef.c" 486