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