X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgfileoutputstream.c;h=2754405052f08708da8692f5b1211c296e41342c;hb=25990eb2b6da94e1d03631eab8a952ef84cb9986;hp=6dc332e90d42905fd004b254c90249b302009c1e;hpb=3d8579f93aaf909b6dcf6d4e63a757aac5e85942;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gfileoutputstream.c b/gio/gfileoutputstream.c index 6dc332e..2754405 100644 --- a/gio/gfileoutputstream.c +++ b/gio/gfileoutputstream.c @@ -13,30 +13,43 @@ * 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: Alexander Larsson */ -#include +#include "config.h" #include #include #include -#include "gsimpleasyncresult.h" +#include "gasyncresult.h" +#include "gtask.h" +#include "gcancellable.h" +#include "gioerror.h" #include "glibintl.h" -#include "gioalias.h" /** * SECTION:gfileoutputstream - * @short_description: file output streaming operations + * @short_description: File output streaming operations + * @include: gio/gio.h * @see_also: #GOutputStream, #GDataOutputStream, #GSeekable * - * + * GFileOutputStream provides output streams that write their + * content to a file. + * + * GFileOutputStream implements #GSeekable, which allows the output + * stream to jump to arbitrary positions in the file and to truncate + * the file, provided the filesystem of the file supports these + * operations. * + * To find the position of a file output stream, use g_seekable_tell(). + * To find out if a file output stream supports seeking, use + * g_seekable_can_seek().To position a file output stream, use + * g_seekable_seek(). To find out if a file output stream supports + * truncating, use g_seekable_can_truncate(). To truncate a file output + * stream, use g_seekable_truncate(). **/ static void g_file_output_stream_seekable_iface_init (GSeekableIface *iface); @@ -53,7 +66,7 @@ static gboolean g_file_output_stream_seekable_truncate (GSeekable GCancellable *cancellable, GError **error); static void g_file_output_stream_real_query_info_async (GFileOutputStream *stream, - char *attributes, + const char *attributes, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -62,19 +75,18 @@ static GFileInfo *g_file_output_stream_real_query_info_finish (GFileOutputStream GAsyncResult *result, GError **error); -G_DEFINE_TYPE_WITH_CODE (GFileOutputStream, g_file_output_stream, G_TYPE_OUTPUT_STREAM, - G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, - g_file_output_stream_seekable_iface_init)); - struct _GFileOutputStreamPrivate { GAsyncReadyCallback outstanding_callback; }; +G_DEFINE_TYPE_WITH_CODE (GFileOutputStream, g_file_output_stream, G_TYPE_OUTPUT_STREAM, + G_ADD_PRIVATE (GFileOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + g_file_output_stream_seekable_iface_init)); + static void g_file_output_stream_class_init (GFileOutputStreamClass *klass) { - g_type_class_add_private (klass, sizeof (GFileOutputStreamPrivate)); - klass->query_info_async = g_file_output_stream_real_query_info_async; klass->query_info_finish = g_file_output_stream_real_query_info_finish; } @@ -86,15 +98,13 @@ g_file_output_stream_seekable_iface_init (GSeekableIface *iface) iface->can_seek = g_file_output_stream_seekable_can_seek; iface->seek = g_file_output_stream_seekable_seek; iface->can_truncate = g_file_output_stream_seekable_can_truncate; - iface->truncate = g_file_output_stream_seekable_truncate; + iface->truncate_fn = g_file_output_stream_seekable_truncate; } static void g_file_output_stream_init (GFileOutputStream *stream) { - stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, - G_TYPE_FILE_OUTPUT_STREAM, - GFileOutputStreamPrivate); + stream->priv = g_file_output_stream_get_instance_private (stream); } /** @@ -122,11 +132,11 @@ g_file_output_stream_init (GFileOutputStream *stream) * 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. + * Returns: (transfer full): a #GFileInfo for the @stream, or %NULL on error. **/ GFileInfo * g_file_output_stream_query_info (GFileOutputStream *stream, - char *attributes, + const char *attributes, GCancellable *cancellable, GError **error) { @@ -138,38 +148,25 @@ g_file_output_stream_query_info (GFileOutputStream *stream, output_stream = G_OUTPUT_STREAM (stream); - if (g_output_stream_is_closed (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); - return NULL; - } - - if (g_output_stream_has_pending (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); - return NULL; - } + if (!g_output_stream_set_pending (output_stream, error)) + return NULL; info = NULL; - g_output_stream_set_pending (output_stream, TRUE); - if (cancellable) - g_push_current_cancellable (cancellable); + g_cancellable_push_current (cancellable); class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); if (class->query_info) info = class->query_info (stream, attributes, cancellable, error); else - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Stream doesn't support query_info")); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Stream doesn't support query_info")); if (cancellable) - g_pop_current_cancellable (cancellable); + g_cancellable_pop_current (cancellable); - g_output_stream_set_pending (output_stream, FALSE); + g_output_stream_clear_pending (output_stream); return info; } @@ -181,7 +178,7 @@ async_ready_callback_wrapper (GObject *source_object, { GFileOutputStream *stream = G_FILE_OUTPUT_STREAM (source_object); - g_output_stream_set_pending (G_OUTPUT_STREAM (stream), FALSE); + g_output_stream_clear_pending (G_OUTPUT_STREAM (stream)); if (stream->priv->outstanding_callback) (*stream->priv->outstanding_callback) (source_object, res, user_data); g_object_unref (stream); @@ -191,8 +188,7 @@ async_ready_callback_wrapper (GObject *source_object, * g_file_output_stream_query_info_async: * @stream: a #GFileOutputStream. * @attributes: a file attribute query string. - * @io_priority: the I/O priority - * of the request. + * @io_priority: the [I/O priority][gio-GIOScheduler] 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 @@ -207,7 +203,7 @@ async_ready_callback_wrapper (GObject *source_object, **/ void g_file_output_stream_query_info_async (GFileOutputStream *stream, - char *attributes, + const char *attributes, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -215,38 +211,26 @@ g_file_output_stream_query_info_async (GFileOutputStream *stream, { GFileOutputStreamClass *klass; GOutputStream *output_stream; + GError *error = NULL; g_return_if_fail (G_IS_FILE_OUTPUT_STREAM (stream)); output_stream = G_OUTPUT_STREAM (stream); - if (g_output_stream_is_closed (output_stream)) - { - g_simple_async_report_error_in_idle (G_OBJECT (stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); - return; - } - - if (g_output_stream_has_pending (output_stream)) + if (!g_output_stream_set_pending (output_stream, &error)) { - g_simple_async_report_error_in_idle (G_OBJECT (stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); + g_task_report_error (stream, callback, user_data, + g_file_output_stream_query_info_async, + error); return; } klass = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); - g_output_stream_set_pending (output_stream, TRUE); stream->priv->outstanding_callback = callback; g_object_ref (stream); klass->query_info_async (stream, attributes, io_priority, cancellable, - async_ready_callback_wrapper, user_data); + async_ready_callback_wrapper, user_data); } /** @@ -258,25 +242,22 @@ g_file_output_stream_query_info_async (GFileOutputStream *stream, * Finalizes the asynchronous query started * by g_file_output_stream_query_info_async(). * - * Returns: A #GFileInfo for the finished query. + * Returns: (transfer full): A #GFileInfo for the finished query. **/ GFileInfo * g_file_output_stream_query_info_finish (GFileOutputStream *stream, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; GFileOutputStreamClass *class; g_return_val_if_fail (G_IS_FILE_OUTPUT_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; - } + if (g_async_result_legacy_propagate_error (result, error)) + return NULL; + else if (g_async_result_is_tagged (result, g_file_output_stream_query_info_async)) + return g_task_propagate_pointer (G_TASK (result), error); class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); return class->query_info_finish (stream, result, error); @@ -286,7 +267,9 @@ g_file_output_stream_query_info_finish (GFileOutputStream *stream, * g_file_output_stream_get_etag: * @stream: a #GFileOutputStream. * - * Gets the entity tag for the file output stream. + * 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. **/ @@ -316,15 +299,7 @@ g_file_output_stream_get_etag (GFileOutputStream *stream) return etag; } -/** - * g_file_output_stream_tell: - * @stream: a #GFileOutputStream. - * - * Gets the current location within the stream. - * - * Returns: a #goffset of the location within the stream. - **/ -goffset +static goffset g_file_output_stream_tell (GFileOutputStream *stream) { GFileOutputStreamClass *class; @@ -347,15 +322,7 @@ g_file_output_stream_seekable_tell (GSeekable *seekable) return g_file_output_stream_tell (G_FILE_OUTPUT_STREAM (seekable)); } -/** - * g_file_output_stream_can_seek: - * @stream: a #GFileOutputStream. - * - * Checks if the stream can be seeked. - * - * Returns: %TRUE if seeking is supported by the stream. - **/ -gboolean +static gboolean g_file_output_stream_can_seek (GFileOutputStream *stream) { GFileOutputStreamClass *class; @@ -382,19 +349,7 @@ g_file_output_stream_seekable_can_seek (GSeekable *seekable) return g_file_output_stream_can_seek (G_FILE_OUTPUT_STREAM (seekable)); } -/** - * g_file_output_stream_seek: - * @stream: a #GFileOutputStream. - * @offset: a #goffset to seek. - * @type: a #GSeekType. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: a #GError, %NULL to ignore. - * - * Seeks to a location in a file output stream. - * - * Returns: %TRUE if the seek was successful. %FALSE otherwise. - **/ -gboolean +static gboolean g_file_output_stream_seek (GFileOutputStream *stream, goffset offset, GSeekType type, @@ -410,38 +365,25 @@ g_file_output_stream_seek (GFileOutputStream *stream, output_stream = G_OUTPUT_STREAM (stream); class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); - if (g_output_stream_is_closed (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); - return FALSE; - } - - if (g_output_stream_has_pending (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); - return FALSE; - } - if (!class->seek) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Seek not supported on stream")); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Seek not supported on stream")); return FALSE; } - g_output_stream_set_pending (output_stream, TRUE); + if (!g_output_stream_set_pending (output_stream, error)) + return FALSE; if (cancellable) - g_push_current_cancellable (cancellable); + g_cancellable_push_current (cancellable); res = class->seek (stream, offset, type, cancellable, error); if (cancellable) - g_pop_current_cancellable (cancellable); + g_cancellable_pop_current (cancellable); - g_output_stream_set_pending (output_stream, FALSE); + g_output_stream_clear_pending (output_stream); return res; } @@ -457,15 +399,7 @@ g_file_output_stream_seekable_seek (GSeekable *seekable, offset, type, cancellable, error); } -/** - * g_file_output_stream_can_truncate: - * @stream: a #GFileOutputStream. - * - * Checks if the stream can be truncated. - * - * Returns: %TRUE if stream can be truncated. - **/ -gboolean +static gboolean g_file_output_stream_can_truncate (GFileOutputStream *stream) { GFileOutputStreamClass *class; @@ -476,7 +410,7 @@ g_file_output_stream_can_truncate (GFileOutputStream *stream) class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); can_truncate = FALSE; - if (class->truncate) + if (class->truncate_fn) { can_truncate = TRUE; if (class->can_truncate) @@ -492,18 +426,7 @@ g_file_output_stream_seekable_can_truncate (GSeekable *seekable) return g_file_output_stream_can_truncate (G_FILE_OUTPUT_STREAM (seekable)); } -/** - * g_file_output_stream_truncate: - * @stream: a #GFileOutputStream. - * @size: a #goffset to truncate the stream at. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: a #GError, %NULL to ignore. - * - * Truncates a file output stream. - * - * Returns: %TRUE if @stream is truncated successfully. - **/ -gboolean +static gboolean g_file_output_stream_truncate (GFileOutputStream *stream, goffset size, GCancellable *cancellable, @@ -518,38 +441,25 @@ g_file_output_stream_truncate (GFileOutputStream *stream, output_stream = G_OUTPUT_STREAM (stream); class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); - if (g_output_stream_is_closed (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); - return FALSE; - } - - if (g_output_stream_has_pending (output_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); - return FALSE; - } - - if (!class->truncate) + if (!class->truncate_fn) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Truncate not supported on stream")); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Truncate not supported on stream")); return FALSE; } - g_output_stream_set_pending (output_stream, TRUE); + if (!g_output_stream_set_pending (output_stream, error)) + return FALSE; if (cancellable) - g_push_current_cancellable (cancellable); + g_cancellable_push_current (cancellable); - res = class->truncate (stream, size, cancellable, error); + res = class->truncate_fn (stream, size, cancellable, error); if (cancellable) - g_pop_current_cancellable (cancellable); + g_cancellable_pop_current (cancellable); - g_output_stream_set_pending (output_stream, FALSE); + g_output_stream_clear_pending (output_stream); return res; } @@ -567,87 +477,55 @@ g_file_output_stream_seekable_truncate (GSeekable *seekable, * Default implementation of async ops * ********************************************/ -typedef struct { - char *attributes; - GFileInfo *info; -} QueryInfoAsyncData; - -static void -query_info_data_free (QueryInfoAsyncData *data) -{ - if (data->info) - g_object_unref (data->info); - g_free (data->attributes); - g_free (data); -} - static void -query_info_async_thread (GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) +query_info_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) { + GFileOutputStream *stream = source_object; + const char *attributes = task_data; GFileOutputStreamClass *class; GError *error = NULL; - QueryInfoAsyncData *data; - GFileInfo *info; - - data = g_simple_async_result_get_op_res_gpointer (res); + GFileInfo *info = NULL; - info = NULL; - - class = G_FILE_OUTPUT_STREAM_GET_CLASS (object); + class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); if (class->query_info) - info = class->query_info (G_FILE_OUTPUT_STREAM (object), data->attributes, cancellable, &error); + info = class->query_info (stream, attributes, cancellable, &error); else - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Stream doesn't support query_info")); + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Stream doesn't support query_info")); if (info == NULL) - { - g_simple_async_result_set_from_error (res, error); - g_error_free (error); - } + g_task_return_error (task, error); else - data->info = info; + g_task_return_pointer (task, info, g_object_unref); } static void g_file_output_stream_real_query_info_async (GFileOutputStream *stream, - char *attributes, + const char *attributes, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; - QueryInfoAsyncData *data; + GTask *task; - data = g_new0 (QueryInfoAsyncData, 1); - data->attributes = g_strdup (attributes); - - res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_file_output_stream_real_query_info_async); - g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_info_data_free); + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_task_data (task, g_strdup (attributes), g_free); + g_task_set_priority (task, io_priority); - g_simple_async_result_run_in_thread (res, query_info_async_thread, io_priority, cancellable); - g_object_unref (res); + g_task_run_in_thread (task, query_info_async_thread); + g_object_unref (task); } static GFileInfo * g_file_output_stream_real_query_info_finish (GFileOutputStream *stream, - GAsyncResult *res, - GError **error) + GAsyncResult *res, + GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - QueryInfoAsyncData *data; - - g_assert (g_simple_async_result_get_source_tag (simple) == g_file_output_stream_real_query_info_async); + g_return_val_if_fail (g_task_is_valid (res, stream), NULL); - data = g_simple_async_result_get_op_res_gpointer (simple); - if (data->info) - return g_object_ref (data->info); - - return NULL; + return g_task_propagate_pointer (G_TASK (res), error); } - -#define __G_FILE_OUTPUT_STREAM_C__ -#include "gioaliasdef.c"