[glib] Add GFileIOStream class



commit bd0b8c60c231c72588d69dfb2018d2e418517f7f
Author: Alexander Larsson <alexl redhat com>
Date:   Tue May 12 16:59:36 2009 +0200

    Add GFileIOStream class
    
    This is similar to GFileInputStream and GFileOutputStream for GIOStreams.
    The default implementations chain to the Output stream.
---
 gio/Makefile.am     |    2 +
 gio/gfileiostream.c |  671 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gio/gfileiostream.h |  118 +++++++++
 gio/gio.h           |    1 +
 gio/gio.symbols     |   10 +
 gio/giostream.c     |    3 -
 gio/giotypes.h      |    1 +
 7 files changed, 803 insertions(+), 3 deletions(-)

diff --git a/gio/Makefile.am b/gio/Makefile.am
index 78c2c3f..76e402d 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -199,6 +199,7 @@ libgio_2_0_la_SOURCES =		\
 	gfilemonitor.c 		\
 	gfilenamecompleter.c 	\
 	gfileoutputstream.c 	\
+	gfileiostream.c		\
 	gfilterinputstream.c 	\
 	gfilteroutputstream.c 	\
 	gicon.c 		\
@@ -315,6 +316,7 @@ gio_headers =			\
 	gfilemonitor.h 		\
 	gfilenamecompleter.h 	\
 	gfileoutputstream.h 	\
+	gfileiostream.h		\
 	gfilterinputstream.h 	\
 	gfilteroutputstream.h 	\
 	gicon.h 		\
diff --git a/gio/gfileiostream.c b/gio/gfileiostream.c
new file mode 100644
index 0000000..9491e76
--- /dev/null
+++ b/gio/gfileiostream.c
@@ -0,0 +1,671 @@
+/* GIO - GLib Input, IO 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: Alexander Larsson <alexl redhat com>
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gfileiostream.h>
+#include <gseekable.h>
+#include "gsimpleasyncresult.h"
+#include "gasyncresult.h"
+#include "gcancellable.h"
+#include "gioerror.h"
+#include "gfileoutputstream.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gfileiostream
+ * @short_description: read write streams for File
+ * @include: gio/gio.h
+ * @see_also: #GIOStream, #GFileInputStream, #GFileOutputStream, #GSeekable
+ *
+ * GFileIOStream provides io streams that both read and write to the same
+ * file handle.
+ *
+ * GFileIOStream implements #GSeekable, which allows the io
+ * stream to jump to arbitrary positions in the file and to truncate
+ * the file, provided the filesystem of the file supports these
+ * operations. In addition to the generic g_seekable_ API,
+ * GFileIOStream has its own API for seeking and positioning.
+ * To find the position of a file io stream, use
+ * g_file_io_stream_tell(). To find out if a file io
+ * stream supports seeking, use g_file_io_stream_can_seek().
+ * To position a file io stream, use g_file_io_stream_seek().
+ * To find out if a file io stream supports truncating, use
+ * g_file_io_stream_can_truncate(). To truncate a file io
+ * stream, use g_file_io_stream_truncate().
+ *
+ * Since: 2.22
+ **/
+
+static void       g_file_io_stream_seekable_iface_init    (GSeekableIface       *iface);
+static goffset    g_file_io_stream_seekable_tell          (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_can_seek      (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_seek          (GSeekable            *seekable,
+							   goffset               offset,
+							   GSeekType             type,
+							   GCancellable         *cancellable,
+							   GError              **error);
+static gboolean   g_file_io_stream_seekable_can_truncate  (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_truncate      (GSeekable            *seekable,
+							   goffset               offset,
+							   GCancellable         *cancellable,
+							   GError              **error);
+static void       g_file_io_stream_real_query_info_async  (GFileIOStream    *stream,
+							   const char           *attributes,
+							   int                   io_priority,
+							   GCancellable         *cancellable,
+							   GAsyncReadyCallback   callback,
+							   gpointer              user_data);
+static GFileInfo *g_file_io_stream_real_query_info_finish (GFileIOStream    *stream,
+							   GAsyncResult         *result,
+							   GError              **error);
+
+G_DEFINE_TYPE_WITH_CODE (GFileIOStream, g_file_io_stream, G_TYPE_IO_STREAM,
+			 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
+						g_file_io_stream_seekable_iface_init));
+
+struct _GFileIOStreamPrivate {
+  GAsyncReadyCallback outstanding_callback;
+};
+
+static void
+g_file_io_stream_seekable_iface_init (GSeekableIface *iface)
+{
+  iface->tell = g_file_io_stream_seekable_tell;
+  iface->can_seek = g_file_io_stream_seekable_can_seek;
+  iface->seek = g_file_io_stream_seekable_seek;
+  iface->can_truncate = g_file_io_stream_seekable_can_truncate;
+  iface->truncate_fn = g_file_io_stream_seekable_truncate;
+}
+
+static void
+g_file_io_stream_init (GFileIOStream *stream)
+{
+  stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
+					      G_TYPE_FILE_IO_STREAM,
+					      GFileIOStreamPrivate);
+}
+
+/**
+ * g_file_io_stream_query_info:
+ * @stream: a #GFileIOStream.
+ * @attributes: a file attribute query string.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: a #GError, %NULL to ignore.
+ *
+ * Queries a file io stream for the given @attributes.
+ * This function blocks while querying the stream. For the asynchronous
+ * version of this function, see g_file_io_stream_query_info_async().
+ * While the stream is blocked, the stream will set the pending flag
+ * internally, and any other operations on the stream will fail with
+ * %G_IO_ERROR_PENDING.
+ *
+ * Can fail if the stream was already closed (with @error being set to
+ * %G_IO_ERROR_CLOSED), the stream has pending operations (with @error being
+ * set to %G_IO_ERROR_PENDING), or if querying info is not supported for
+ * the stream's interface (with @error being set to %G_IO_ERROR_NOT_SUPPORTED). I
+ * all cases of failure, %NULL will be returned.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %NULL will
+ * be returned.
+ *
+ * Returns: a #GFileInfo for the @stream, or %NULL on error.
+ *
+ * Since: 2.22
+ **/
+GFileInfo *
+g_file_io_stream_query_info (GFileIOStream      *stream,
+			     const char             *attributes,
+			     GCancellable           *cancellable,
+			     GError                **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  GFileInfo *info;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return NULL;
+
+  info = NULL;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  if (class->query_info)
+    info = class->query_info (stream, attributes, cancellable, error);
+  else
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                         _("Stream doesn't support query_info"));
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return info;
+}
+
+static void
+async_ready_callback_wrapper (GObject *source_object,
+			      GAsyncResult *res,
+			      gpointer      user_data)
+{
+  GFileIOStream *stream = G_FILE_IO_STREAM (source_object);
+
+  g_io_stream_clear_pending (G_IO_STREAM (stream));
+  if (stream->priv->outstanding_callback)
+    (*stream->priv->outstanding_callback) (source_object, res, user_data);
+  g_object_unref (stream);
+}
+
+/**
+ * g_file_io_stream_query_info_async:
+ * @stream: a #GFileIOStream.
+ * @attributes: a file attribute query string.
+ * @io_priority: the <link linkend="gio-GIOScheduler">I/O priority</link>
+ *     of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: callback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously queries the @stream for a #GFileInfo. When completed,
+ * @callback will be called with a #GAsyncResult which can be used to
+ * finish the operation with g_file_io_stream_query_info_finish().
+ *
+ * For the synchronous version of this function, see
+ * g_file_io_stream_query_info().
+ *
+ * Since: 2.22
+ **/
+void
+g_file_io_stream_query_info_async (GFileIOStream     *stream,
+					  const char           *attributes,
+					  int                   io_priority,
+					  GCancellable         *cancellable,
+					  GAsyncReadyCallback   callback,
+					  gpointer              user_data)
+{
+  GFileIOStreamClass *klass;
+  GIOStream *io_stream;
+  GError *error = NULL;
+
+  g_return_if_fail (G_IS_FILE_IO_STREAM (stream));
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_set_pending (io_stream, &error))
+    {
+      g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
+					    callback,
+					    user_data,
+					    error);
+      g_error_free (error);
+      return;
+    }
+
+  klass = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  stream->priv->outstanding_callback = callback;
+  g_object_ref (stream);
+  klass->query_info_async (stream, attributes, io_priority, cancellable,
+			      async_ready_callback_wrapper, user_data);
+}
+
+/**
+ * g_file_io_stream_query_info_finish:
+ * @stream: a #GFileIOStream.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, %NULL to ignore.
+ *
+ * Finalizes the asynchronous query started
+ * by g_file_io_stream_query_info_async().
+ *
+ * Returns: A #GFileInfo for the finished query.
+ *
+ * Since: 2.22
+ **/
+GFileInfo *
+g_file_io_stream_query_info_finish (GFileIOStream     *stream,
+					   GAsyncResult         *result,
+					   GError              **error)
+{
+  GSimpleAsyncResult *simple;
+  GFileIOStreamClass *class;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+	return NULL;
+    }
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  return class->query_info_finish (stream, result, error);
+}
+
+/**
+ * g_file_io_stream_get_etag:
+ * @stream: a #GFileIOStream.
+ *
+ * Gets the entity tag for the file when it has been written.
+ * This must be called after the stream has been written
+ * and closed, as the etag can change while writing.
+ *
+ * Returns: the entity tag for the stream.
+ *
+ * Since: 2.22
+ **/
+char *
+g_file_io_stream_get_etag (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  char *etag;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_is_closed (io_stream))
+    {
+      g_warning ("stream is not closed yet, can't get etag");
+      return NULL;
+    }
+
+  etag = NULL;
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  if (class->get_etag)
+    etag = class->get_etag (stream);
+
+  return etag;
+}
+
+static goffset
+g_file_io_stream_tell (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  goffset offset;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), 0);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  offset = 0;
+  if (class->tell)
+    offset = class->tell (stream);
+
+  return offset;
+}
+
+static goffset
+g_file_io_stream_seekable_tell (GSeekable *seekable)
+{
+  return g_file_io_stream_tell (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_can_seek (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  gboolean can_seek;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  can_seek = FALSE;
+  if (class->seek)
+    {
+      can_seek = TRUE;
+      if (class->can_seek)
+	can_seek = class->can_seek (stream);
+    }
+
+  return can_seek;
+}
+
+static gboolean
+g_file_io_stream_seekable_can_seek (GSeekable *seekable)
+{
+  return g_file_io_stream_can_seek (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_seek (GFileIOStream  *stream,
+		       goffset             offset,
+		       GSeekType           type,
+		       GCancellable       *cancellable,
+		       GError            **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  gboolean res;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  io_stream = G_IO_STREAM (stream);
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  if (!class->seek)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Seek not supported on stream"));
+      return FALSE;
+    }
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return FALSE;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  res = class->seek (stream, offset, type, cancellable, error);
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return res;
+}
+
+static gboolean
+g_file_io_stream_seekable_seek (GSeekable  *seekable,
+				    goffset     offset,
+				    GSeekType   type,
+				    GCancellable  *cancellable,
+				    GError    **error)
+{
+  return g_file_io_stream_seek (G_FILE_IO_STREAM (seekable),
+				offset, type, cancellable, error);
+}
+
+static gboolean
+g_file_io_stream_can_truncate (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  gboolean can_truncate;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  can_truncate = FALSE;
+  if (class->truncate_fn)
+    {
+      can_truncate = TRUE;
+      if (class->can_truncate)
+	can_truncate = class->can_truncate (stream);
+    }
+
+  return can_truncate;
+}
+
+static gboolean
+g_file_io_stream_seekable_can_truncate (GSeekable  *seekable)
+{
+  return g_file_io_stream_can_truncate (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_truncate (GFileIOStream  *stream,
+			   goffset             size,
+			   GCancellable       *cancellable,
+			   GError            **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  gboolean res;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  io_stream = G_IO_STREAM (stream);
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  if (!class->truncate_fn)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Truncate not supported on stream"));
+      return FALSE;
+    }
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return FALSE;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  res = class->truncate_fn (stream, size, cancellable, error);
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return res;
+}
+
+static gboolean
+g_file_io_stream_seekable_truncate (GSeekable     *seekable,
+				    goffset        size,
+				    GCancellable  *cancellable,
+				    GError       **error)
+{
+  return g_file_io_stream_truncate (G_FILE_IO_STREAM (seekable),
+					size, cancellable, error);
+}
+/*****************************************************
+ *   Default implementations based on output stream  *
+ *****************************************************/
+
+static goffset
+g_file_io_stream_real_tell (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_tell (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_can_seek (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_can_seek (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_seek (GFileIOStream    *stream,
+			    goffset           offset,
+			    GSeekType         type,
+			    GCancellable     *cancellable,
+			    GError          **error)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_seek (seekable, offset, type, cancellable, error);
+}
+
+static  gboolean
+g_file_io_stream_real_can_truncate (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_can_truncate (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_truncate_fn (GFileIOStream    *stream,
+				   goffset               size,
+				   GCancellable         *cancellable,
+				   GError              **error)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_truncate (seekable, size, cancellable, error);
+}
+
+static char *
+g_file_io_stream_real_get_etag (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_get_etag (file_out);
+}
+
+static GFileInfo *
+g_file_io_stream_real_query_info (GFileIOStream    *stream,
+				  const char           *attributes,
+				  GCancellable         *cancellable,
+				  GError              **error)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_query_info (file_out,
+					  attributes, cancellable, error);
+}
+
+typedef struct {
+  GObject *object;
+  GAsyncReadyCallback callback;
+  gpointer user_data;
+} AsyncOpWrapper;
+
+static AsyncOpWrapper *
+async_op_wrapper_new (gpointer object,
+		      GAsyncReadyCallback callback,
+		      gpointer user_data)
+{
+  AsyncOpWrapper *data;
+
+  data = g_new0 (AsyncOpWrapper, 1);
+  data->object = g_object_ref (object);
+  data->callback = callback;
+  data->user_data = user_data;
+}
+
+static void
+async_op_wrapper_callback (GObject *source_object,
+			   GAsyncResult *res,
+			   gpointer user_data)
+{
+  AsyncOpWrapper *data  = user_data;
+  data->callback (data->object, res, data->user_data);
+  g_object_unref (data->object);
+  g_free (data);
+}
+
+static void
+g_file_io_stream_real_query_info_async (GFileIOStream     *stream,
+					const char           *attributes,
+					int                   io_priority,
+					GCancellable         *cancellable,
+					GAsyncReadyCallback   callback,
+					gpointer              user_data)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+  AsyncOpWrapper *data;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  data = async_op_wrapper_new (stream, callback, user_data);
+  g_file_output_stream_query_info_async (file_out,
+					 attributes, io_priority,
+					 cancellable, async_op_wrapper_callback, data);
+}
+
+static GFileInfo *
+g_file_io_stream_real_query_info_finish (GFileIOStream     *stream,
+					 GAsyncResult      *res,
+					 GError           **error)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_query_info_finish (file_out, res, error);
+}
+
+static void
+g_file_io_stream_class_init (GFileIOStreamClass *klass)
+{
+  g_type_class_add_private (klass, sizeof (GFileIOStreamPrivate));
+
+  klass->tell = g_file_io_stream_real_tell;
+  klass->can_seek = g_file_io_stream_real_can_seek;
+  klass->seek = g_file_io_stream_real_seek;
+  klass->can_truncate = g_file_io_stream_real_can_truncate;
+  klass->truncate_fn = g_file_io_stream_real_truncate_fn;
+  klass->query_info = g_file_io_stream_real_query_info;
+  klass->query_info_async = g_file_io_stream_real_query_info_async;
+  klass->query_info_finish = g_file_io_stream_real_query_info_finish;
+  klass->get_etag = g_file_io_stream_real_get_etag;
+}
+
+#define __G_FILE_IO_STREAM_C__
+#include "gioaliasdef.c"
diff --git a/gio/gfileiostream.h b/gio/gfileiostream.h
new file mode 100644
index 0000000..09c9922
--- /dev/null
+++ b/gio/gfileiostream.h
@@ -0,0 +1,118 @@
+/* GIO - GLib Input, Io 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: Alexander Larsson <alexl redhat com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_FILE_IO_STREAM_H__
+#define __G_FILE_IO_STREAM_H__
+
+#include <gio/giostream.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_FILE_IO_STREAM         (g_file_io_stream_get_type ())
+#define G_FILE_IO_STREAM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_IO_STREAM, GFileIOStream))
+#define G_FILE_IO_STREAM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_IO_STREAM, GFileIOStreamClass))
+#define G_IS_FILE_IO_STREAM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_IO_STREAM))
+#define G_IS_FILE_IO_STREAM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_IO_STREAM))
+#define G_FILE_IO_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_IO_STREAM, GFileIOStreamClass))
+
+/**
+ * GFileIOStream:
+ *
+ * A subclass of GIOStream for opened files. This adds
+ * a few file-specific operations and seeking and truncating.
+ *
+ * #GFileIOStream implements GSeekable.
+ **/
+typedef struct _GFileIOStreamClass    GFileIOStreamClass;
+typedef struct _GFileIOStreamPrivate  GFileIOStreamPrivate;
+
+struct _GFileIOStream
+{
+  GIOStream parent_instance;
+
+  /*< private >*/
+  GFileIOStreamPrivate *priv;
+};
+
+struct _GFileIOStreamClass
+{
+  GIOStreamClass parent_class;
+
+  goffset     (* tell)              (GFileIOStream    *stream);
+  gboolean    (* can_seek)          (GFileIOStream    *stream);
+  gboolean    (* seek)	            (GFileIOStream    *stream,
+                                     goffset               offset,
+                                     GSeekType             type,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  gboolean    (* can_truncate)      (GFileIOStream    *stream);
+  gboolean    (* truncate_fn)       (GFileIOStream    *stream,
+                                     goffset               size,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  GFileInfo * (* query_info)        (GFileIOStream    *stream,
+                                     const char           *attributes,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  void        (* query_info_async)  (GFileIOStream     *stream,
+                                     const char            *attributes,
+                                     int                   io_priority,
+                                     GCancellable         *cancellable,
+                                     GAsyncReadyCallback   callback,
+                                     gpointer              user_data);
+  GFileInfo * (* query_info_finish) (GFileIOStream     *stream,
+                                     GAsyncResult         *res,
+                                     GError              **error);
+  char      * (* get_etag)          (GFileIOStream    *stream);
+
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+};
+
+GType      g_file_io_stream_get_type          (void) G_GNUC_CONST;
+
+GFileInfo *g_file_io_stream_query_info        (GFileIOStream    *stream,
+					       const char           *attributes,
+					       GCancellable         *cancellable,
+					       GError              **error);
+void       g_file_io_stream_query_info_async  (GFileIOStream    *stream,
+					       const char           *attributes,
+					       int                   io_priority,
+					       GCancellable         *cancellable,
+					       GAsyncReadyCallback   callback,
+					       gpointer              user_data);
+GFileInfo *g_file_io_stream_query_info_finish (GFileIOStream    *stream,
+					       GAsyncResult         *result,
+					       GError              **error);
+char *     g_file_io_stream_get_etag          (GFileIOStream    *stream);
+
+G_END_DECLS
+
+#endif /* __G_FILE_FILE_IO_STREAM_H__ */
diff --git a/gio/gio.h b/gio/gio.h
index 63d0b79..f12d2ed 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -58,6 +58,7 @@
 #include <gio/giomodule.h>
 #include <gio/gioscheduler.h>
 #include <gio/giostream.h>
+#include <gio/gfileiostream.h>
 #include <gio/gloadableicon.h>
 #include <gio/gmemoryinputstream.h>
 #include <gio/gmemoryoutputstream.h>
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 9ebc37c..2671194 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -458,6 +458,16 @@ g_file_output_stream_get_etag
 #endif
 #endif
 
+#if IN_HEADER(__G_FILE_IO_STREAM_H__)
+#if IN_FILE(__G_FILE_IO_STREAM_C__)
+g_file_io_stream_get_type  G_GNUC_CONST
+g_file_io_stream_query_info
+g_file_io_stream_query_info_async
+g_file_io_stream_query_info_finish
+g_file_io_stream_get_etag
+#endif
+#endif
+
 #if IN_HEADER(__G_FILTER_INPUT_STREAM_H__)
 #if IN_FILE(__G_FILTER_INPUT_STREAM_C__)
 g_filter_input_stream_get_type  G_GNUC_CONST
diff --git a/gio/giostream.c b/gio/giostream.c
index 6f3de48..6c3a073 100644
--- a/gio/giostream.c
+++ b/gio/giostream.c
@@ -96,9 +96,6 @@ g_io_stream_finalize (GObject *object)
 
   stream = G_IO_STREAM (object);
 
-  if (!stream->priv->closed)
-    g_io_stream_close (stream, NULL, NULL);
-
   G_OBJECT_CLASS (g_io_stream_parent_class)->finalize (object);
 }
 
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 9af8651..3a3c361 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -70,6 +70,7 @@ typedef struct _GFileAttributeInfo            GFileAttributeInfo;
 typedef struct _GFileAttributeInfoList        GFileAttributeInfoList;
 typedef struct _GFileInputStream              GFileInputStream;
 typedef struct _GFileOutputStream             GFileOutputStream;
+typedef struct _GFileIOStream                 GFileIOStream;
 typedef struct _GFileIcon                     GFileIcon;
 typedef struct _GFilenameCompleter            GFilenameCompleter;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]