Home | History | Annotate | Download | only in gio
      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