X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgbufferedoutputstream.c;h=ac9b45f053c0341a0fa5f19d27742f6a4f71d66d;hb=4482977238ae80f64c2fe318d1500f4662c73980;hp=020d753495138467fb5b43b02b9a036535e699ff;hpb=e919f0198b8e2106313eab55af29872c83fa6dc9;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gbufferedoutputstream.c b/gio/gbufferedoutputstream.c index 020d753..ac9b45f 100644 --- a/gio/gbufferedoutputstream.c +++ b/gio/gbufferedoutputstream.c @@ -13,25 +13,24 @@ * 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 . * * Author: Christian Kellner */ -#include +#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 - /** * SECTION:gbufferedoutputstream * @short_description: Buffered Output Stream + * @include: gio/gio.h * @see_also: #GFilterOutputStream, #GOutputStream * * Buffered output stream implements #GFilterOutputStream and provides @@ -89,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, @@ -116,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 @@ -126,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; @@ -135,11 +139,9 @@ g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass) object_class->finalize = g_buffered_output_stream_finalize; ostream_class = G_OUTPUT_STREAM_CLASS (klass); - ostream_class->write = g_buffered_output_stream_write; + ostream_class->write_fn = g_buffered_output_stream_write; ostream_class->flush = g_buffered_output_stream_flush; - ostream_class->close = 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->close_fn = g_buffered_output_stream_close; 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; @@ -153,7 +155,7 @@ g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass) 1, G_MAXUINT, DEFAULT_BUFFER_SIZE, - G_PARAM_READWRITE| + G_PARAM_READWRITE|G_PARAM_CONSTRUCT| G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); g_object_class_install_property (object_class, @@ -248,6 +250,9 @@ g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream) * @auto_grow: a #gboolean. * * Sets whether or not the @stream's buffer should automatically grow. + * If @auto_grow is true, then each write will just make the buffer + * larger, and you must manually flush the buffer to actually write out + * the data to the underlying stream. **/ void g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream, @@ -331,17 +336,23 @@ g_buffered_output_stream_finalize (GObject *object) g_free (priv->buffer); - if (G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize) - (*G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize) (object); + G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize (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; } /** @@ -377,7 +388,7 @@ g_buffered_output_stream_new (GOutputStream *base_stream) **/ GOutputStream * g_buffered_output_stream_new_sized (GOutputStream *base_stream, - guint size) + gsize size) { GOutputStream *stream; @@ -418,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; @@ -471,12 +482,10 @@ g_buffered_output_stream_flush (GOutputStream *stream, GError **error) { GBufferedOutputStream *bstream; - GBufferedOutputStreamPrivate *priv; GOutputStream *base_stream; gboolean res; bstream = G_BUFFERED_OUTPUT_STREAM (stream); - priv = bstream->priv; base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; res = flush_buffer (bstream, cancellable, error); @@ -495,25 +504,123 @@ g_buffered_output_stream_close (GOutputStream *stream, GError **error) { GBufferedOutputStream *bstream; - GBufferedOutputStreamPrivate *priv; GOutputStream *base_stream; gboolean res; bstream = G_BUFFERED_OUTPUT_STREAM (stream); - priv = bstream->priv; base_stream = G_FILTER_OUTPUT_STREAM (bstream)->base_stream; - res = flush_buffer (bstream, cancellable, error); - /* report the first error but still close the stream */ - if (res) - res = g_output_stream_close (base_stream, cancellable, error); - else - g_output_stream_close (base_stream, cancellable, NULL); + if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) + { + /* report the first error but still close the stream */ + if (res) + res = g_output_stream_close (base_stream, cancellable, error); + else + g_output_stream_close (base_stream, cancellable, NULL); + } 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 */ /* ************************** */ @@ -539,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; @@ -550,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); @@ -566,113 +674,19 @@ flush_buffer_thread (GSimpleAsyncResult *result, /* if flushing the buffer or the stream returned * an error report that first error but still try * close the stream */ - if (res == FALSE) - g_output_stream_close (base_stream, cancellable, NULL); - else - res = g_output_stream_close (base_stream, cancellable, &error); + if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) + { + if (res == FALSE) + g_output_stream_close (base_stream, cancellable, NULL); + else + res = g_output_stream_close (base_stream, cancellable, &error); + } } 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_assert (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 @@ -682,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); + 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_set_op_res_gpointer (res, fdata, free_flush_data); - - 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 @@ -708,14 +716,9 @@ g_buffered_output_stream_flush_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; - - simple = G_SIMPLE_ASYNC_RESULT (result); + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); - g_assert (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 @@ -725,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 @@ -750,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_assert (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); } - -#define __G_BUFFERED_OUTPUT_STREAM_C__ -#include "gioaliasdef.c"