X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=gio%2Fgfileenumerator.c;h=c0d40541a93b94fd45a045c29ee26aa86473bc6c;hb=2138deb07ebb7d7e541c0cd35b966e107d1bf800;hp=f9439d226f3a8e651dcba6cc738c0e01678ed571;hpb=7c36619d269284597d5df4f366b6389df9bcf617;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gfileenumerator.c b/gio/gfileenumerator.c index f9439d2..c0d4054 100644 --- a/gio/gfileenumerator.c +++ b/gio/gfileenumerator.c @@ -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 . * * Author: Alexander Larsson */ @@ -26,18 +24,24 @@ #include "gioscheduler.h" #include "gasyncresult.h" #include "gasynchelper.h" -#include "gsimpleasyncresult.h" #include "gioerror.h" #include "glibintl.h" -#include "gioalias.h" +struct _GFileEnumeratorPrivate { + /* TODO: Should be public for subclasses? */ + GFile *container; + guint closed : 1; + guint pending : 1; + GAsyncReadyCallback outstanding_callback; + GError *outstanding_error; +}; /** * SECTION:gfileenumerator * @short_description: Enumerated Files Routines * @include: gio/gio.h * - * #GFileEnumerator allows you to operate on a set of #GFiles, + * #GFileEnumerator allows you to operate on a set of #GFiles, * returning a #GFileInfo structure for each file enumerated (e.g. * g_file_enumerate_children() will return a #GFileEnumerator for each * of the children within a directory). @@ -45,9 +49,20 @@ * To get the next file's information from a #GFileEnumerator, use * g_file_enumerator_next_file() or its asynchronous version, * g_file_enumerator_next_files_async(). Note that the asynchronous - * version will return a list of #GFileInfos, whereas the + * version will return a list of #GFileInfos, whereas the * synchronous will only return the next file in the enumerator. * + * The ordering of returned files is unspecified for non-Unix + * platforms; for more information, see g_dir_read_name(). On Unix, + * when operating on local files, returned files will be sorted by + * inode number. Effectively you can assume that the ordering of + * returned files will be stable between successive calls (and + * applications) assuming the directory is unchanged. + * + * If your application needs a specific ordering, such as by name or + * modification time, you will have to implement that in your + * application code. + * * To close a #GFileEnumerator, use g_file_enumerator_close(), or * its asynchronous version, g_file_enumerator_close_async(). Once * a #GFileEnumerator is closed, no further actions may be performed @@ -55,16 +70,7 @@ * **/ -G_DEFINE_TYPE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT); - -struct _GFileEnumeratorPrivate { - /* TODO: Should be public for subclasses? */ - GFile *container; - guint closed : 1; - guint pending : 1; - GAsyncReadyCallback outstanding_callback; - GError *outstanding_error; -}; +G_DEFINE_TYPE_WITH_PRIVATE (GFileEnumerator, g_file_enumerator, G_TYPE_OBJECT) enum { PROP_0, @@ -141,9 +147,7 @@ static void g_file_enumerator_class_init (GFileEnumeratorClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (GFileEnumeratorPrivate)); - + gobject_class->set_property = g_file_enumerator_set_property; gobject_class->dispose = g_file_enumerator_dispose; gobject_class->finalize = g_file_enumerator_finalize; @@ -166,28 +170,30 @@ g_file_enumerator_class_init (GFileEnumeratorClass *klass) static void g_file_enumerator_init (GFileEnumerator *enumerator) { - enumerator->priv = G_TYPE_INSTANCE_GET_PRIVATE (enumerator, - G_TYPE_FILE_ENUMERATOR, - GFileEnumeratorPrivate); + enumerator->priv = g_file_enumerator_get_instance_private (enumerator); } /** * g_file_enumerator_next_file: * @enumerator: a #GFileEnumerator. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: location to store the error occuring, or %NULL to ignore + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: location to store the error occurring, or %NULL to ignore * * Returns information for the next file in the enumerated object. * Will block until the information is available. The #GFileInfo * returned from this function will contain attributes that match the * attribute string that was passed when the #GFileEnumerator was created. * + * See the documentation of #GFileEnumerator for information about the + * order of returned files. + * * On error, returns %NULL and sets @error to the error. If the * enumerator is at the end, %NULL will be returned and @error will * be unset. * - * Return value: A #GFileInfo or %NULL on error or end of enumerator. - * Free the returned object with g_object_unref() when no longer needed. + * Returns: (nullable) (transfer full): A #GFileInfo or %NULL on error + * or end of enumerator. Free the returned object with + * g_object_unref() when no longer needed. **/ GFileInfo * g_file_enumerator_next_file (GFileEnumerator *enumerator, @@ -239,8 +245,8 @@ g_file_enumerator_next_file (GFileEnumerator *enumerator, /** * g_file_enumerator_close: * @enumerator: a #GFileEnumerator. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: location to store the error occuring, or %NULL to ignore + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: location to store the error occurring, or %NULL to ignore * * Releases all resources used by this enumerator, making the * enumerator return %G_IO_ERROR_CLOSED on all calls. @@ -249,7 +255,7 @@ g_file_enumerator_next_file (GFileEnumerator *enumerator, * is dropped, but you might want to call this function to make * sure resources are released as early as possible. * - * Return value: #TRUE on success or #FALSE on error. + * Returns: #TRUE on success or #FALSE on error. **/ gboolean g_file_enumerator_close (GFileEnumerator *enumerator, @@ -304,15 +310,17 @@ next_async_callback_wrapper (GObject *source_object, * g_file_enumerator_next_files_async: * @enumerator: a #GFileEnumerator. * @num_files: the number of file info objects to request - * @io_priority: the io priority - * of the request. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @callback: a #GAsyncReadyCallback to call when the request is satisfied - * @user_data: the data to pass to callback function + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function * * Request information for a number of files from the enumerator asynchronously. * When all i/o for the operation is finished the @callback will be called with * the requested information. + + * See the documentation of #GFileEnumerator for information about the + * order of returned files. * * The callback can be called with less than @num_files files in case of error * or at the end of the enumerator. In case of a partial error the callback will @@ -336,7 +344,6 @@ g_file_enumerator_next_files_async (GFileEnumerator *enumerator, gpointer user_data) { GFileEnumeratorClass *class; - GSimpleAsyncResult *simple; g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator)); g_return_if_fail (enumerator != NULL); @@ -344,32 +351,30 @@ g_file_enumerator_next_files_async (GFileEnumerator *enumerator, if (num_files == 0) { - simple = g_simple_async_result_new (G_OBJECT (enumerator), - callback, - user_data, - g_file_enumerator_next_files_async); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + GTask *task; + + task = g_task_new (enumerator, cancellable, callback, user_data); + g_task_set_source_tag (task, g_file_enumerator_next_files_async); + g_task_return_pointer (task, NULL, NULL); + g_object_unref (task); return; } if (enumerator->priv->closed) { - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_CLOSED, - _("File enumerator is already closed")); + g_task_report_new_error (enumerator, callback, user_data, + g_file_enumerator_next_files_async, + G_IO_ERROR, G_IO_ERROR_CLOSED, + _("File enumerator is already closed")); return; } if (enumerator->priv->pending) { - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_PENDING, - _("File enumerator has outstanding operation")); + g_task_report_new_error (enumerator, callback, user_data, + g_file_enumerator_next_files_async, + G_IO_ERROR, G_IO_ERROR_PENDING, + _("File enumerator has outstanding operation")); return; } @@ -386,12 +391,12 @@ g_file_enumerator_next_files_async (GFileEnumerator *enumerator, * g_file_enumerator_next_files_finish: * @enumerator: a #GFileEnumerator. * @result: a #GAsyncResult. - * @error: a #GError location to store the error occuring, or %NULL to + * @error: a #GError location to store the error occurring, or %NULL to * ignore. * * Finishes the asynchronous operation started with g_file_enumerator_next_files_async(). * - * Returns: (transfer full) (element-type FileInfo): a #GList of #GFileInfos. You must free the list with + * Returns: (transfer full) (element-type Gio.FileInfo): a #GList of #GFileInfos. You must free the list with * g_list_free() and unref the infos with g_object_unref() when you're * done with them. **/ @@ -401,21 +406,14 @@ g_file_enumerator_next_files_finish (GFileEnumerator *enumerator, GError **error) { GFileEnumeratorClass *class; - GSimpleAsyncResult *simple; g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), 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; - - /* Special case read of 0 files */ - if (g_simple_async_result_get_source_tag (simple) == g_file_enumerator_next_files_async) - return NULL; - } + if (g_async_result_legacy_propagate_error (result, error)) + return NULL; + else if (g_async_result_is_tagged (result, g_file_enumerator_next_files_async)) + return g_task_propagate_pointer (G_TASK (result), error); class = G_FILE_ENUMERATOR_GET_CLASS (enumerator); return class->next_files_finish (enumerator, result, error); @@ -438,11 +436,10 @@ close_async_callback_wrapper (GObject *source_object, /** * g_file_enumerator_close_async: * @enumerator: a #GFileEnumerator. - * @io_priority: the I/O priority - * of the request. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @callback: a #GAsyncReadyCallback to call when the request is satisfied - * @user_data: the data to pass to callback function + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function * * Asynchronously closes the file enumerator. * @@ -464,21 +461,19 @@ g_file_enumerator_close_async (GFileEnumerator *enumerator, if (enumerator->priv->closed) { - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_CLOSED, - _("File enumerator is already closed")); + g_task_report_new_error (enumerator, callback, user_data, + g_file_enumerator_close_async, + G_IO_ERROR, G_IO_ERROR_CLOSED, + _("File enumerator is already closed")); return; } if (enumerator->priv->pending) { - g_simple_async_report_error_in_idle (G_OBJECT (enumerator), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_PENDING, - _("File enumerator has outstanding operation")); + g_task_report_new_error (enumerator, callback, user_data, + g_file_enumerator_close_async, + G_IO_ERROR, G_IO_ERROR_PENDING, + _("File enumerator has outstanding operation")); return; } @@ -495,7 +490,7 @@ g_file_enumerator_close_async (GFileEnumerator *enumerator, * g_file_enumerator_close_finish: * @enumerator: a #GFileEnumerator. * @result: a #GAsyncResult. - * @error: a #GError location to store the error occuring, or %NULL to + * @error: a #GError location to store the error occurring, or %NULL to * ignore. * * Finishes closing a file enumerator, started from g_file_enumerator_close_async(). @@ -516,19 +511,16 @@ g_file_enumerator_close_finish (GFileEnumerator *enumerator, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; GFileEnumeratorClass *class; g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), FALSE); g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE); - if (G_IS_SIMPLE_ASYNC_RESULT (result)) - { - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - } - + if (g_async_result_legacy_propagate_error (result, error)) + return FALSE; + else if (g_async_result_is_tagged (result, g_file_enumerator_close_async)) + return g_task_propagate_boolean (G_TASK (result), error); + class = G_FILE_ENUMERATOR_GET_CLASS (enumerator); return class->close_finish (enumerator, result, error); } @@ -587,7 +579,7 @@ g_file_enumerator_set_pending (GFileEnumerator *enumerator, * * Get the #GFile container which is being enumerated. * - * Returns: the #GFile which is being enumerated. + * Returns: (transfer none): the #GFile which is being enumerated. * * Since: 2.18 */ @@ -599,41 +591,60 @@ g_file_enumerator_get_container (GFileEnumerator *enumerator) return enumerator->priv->container; } -typedef struct { - int num_files; - GList *files; -} NextAsyncOp; +/** + * g_file_enumerator_get_child: + * @enumerator: a #GFileEnumerator + * @info: a #GFileInfo gotten from g_file_enumerator_next_file() + * or the async equivalents. + * + * Return a new #GFile which refers to the file named by @info in the source + * directory of @enumerator. This function is primarily intended to be used + * inside loops with g_file_enumerator_next_file(). + * + * This is a convenience method that's equivalent to: + * |[ + * gchar *name = g_file_info_get_name (info); + * GFile *child = g_file_get_child (g_file_enumerator_get_container (enumr), + * name); + * ]| + * + * Returns: (transfer full): a #GFile for the #GFileInfo passed it. + * + * Since: 2.36 + */ +GFile * +g_file_enumerator_get_child (GFileEnumerator *enumerator, + GFileInfo *info) +{ + g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL); + + return g_file_get_child (enumerator->priv->container, + g_file_info_get_name (info)); +} static void -next_async_op_free (NextAsyncOp *op) +next_async_op_free (GList *files) { - /* Free the list, if finish wasn't called */ - g_list_foreach (op->files, (GFunc)g_object_unref, NULL); - g_list_free (op->files); - - g_free (op); + g_list_free_full (files, g_object_unref); } - - static void -next_files_thread (GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) +next_files_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) { - NextAsyncOp *op; + GFileEnumerator *enumerator = source_object; + int num_files = GPOINTER_TO_INT (task_data); GFileEnumeratorClass *class; + GList *files = NULL; GError *error = NULL; GFileInfo *info; - GFileEnumerator *enumerator; int i; - enumerator = G_FILE_ENUMERATOR (object); - op = g_simple_async_result_get_op_res_gpointer (res); - - class = G_FILE_ENUMERATOR_GET_CLASS (object); + class = G_FILE_ENUMERATOR_GET_CLASS (enumerator); - for (i = 0; i < op->num_files; i++) + for (i = 0; i < num_files; i++) { if (g_cancellable_set_error_if_cancelled (cancellable, &error)) info = NULL; @@ -645,8 +656,7 @@ next_files_thread (GSimpleAsyncResult *res, /* If we get an error after first file, return that on next operation */ if (error != NULL && i > 0) { - if (error->domain == G_IO_ERROR && - error->code == G_IO_ERROR_CANCELLED) + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_error_free (error); /* Never propagate cancel errors to other call */ else enumerator->priv->outstanding_error = error; @@ -656,8 +666,13 @@ next_files_thread (GSimpleAsyncResult *res, break; } else - op->files = g_list_prepend (op->files, info); + files = g_list_prepend (files, info); } + + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free); } static void @@ -668,19 +683,14 @@ g_file_enumerator_real_next_files_async (GFileEnumerator *enumerator, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; - NextAsyncOp *op; - - op = g_new0 (NextAsyncOp, 1); + GTask *task; - op->num_files = num_files; - op->files = NULL; + task = g_task_new (enumerator, cancellable, callback, user_data); + g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL); + g_task_set_priority (task, io_priority); - res = g_simple_async_result_new (G_OBJECT (enumerator), callback, user_data, g_file_enumerator_real_next_files_async); - g_simple_async_result_set_op_res_gpointer (res, op, (GDestroyNotify) next_async_op_free); - - g_simple_async_result_run_in_thread (res, next_files_thread, io_priority, cancellable); - g_object_unref (res); + g_task_run_in_thread (task, next_files_thread); + g_object_unref (task); } static GList * @@ -688,44 +698,30 @@ g_file_enumerator_real_next_files_finish (GFileEnumerator *enumer GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - NextAsyncOp *op; - GList *res; - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == - g_file_enumerator_real_next_files_async); + g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL); - op = g_simple_async_result_get_op_res_gpointer (simple); - - res = op->files; - op->files = NULL; - return res; + return g_task_propagate_pointer (G_TASK (result), error); } static void -close_async_thread (GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) +close_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) { + GFileEnumerator *enumerator = source_object; GFileEnumeratorClass *class; GError *error = NULL; gboolean result; - /* Auto handling of cancelation disabled, and ignore - cancellation, since we want to close things anyway, although - possibly in a quick-n-dirty way. At least we never want to leak - open handles */ - - class = G_FILE_ENUMERATOR_GET_CLASS (object); - result = class->close_fn (G_FILE_ENUMERATOR (object), cancellable, &error); - if (!result) - { - g_simple_async_result_set_from_error (res, error); - g_error_free (error); - } + class = G_FILE_ENUMERATOR_GET_CLASS (enumerator); + result = class->close_fn (enumerator, cancellable, &error); + if (result) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); } - static void g_file_enumerator_real_close_async (GFileEnumerator *enumerator, int io_priority, @@ -733,20 +729,13 @@ g_file_enumerator_real_close_async (GFileEnumerator *enumerator, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *res; - - res = g_simple_async_result_new (G_OBJECT (enumerator), - callback, - user_data, - g_file_enumerator_real_close_async); + GTask *task; - g_simple_async_result_set_handle_cancellation (res, FALSE); + task = g_task_new (enumerator, cancellable, callback, user_data); + g_task_set_priority (task, io_priority); - g_simple_async_result_run_in_thread (res, - close_async_thread, - io_priority, - cancellable); - g_object_unref (res); + g_task_run_in_thread (task, close_async_thread); + g_object_unref (task); } static gboolean @@ -754,11 +743,7 @@ g_file_enumerator_real_close_finish (GFileEnumerator *enumerator, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == - g_file_enumerator_real_close_async); - return TRUE; -} + g_return_val_if_fail (g_task_is_valid (result, enumerator), FALSE); -#define __G_FILE_ENUMERATOR_C__ -#include "gioaliasdef.c" + return g_task_propagate_boolean (G_TASK (result), error); +}