mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
file: add g_file_load_bytes()
This adds g_file_load_bytes() to make it more convenient to load the contents of a GFile as GBytes. It includes a special casing for gresources to increase the chances that the GBytes directly references the embedded data instead of copying to the heap. https://bugzilla.gnome.org/show_bug.cgi?id=790272
This commit is contained in:
parent
5464461e4c
commit
2227918dfd
@ -184,6 +184,9 @@ g_file_mount_enclosing_volume_finish
|
||||
g_file_monitor_directory
|
||||
g_file_monitor_file
|
||||
g_file_monitor
|
||||
g_file_load_bytes
|
||||
g_file_load_bytes_async
|
||||
g_file_load_bytes_finish
|
||||
g_file_load_contents
|
||||
g_file_load_contents_async
|
||||
g_file_load_contents_finish
|
||||
|
188
gio/gfile.c
188
gio/gfile.c
@ -8092,3 +8092,191 @@ g_file_supports_thread_contexts (GFile *file)
|
||||
iface = G_FILE_GET_IFACE (file);
|
||||
return iface->supports_thread_contexts;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_file_load_bytes:
|
||||
* @file: a #GFile
|
||||
* @cancellable: (nullable): a #GCancellable or %NULL
|
||||
* @etag_out: (out) (nullable) (optional): a location to place the current
|
||||
* entity tag for the file, or %NULL if the entity tag is not needed
|
||||
* @error: a location for a #GError or %NULL
|
||||
*
|
||||
* Loads the contents of @file and returns it as #GBytes.
|
||||
*
|
||||
* If @file is a resource:// based URI, the resulting bytes will reference the
|
||||
* embedded resource instead of a copy. Otherwise, this is equivalent to calling
|
||||
* g_file_load_contents() and g_bytes_new_take().
|
||||
*
|
||||
* For resources, @etag_out will be set to %NULL.
|
||||
*
|
||||
* The data contained in the resulting #GBytes is always zero-terminated, but
|
||||
* this is not included in the #GBytes length. The resulting #GBytes should be
|
||||
* freed with g_bytes_unref() when no longer in use.
|
||||
*
|
||||
* Returns: (transfer full): a #GBytes or %NULL and @error is set
|
||||
*
|
||||
* Since: 2.56
|
||||
*/
|
||||
GBytes *
|
||||
g_file_load_bytes (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
gchar **etag_out,
|
||||
GError **error)
|
||||
{
|
||||
gchar *contents;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (etag_out != NULL)
|
||||
*etag_out = NULL;
|
||||
|
||||
if (g_file_has_uri_scheme (file, "resource"))
|
||||
{
|
||||
GBytes *bytes;
|
||||
gchar *uri, *unescaped;
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
unescaped = g_uri_unescape_string (uri + strlen ("resource://"), NULL);
|
||||
g_free (uri);
|
||||
|
||||
bytes = g_resources_lookup_data (unescaped, G_RESOURCE_LOOKUP_FLAGS_NONE, error);
|
||||
g_free (unescaped);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* contents is guaranteed to be \0 terminated */
|
||||
if (g_file_load_contents (file, cancellable, &contents, &len, etag_out, error))
|
||||
return g_bytes_new_take (g_steal_pointer (&contents), len);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
g_file_load_bytes_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFile *file = G_FILE (object);
|
||||
GTask *task = user_data;
|
||||
GError *error = NULL;
|
||||
gchar *etag = NULL;
|
||||
gchar *contents = NULL;
|
||||
gsize len = 0;
|
||||
|
||||
g_file_load_contents_finish (file, result, &contents, &len, &etag, &error);
|
||||
g_task_set_task_data (task, g_steal_pointer (&etag), g_free);
|
||||
|
||||
if (error != NULL)
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
g_task_return_pointer (task,
|
||||
g_bytes_new_take (g_steal_pointer (&contents), len),
|
||||
(GDestroyNotify)g_bytes_unref);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_file_load_bytes_async:
|
||||
* @file: a #GFile
|
||||
* @cancellable: (nullable): a #GCancellable or %NULL
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the
|
||||
* request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously loads the contents of @file as #GBytes.
|
||||
*
|
||||
* If @file is a resource:// based URI, the resulting bytes will reference the
|
||||
* embedded resource instead of a copy. Otherwise, this is equivalent to calling
|
||||
* g_file_load_contents_async() and g_bytes_new_take().
|
||||
*
|
||||
* @callback should call g_file_load_bytes_finish() to get the result of this
|
||||
* asynchronous operation.
|
||||
*
|
||||
* See g_file_load_bytes() for more information.
|
||||
*
|
||||
* Since: 2.56
|
||||
*/
|
||||
void
|
||||
g_file_load_bytes_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GBytes *bytes;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (file, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_file_load_bytes_async);
|
||||
|
||||
if (!g_file_has_uri_scheme (file, "resource"))
|
||||
{
|
||||
g_file_load_contents_async (file,
|
||||
cancellable,
|
||||
g_file_load_bytes_cb,
|
||||
g_steal_pointer (&task));
|
||||
return;
|
||||
}
|
||||
|
||||
bytes = g_file_load_bytes (file, cancellable, NULL, &error);
|
||||
|
||||
if (bytes == NULL)
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&bytes),
|
||||
(GDestroyNotify)g_bytes_unref);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_file_load_bytes_finish:
|
||||
* @file: a #GFile
|
||||
* @result: a #GAsyncResult provided to the callback
|
||||
* @etag_out: (out) (nullable) (optional): a location to place the current
|
||||
* entity tag for the file, or %NULL if the entity tag is not needed
|
||||
* @error: a location for a #GError, or %NULL
|
||||
*
|
||||
* Completes an asynchronous request to g_file_load_bytes_async().
|
||||
*
|
||||
* For resources, @etag_out will be set to %NULL.
|
||||
*
|
||||
* The data contained in the resulting #GBytes is always zero-terminated, but
|
||||
* this is not included in the #GBytes length. The resulting #GBytes should be
|
||||
* freed with g_bytes_unref() when no longer in use.
|
||||
*
|
||||
* See g_file_load_bytes() for more information.
|
||||
*
|
||||
* Returns: (transfer full): a #GBytes or %NULL and @error is set
|
||||
*
|
||||
* Since: 2.56
|
||||
*/
|
||||
GBytes *
|
||||
g_file_load_bytes_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
gchar **etag_out,
|
||||
GError **error)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||
g_return_val_if_fail (g_task_is_valid (G_TASK (result), file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
bytes = g_task_propagate_pointer (G_TASK (result), error);
|
||||
|
||||
if (etag_out != NULL)
|
||||
*etag_out = g_strdup (g_task_get_task_data (G_TASK (result)));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
16
gio/gfile.h
16
gio/gfile.h
@ -1251,6 +1251,22 @@ gboolean g_file_replace_contents_finish (GFile *file,
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_file_supports_thread_contexts (GFile *file);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_56
|
||||
GBytes *g_file_load_bytes (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
gchar **etag_out,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_2_56
|
||||
void g_file_load_bytes_async (GFile *file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_2_56
|
||||
GBytes *g_file_load_bytes_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
gchar **etag_out,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_FILE_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user