/* GIO - GLib Input, Output and Streaming Library * * Copyright (C) 2006-2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * Author: Christian Kellner */ #include "config.h" #include "gfilterinputstream.h" #include "ginputstream.h" #include "gsimpleasyncresult.h" #include "glibintl.h" #include "gioalias.h" /** * SECTION:gfilterinputstream * @short_description: Filter Input Stream * @include: gio/gio.h * **/ enum { PROP_0, PROP_BASE_STREAM, PROP_CLOSE_BASE }; static void g_filter_input_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void g_filter_input_stream_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void g_filter_input_stream_finalize (GObject *object); static gssize g_filter_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error); static gssize g_filter_input_stream_skip (GInputStream *stream, gsize count, GCancellable *cancellable, GError **error); static gboolean g_filter_input_stream_close (GInputStream *stream, GCancellable *cancellable, GError **error); static void g_filter_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); static gssize g_filter_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error); static void g_filter_input_stream_skip_async (GInputStream *stream, gsize count, int io_priority, GCancellable *cancellabl, GAsyncReadyCallback callback, gpointer datae); static gssize g_filter_input_stream_skip_finish (GInputStream *stream, GAsyncResult *result, GError **error); static void g_filter_input_stream_close_async (GInputStream *stream, int io_priority, GCancellable *cancellabl, GAsyncReadyCallback callback, gpointer data); static gboolean g_filter_input_stream_close_finish (GInputStream *stream, GAsyncResult *result, GError **error); G_DEFINE_TYPE (GFilterInputStream, g_filter_input_stream, G_TYPE_INPUT_STREAM) #define GET_PRIVATE(inst) G_TYPE_INSTANCE_GET_PRIVATE (inst, \ G_TYPE_FILTER_INPUT_STREAM, GFilterInputStreamPrivate) typedef struct { gboolean close_base; } GFilterInputStreamPrivate; static void g_filter_input_stream_class_init (GFilterInputStreamClass *klass) { GObjectClass *object_class; GInputStreamClass *istream_class; object_class = G_OBJECT_CLASS (klass); object_class->get_property = g_filter_input_stream_get_property; object_class->set_property = g_filter_input_stream_set_property; object_class->finalize = g_filter_input_stream_finalize; istream_class = G_INPUT_STREAM_CLASS (klass); istream_class->read_fn = g_filter_input_stream_read; istream_class->skip = g_filter_input_stream_skip; istream_class->close_fn = g_filter_input_stream_close; istream_class->read_async = g_filter_input_stream_read_async; istream_class->read_finish = g_filter_input_stream_read_finish; istream_class->skip_async = g_filter_input_stream_skip_async; istream_class->skip_finish = g_filter_input_stream_skip_finish; istream_class->close_async = g_filter_input_stream_close_async; istream_class->close_finish = g_filter_input_stream_close_finish; g_type_class_add_private (klass, sizeof (GFilterInputStreamPrivate)); g_object_class_install_property (object_class, PROP_BASE_STREAM, g_param_spec_object ("base-stream", P_("The Filter Base Stream"), P_("The underlying base stream on which the io ops will be done."), G_TYPE_INPUT_STREAM, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); g_object_class_install_property (object_class, PROP_CLOSE_BASE, g_param_spec_boolean ("close-base-stream", P_("Close Base Stream"), P_("If the base stream should be closed when the filter stream is closed."), TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); } static void g_filter_input_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GFilterInputStream *filter_stream; GObject *obj; filter_stream = G_FILTER_INPUT_STREAM (object); switch (prop_id) { case PROP_BASE_STREAM: obj = g_value_dup_object (value); filter_stream->base_stream = G_INPUT_STREAM (obj); break; case PROP_CLOSE_BASE: g_filter_input_stream_set_close_base_stream (filter_stream, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void g_filter_input_stream_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GFilterInputStream *filter_stream; filter_stream = G_FILTER_INPUT_STREAM (object); switch (prop_id) { case PROP_BASE_STREAM: g_value_set_object (value, filter_stream->base_stream); break; case PROP_CLOSE_BASE: g_value_set_boolean (value, GET_PRIVATE (filter_stream)->close_base); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void g_filter_input_stream_finalize (GObject *object) { GFilterInputStream *stream; stream = G_FILTER_INPUT_STREAM (object); g_object_unref (stream->base_stream); G_OBJECT_CLASS (g_filter_input_stream_parent_class)->finalize (object); } static void g_filter_input_stream_init (GFilterInputStream *stream) { } /** * g_filter_input_stream_get_base_stream: * @stream: a #GFilterInputStream. * * Gets the base stream for the filter stream. * * Returns: a #GInputStream. **/ GInputStream * g_filter_input_stream_get_base_stream (GFilterInputStream *stream) { g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), NULL); return stream->base_stream; } /** * g_filter_input_stream_get_close_base_stream: * @stream: a #GFilterInputStream. * * Returns whether the base stream will be closed when @stream is * closed. * * Return value: %TRUE if the base stream will be closed. **/ gboolean g_filter_input_stream_get_close_base_stream (GFilterInputStream *stream) { g_return_val_if_fail (G_IS_FILTER_INPUT_STREAM (stream), FALSE); return GET_PRIVATE (stream)->close_base; } /** * g_filter_input_stream_set_close_base_stream: * @stream: a #GFilterInputStream. * @close_base: %TRUE to close the base stream. * * Sets whether the base stream will be closed when @stream is closed. **/ void g_filter_input_stream_set_close_base_stream (GFilterInputStream *stream, gboolean close_base) { GFilterInputStreamPrivate *priv; g_return_if_fail (G_IS_FILTER_INPUT_STREAM (stream)); close_base = !!close_base; priv = GET_PRIVATE (stream); if (priv->close_base != close_base) { priv->close_base = close_base; g_object_notify (G_OBJECT (stream), "close-base-stream"); } } static gssize g_filter_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { GFilterInputStream *filter_stream; GInputStream *base_stream; gssize nread; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; nread = g_input_stream_read (base_stream, buffer, count, cancellable, error); return nread; } static gssize g_filter_input_stream_skip (GInputStream *stream, gsize count, GCancellable *cancellable, GError **error) { GFilterInputStream *filter_stream; GInputStream *base_stream; gssize nskipped; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; nskipped = g_input_stream_skip (base_stream, count, cancellable, error); return nskipped; } static gboolean g_filter_input_stream_close (GInputStream *stream, GCancellable *cancellable, GError **error) { gboolean res = TRUE; if (GET_PRIVATE (stream)->close_base) { GFilterInputStream *filter_stream; GInputStream *base_stream; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; res = g_input_stream_close (base_stream, cancellable, error); } return res; } static void g_filter_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GFilterInputStream *filter_stream; GInputStream *base_stream; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; g_input_stream_read_async (base_stream, buffer, count, io_priority, cancellable, callback, user_data); } static gssize g_filter_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error) { GFilterInputStream *filter_stream; GInputStream *base_stream; gssize nread; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; nread = g_input_stream_read_finish (base_stream, result, error); return nread; } static void g_filter_input_stream_skip_async (GInputStream *stream, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GFilterInputStream *filter_stream; GInputStream *base_stream; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; g_input_stream_skip_async (base_stream, count, io_priority, cancellable, callback, user_data); } static gssize g_filter_input_stream_skip_finish (GInputStream *stream, GAsyncResult *result, GError **error) { GFilterInputStream *filter_stream; GInputStream *base_stream; gssize nskipped; filter_stream = G_FILTER_INPUT_STREAM (stream); base_stream = filter_stream->base_stream; nskipped = g_input_stream_skip_finish (base_stream, result, error); return nskipped; } static void g_filter_input_stream_close_ready (GObject *object, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *simple = user_data; GError *error = NULL; g_input_stream_close_finish (G_INPUT_STREAM (object), result, &error); if (error) { g_simple_async_result_set_from_error (simple, error); g_error_free (error); } g_simple_async_result_complete (simple); g_object_unref (simple); } static void g_filter_input_stream_close_async (GInputStream *stream, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_filter_input_stream_close_async); if (GET_PRIVATE (stream)->close_base) { GFilterInputStream *filter_stream = G_FILTER_INPUT_STREAM (stream); g_input_stream_close_async (filter_stream->base_stream, io_priority, cancellable, g_filter_input_stream_close_ready, g_object_ref (simple)); } else /* do nothing */ g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } static gboolean g_filter_input_stream_close_finish (GInputStream *stream, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (g_simple_async_result_is_valid ( result, G_OBJECT (stream), g_filter_input_stream_close_async), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); return !g_simple_async_result_propagate_error (simple, error); } #define __G_FILTER_INPUT_STREAM_C__ #include "gioaliasdef.c"