(root)/
glib-2.79.0/
gio/
gfilteroutputstream.c
       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 "gfilteroutputstream.h"
      25  #include "goutputstream.h"
      26  #include "glibintl.h"
      27  
      28  
      29  /**
      30   * GFilterOutputStream:
      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    /**
      92     * GFilterOutputStream:close-base-stream:
      93     *
      94     * The underlying base stream on which the I/O ops will be done.
      95     */
      96    g_object_class_install_property (object_class,
      97                                     PROP_BASE_STREAM,
      98                                     g_param_spec_object ("base-stream", NULL, NULL,
      99                                                           G_TYPE_OUTPUT_STREAM,
     100                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | 
     101                                                           G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
     102  
     103    /**
     104     * GFilterOutputStream:close-base-stream:
     105     *
     106     * Whether the base stream should be closed when the filter stream is closed.
     107     */
     108    g_object_class_install_property (object_class,
     109                                     PROP_CLOSE_BASE,
     110                                     g_param_spec_boolean ("close-base-stream", NULL, NULL,
     111                                                           TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
     112                                                           G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
     113  }
     114  
     115  static void
     116  g_filter_output_stream_set_property (GObject      *object,
     117                                       guint         prop_id,
     118                                       const GValue *value,
     119                                       GParamSpec   *pspec)
     120  {
     121    GFilterOutputStream *filter_stream;
     122    GObject *obj;
     123  
     124    filter_stream = G_FILTER_OUTPUT_STREAM (object);
     125  
     126    switch (prop_id) 
     127      {
     128      case PROP_BASE_STREAM:
     129        obj = g_value_dup_object (value);
     130        filter_stream->base_stream = G_OUTPUT_STREAM (obj);
     131        break;
     132  
     133      case PROP_CLOSE_BASE:
     134        g_filter_output_stream_set_close_base_stream (filter_stream,
     135                                                      g_value_get_boolean (value));
     136        break;
     137  
     138      default:
     139        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     140        break;
     141      }
     142  
     143  }
     144  
     145  static void
     146  g_filter_output_stream_get_property (GObject    *object,
     147                                       guint       prop_id,
     148                                       GValue     *value,
     149                                       GParamSpec *pspec)
     150  {
     151    GFilterOutputStream *filter_stream;
     152    GFilterOutputStreamPrivate *priv;
     153  
     154    filter_stream = G_FILTER_OUTPUT_STREAM (object);
     155    priv = g_filter_output_stream_get_instance_private (filter_stream);
     156  
     157    switch (prop_id)
     158      {
     159      case PROP_BASE_STREAM:
     160        g_value_set_object (value, filter_stream->base_stream);
     161        break;
     162  
     163      case PROP_CLOSE_BASE:
     164        g_value_set_boolean (value, priv->close_base);
     165        break;
     166  
     167      default:
     168        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     169        break;
     170      }
     171  
     172  }
     173  
     174  static void
     175  g_filter_output_stream_dispose (GObject *object)
     176  {
     177    GFilterOutputStream *stream;
     178  
     179    stream = G_FILTER_OUTPUT_STREAM (object);
     180  
     181    G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object);
     182    
     183    if (stream->base_stream)
     184      {
     185        g_object_unref (stream->base_stream);
     186        stream->base_stream = NULL;
     187      }
     188  }
     189  
     190  
     191  static void
     192  g_filter_output_stream_init (GFilterOutputStream *stream)
     193  {
     194  }
     195  
     196  /**
     197   * g_filter_output_stream_get_base_stream:
     198   * @stream: a #GFilterOutputStream.
     199   * 
     200   * Gets the base stream for the filter stream.
     201   *
     202   * Returns: (transfer none): a #GOutputStream.
     203   **/
     204  GOutputStream *
     205  g_filter_output_stream_get_base_stream (GFilterOutputStream *stream)
     206  {
     207    g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), NULL);
     208  
     209    return stream->base_stream;
     210  }
     211  
     212  /**
     213   * g_filter_output_stream_get_close_base_stream:
     214   * @stream: a #GFilterOutputStream.
     215   *
     216   * Returns whether the base stream will be closed when @stream is
     217   * closed.
     218   *
     219   * Returns: %TRUE if the base stream will be closed.
     220   **/
     221  gboolean
     222  g_filter_output_stream_get_close_base_stream (GFilterOutputStream *stream)
     223  {
     224    GFilterOutputStreamPrivate *priv;
     225  
     226    g_return_val_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream), FALSE);
     227  
     228    priv = g_filter_output_stream_get_instance_private (stream);
     229  
     230    return priv->close_base;
     231  }
     232  
     233  /**
     234   * g_filter_output_stream_set_close_base_stream:
     235   * @stream: a #GFilterOutputStream.
     236   * @close_base: %TRUE to close the base stream.
     237   *
     238   * Sets whether the base stream will be closed when @stream is closed.
     239   **/
     240  void
     241  g_filter_output_stream_set_close_base_stream (GFilterOutputStream *stream,
     242                                                gboolean             close_base)
     243  {
     244    GFilterOutputStreamPrivate *priv;
     245  
     246    g_return_if_fail (G_IS_FILTER_OUTPUT_STREAM (stream));
     247  
     248    close_base = !!close_base;
     249  
     250    priv = g_filter_output_stream_get_instance_private (stream);
     251  
     252    if (priv->close_base != close_base)
     253      {
     254        priv->close_base = close_base;
     255        g_object_notify (G_OBJECT (stream), "close-base-stream");
     256      }
     257  }
     258  
     259  static gssize
     260  g_filter_output_stream_write (GOutputStream  *stream,
     261                                const void     *buffer,
     262                                gsize           count,
     263                                GCancellable   *cancellable,
     264                                GError        **error)
     265  {
     266    GFilterOutputStream *filter_stream;
     267    gssize nwritten;
     268  
     269    filter_stream = G_FILTER_OUTPUT_STREAM (stream);
     270  
     271    nwritten = g_output_stream_write (filter_stream->base_stream,
     272                                      buffer,
     273                                      count,
     274                                      cancellable,
     275                                      error);
     276  
     277    return nwritten;
     278  }
     279  
     280  static gboolean
     281  g_filter_output_stream_flush (GOutputStream  *stream,
     282                                GCancellable   *cancellable,
     283                                GError        **error)
     284  {
     285    GFilterOutputStream *filter_stream;
     286    gboolean res;
     287  
     288    filter_stream = G_FILTER_OUTPUT_STREAM (stream);
     289  
     290    res = g_output_stream_flush (filter_stream->base_stream,
     291                                 cancellable,
     292                                 error);
     293  
     294    return res;
     295  }
     296  
     297  static gboolean
     298  g_filter_output_stream_close (GOutputStream  *stream,
     299                                GCancellable   *cancellable,
     300                                GError        **error)
     301  {
     302    GFilterOutputStream *filter_stream = G_FILTER_OUTPUT_STREAM (stream);
     303    GFilterOutputStreamPrivate *priv = g_filter_output_stream_get_instance_private (filter_stream);
     304    gboolean res = TRUE;
     305  
     306    if (priv->close_base)
     307      {
     308        res = g_output_stream_close (filter_stream->base_stream,
     309                                     cancellable,
     310                                     error);
     311      }
     312  
     313    return res;
     314  }