hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gbufferedoutputstream.c
index ec84a61..ac9b45f 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Christian Kellner <gicmo@gnome.org> 
  */
 #include "config.h"
 #include "gbufferedoutputstream.h"
 #include "goutputstream.h"
-#include "gsimpleasyncresult.h"
+#include "gseekable.h"
+#include "gtask.h"
 #include "string.h"
+#include "gioerror.h"
 #include "glibintl.h"
 
-#include <gioalias.h>
-
 /**
  * SECTION:gbufferedoutputstream
  * @short_description: Buffered Output Stream
@@ -90,16 +88,6 @@ static gboolean g_buffered_output_stream_close        (GOutputStream  *stream,
                                                        GCancellable   *cancellable,
                                                        GError        **error);
 
-static void     g_buffered_output_stream_write_async  (GOutputStream        *stream,
-                                                       const void           *buffer,
-                                                       gsize                 count,
-                                                       int                   io_priority,
-                                                       GCancellable         *cancellable,
-                                                       GAsyncReadyCallback   callback,
-                                                       gpointer              data);
-static gssize   g_buffered_output_stream_write_finish (GOutputStream        *stream,
-                                                       GAsyncResult         *result,
-                                                       GError              **error);
 static void     g_buffered_output_stream_flush_async  (GOutputStream        *stream,
                                                        int                   io_priority,
                                                        GCancellable         *cancellable,
@@ -117,9 +105,26 @@ static gboolean g_buffered_output_stream_close_finish (GOutputStream        *str
                                                        GAsyncResult         *result,
                                                        GError              **error);
 
-G_DEFINE_TYPE (GBufferedOutputStream,
-               g_buffered_output_stream,
-               G_TYPE_FILTER_OUTPUT_STREAM)
+static void     g_buffered_output_stream_seekable_iface_init (GSeekableIface  *iface);
+static goffset  g_buffered_output_stream_tell                (GSeekable       *seekable);
+static gboolean g_buffered_output_stream_can_seek            (GSeekable       *seekable);
+static gboolean g_buffered_output_stream_seek                (GSeekable       *seekable,
+                                                             goffset          offset,
+                                                             GSeekType        type,
+                                                             GCancellable    *cancellable,
+                                                             GError         **error);
+static gboolean g_buffered_output_stream_can_truncate        (GSeekable       *seekable);
+static gboolean g_buffered_output_stream_truncate            (GSeekable       *seekable,
+                                                             goffset          offset,
+                                                             GCancellable    *cancellable,
+                                                             GError         **error);
+
+G_DEFINE_TYPE_WITH_CODE (GBufferedOutputStream,
+                        g_buffered_output_stream,
+                        G_TYPE_FILTER_OUTPUT_STREAM,
+                         G_ADD_PRIVATE (GBufferedOutputStream)
+                        G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
+                                               g_buffered_output_stream_seekable_iface_init))
 
 
 static void
@@ -127,8 +132,6 @@ g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass)
 {
   GObjectClass *object_class;
   GOutputStreamClass *ostream_class;
-  g_type_class_add_private (klass, sizeof (GBufferedOutputStreamPrivate));
 
   object_class = G_OBJECT_CLASS (klass);
   object_class->get_property = g_buffered_output_stream_get_property;
@@ -139,8 +142,6 @@ g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass)
   ostream_class->write_fn = g_buffered_output_stream_write;
   ostream_class->flush = g_buffered_output_stream_flush;
   ostream_class->close_fn = g_buffered_output_stream_close;
-  ostream_class->write_async  = g_buffered_output_stream_write_async;
-  ostream_class->write_finish = g_buffered_output_stream_write_finish;
   ostream_class->flush_async  = g_buffered_output_stream_flush_async;
   ostream_class->flush_finish = g_buffered_output_stream_flush_finish;
   ostream_class->close_async  = g_buffered_output_stream_close_async;
@@ -341,10 +342,17 @@ g_buffered_output_stream_finalize (GObject *object)
 static void
 g_buffered_output_stream_init (GBufferedOutputStream *stream)
 {
-  stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
-                                              G_TYPE_BUFFERED_OUTPUT_STREAM,
-                                              GBufferedOutputStreamPrivate);
+  stream->priv = g_buffered_output_stream_get_instance_private (stream);
+}
 
+static void
+g_buffered_output_stream_seekable_iface_init (GSeekableIface *iface)
+{
+  iface->tell         = g_buffered_output_stream_tell;
+  iface->can_seek     = g_buffered_output_stream_can_seek;
+  iface->seek         = g_buffered_output_stream_seek;
+  iface->can_truncate = g_buffered_output_stream_can_truncate;
+  iface->truncate_fn  = g_buffered_output_stream_truncate;
 }
 
 /**
@@ -421,7 +429,7 @@ flush_buffer (GBufferedOutputStream  *stream,
   count = priv->pos - bytes_written;
 
   if (count > 0)
-    g_memmove (priv->buffer, priv->buffer + bytes_written, count);
+    memmove (priv->buffer, priv->buffer + bytes_written, count);
   
   priv->pos -= bytes_written;
 
@@ -515,6 +523,104 @@ g_buffered_output_stream_close (GOutputStream  *stream,
   return res;
 }
 
+static goffset
+g_buffered_output_stream_tell (GSeekable *seekable)
+{
+  GBufferedOutputStream        *bstream;
+  GBufferedOutputStreamPrivate *priv;
+  GOutputStream *base_stream;
+  GSeekable    *base_stream_seekable;
+  goffset base_offset;
+  
+  bstream = G_BUFFERED_OUTPUT_STREAM (seekable);
+  priv = bstream->priv;
+
+  base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
+  if (!G_IS_SEEKABLE (base_stream))
+    return 0;
+
+  base_stream_seekable = G_SEEKABLE (base_stream);
+  
+  base_offset = g_seekable_tell (base_stream_seekable);
+  return base_offset + priv->pos;
+}
+
+static gboolean
+g_buffered_output_stream_can_seek (GSeekable *seekable)
+{
+  GOutputStream *base_stream;
+  
+  base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
+  return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream));
+}
+
+static gboolean
+g_buffered_output_stream_seek (GSeekable     *seekable,
+                              goffset        offset,
+                              GSeekType      type,
+                              GCancellable  *cancellable,
+                              GError       **error)
+{
+  GBufferedOutputStream *bstream;
+  GOutputStream *base_stream;
+  GSeekable *base_stream_seekable;
+  gboolean flushed;
+
+  bstream = G_BUFFERED_OUTPUT_STREAM (seekable);
+
+  base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
+  if (!G_IS_SEEKABLE (base_stream))
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Seek not supported on base stream"));
+      return FALSE;
+    }
+
+  base_stream_seekable = G_SEEKABLE (base_stream);
+  flushed = flush_buffer (bstream, cancellable, error);
+  if (!flushed)
+    return FALSE;
+
+  return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error);
+}
+
+static gboolean
+g_buffered_output_stream_can_truncate (GSeekable *seekable)
+{
+  GOutputStream *base_stream;
+  
+  base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
+  return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream));
+}
+
+static gboolean
+g_buffered_output_stream_truncate (GSeekable     *seekable,
+                                  goffset        offset,
+                                  GCancellable  *cancellable,
+                                  GError       **error)
+{
+  GBufferedOutputStream        *bstream;
+  GOutputStream *base_stream;
+  GSeekable *base_stream_seekable;
+  gboolean flushed;
+
+  bstream = G_BUFFERED_OUTPUT_STREAM (seekable);
+  base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
+  if (!G_IS_SEEKABLE (base_stream))
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Truncate not supported on base stream"));
+      return FALSE;
+    }
+
+  base_stream_seekable = G_SEEKABLE (base_stream);
+
+  flushed = flush_buffer (bstream, cancellable, error);
+  if (!flushed)
+    return FALSE;
+  return g_seekable_truncate (base_stream_seekable, offset, cancellable, error);
+}
+
 /* ************************** */
 /* Async stuff implementation */
 /* ************************** */
@@ -540,9 +646,10 @@ free_flush_data (gpointer data)
  * and so closing and writing is just a special
  * case of flushing + some addition stuff */
 static void
-flush_buffer_thread (GSimpleAsyncResult *result,
-                     GObject            *object,
-                     GCancellable       *cancellable)
+flush_buffer_thread (GTask        *task,
+                     gpointer      object,
+                     gpointer      task_data,
+                     GCancellable *cancellable)
 {
   GBufferedOutputStream *stream;
   GOutputStream *base_stream;
@@ -551,7 +658,7 @@ flush_buffer_thread (GSimpleAsyncResult *result,
   GError        *error = NULL;
 
   stream = G_BUFFERED_OUTPUT_STREAM (object);
-  fdata = g_simple_async_result_get_op_res_gpointer (result);
+  fdata = task_data;
   base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream;
 
   res = flush_buffer (stream, cancellable, &error);
@@ -577,106 +684,9 @@ flush_buffer_thread (GSimpleAsyncResult *result,
     }
 
   if (res == FALSE)
-    {
-      g_simple_async_result_set_from_error (result, error);
-      g_error_free (error);
-    }
-}
-
-typedef struct {
-    
-  FlushData fdata;
-
-  gsize  count;
-  const void  *buffer;
-
-} WriteData;
-
-static void 
-free_write_data (gpointer data)
-{
-  g_slice_free (WriteData, data);
-}
-
-static void
-g_buffered_output_stream_write_async (GOutputStream        *stream,
-                                      const void           *buffer,
-                                      gsize                 count,
-                                      int                   io_priority,
-                                      GCancellable         *cancellable,
-                                      GAsyncReadyCallback   callback,
-                                      gpointer              data)
-{
-  GBufferedOutputStream *buffered_stream;
-  GBufferedOutputStreamPrivate *priv;
-  GSimpleAsyncResult *res;
-  WriteData *wdata;
-
-  buffered_stream = G_BUFFERED_OUTPUT_STREAM (stream);
-  priv = buffered_stream->priv;
-
-  wdata = g_slice_new (WriteData);
-  wdata->count  = count;
-  wdata->buffer = buffer;
-
-  res = g_simple_async_result_new (G_OBJECT (stream),
-                                   callback,
-                                   data,
-                                   g_buffered_output_stream_write_async);
-
-  g_simple_async_result_set_op_res_gpointer (res, wdata, free_write_data);
-
-  /* if we have space left directly call the
-   * callback (from idle) otherwise schedule a buffer 
-   * flush in the thread. In both cases the actual
-   * copying of the data to the buffer will be done in
-   * the write_finish () func since that should
-   * be fast enough */
-  if (priv->len - priv->pos > 0)
-    {
-      g_simple_async_result_complete_in_idle (res);
-    }
+    g_task_return_error (task, error);
   else
-    {
-      wdata->fdata.flush_stream = FALSE;
-      wdata->fdata.close_stream = FALSE;
-      g_simple_async_result_run_in_thread (res, 
-                                           flush_buffer_thread, 
-                                           io_priority,
-                                           cancellable);
-      g_object_unref (res);
-    }
-}
-
-static gssize
-g_buffered_output_stream_write_finish (GOutputStream        *stream,
-                                       GAsyncResult         *result,
-                                       GError              **error)
-{
-  GBufferedOutputStreamPrivate *priv;
-  GBufferedOutputStream        *buffered_stream;
-  GSimpleAsyncResult *simple;
-  WriteData          *wdata;
-  gssize              count;
-
-  simple = G_SIMPLE_ASYNC_RESULT (result);
-  buffered_stream = G_BUFFERED_OUTPUT_STREAM (stream);
-  priv = buffered_stream->priv;
-
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == 
-            g_buffered_output_stream_write_async);
-
-  wdata = g_simple_async_result_get_op_res_gpointer (simple);
-
-  /* Now do the real copying of data to the buffer */
-  count = priv->len - priv->pos; 
-  count = MIN (wdata->count, count);
-
-  memcpy (priv->buffer + priv->pos, wdata->buffer, count);
-  
-  priv->pos += count;
-
-  return count;
+    g_task_return_boolean (task, TRUE);
 }
 
 static void
@@ -686,25 +696,19 @@ g_buffered_output_stream_flush_async (GOutputStream        *stream,
                                       GAsyncReadyCallback   callback,
                                       gpointer              data)
 {
-  GSimpleAsyncResult *res;
-  FlushData          *fdata;
+  GTask *task;
+  FlushData *fdata;
 
   fdata = g_slice_new (FlushData);
   fdata->flush_stream = TRUE;
   fdata->close_stream = FALSE;
 
-  res = g_simple_async_result_new (G_OBJECT (stream),
-                                   callback,
-                                   data,
-                                   g_buffered_output_stream_flush_async);
-
-  g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data);
+  task = g_task_new (stream, cancellable, callback, data);
+  g_task_set_task_data (task, fdata, free_flush_data);
+  g_task_set_priority (task, io_priority);
 
-  g_simple_async_result_run_in_thread (res, 
-                                       flush_buffer_thread, 
-                                       io_priority,
-                                       cancellable);
-  g_object_unref (res);
+  g_task_run_in_thread (task, flush_buffer_thread);
+  g_object_unref (task);
 }
 
 static gboolean
@@ -712,14 +716,9 @@ g_buffered_output_stream_flush_finish (GOutputStream        *stream,
                                        GAsyncResult         *result,
                                        GError              **error)
 {
-  GSimpleAsyncResult *simple;
+  g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
 
-  simple = G_SIMPLE_ASYNC_RESULT (result);
-
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == 
-            g_buffered_output_stream_flush_async);
-
-  return TRUE;
+  return g_task_propagate_boolean (G_TASK (result), error);
 }
 
 static void
@@ -729,24 +728,18 @@ g_buffered_output_stream_close_async (GOutputStream        *stream,
                                       GAsyncReadyCallback   callback,
                                       gpointer              data)
 {
-  GSimpleAsyncResult *res;
-  FlushData          *fdata;
+  GTask *task;
+  FlushData *fdata;
 
   fdata = g_slice_new (FlushData);
   fdata->close_stream = TRUE;
 
-  res = g_simple_async_result_new (G_OBJECT (stream),
-                                   callback,
-                                   data,
-                                   g_buffered_output_stream_close_async);
-
-  g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data);
+  task = g_task_new (stream, cancellable, callback, data);
+  g_task_set_task_data (task, fdata, free_flush_data);
+  g_task_set_priority (task, io_priority);
 
-  g_simple_async_result_run_in_thread (res, 
-                                       flush_buffer_thread, 
-                                       io_priority,
-                                       cancellable);
-  g_object_unref (res);
+  g_task_run_in_thread (task, flush_buffer_thread);
+  g_object_unref (task);
 }
 
 static gboolean
@@ -754,15 +747,7 @@ g_buffered_output_stream_close_finish (GOutputStream        *stream,
                                        GAsyncResult         *result,
                                        GError              **error)
 {
-  GSimpleAsyncResult *simple;
+  g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
 
-  simple = G_SIMPLE_ASYNC_RESULT (result);
-
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == 
-            g_buffered_output_stream_close_async);
-
-  return TRUE;
+  return g_task_propagate_boolean (G_TASK (result), error);
 }
-
-#define __G_BUFFERED_OUTPUT_STREAM_C__
-#include "gioaliasdef.c"